| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0.295 Tracking Error 0.197 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset |
# region imports
from AlgorithmImports import *
import datetime as dt
import ast
import json
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
from io import StringIO
import pandas as pd
# endregion
class AdaptableVioletJaguar(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2022, 1, 1) # Set Start Date
self.SetEndDate(2023, 2, 4)
self.SetCash(50000) # Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Daily
self.tickers = ["AAPL"]
self.AddUniverse(self.CoarseSelection, self.FineSelection)
self.symbolDataBySymbol = {}
self.fineFundamentals = {}
self.SAVE_EARNINGS = True
self.loaded_earnings = {}
if not self.SAVE_EARNINGS:
self.SetEndDate(2023, 2, 1)
earnings = json.loads(self.ObjectStore.Read("Earnings_dates"))
temp_earnings = dict(earnings)
for ticker, str_dates in earnings.items():
temp_earnings[ticker] = [dt.datetime.strptime(x, '%m/%d/%Y').date() for x in ast.literal_eval(str_dates)]
self.loaded_earnings = dict(temp_earnings)
self.Debug(temp_earnings)
del temp_earnings
del earnings
elif self.SAVE_EARNINGS and self.ObjectStore.ContainsKey("Earnings_dates"):
self.SetEndDate(2023, 2, 4)
self.ObjectStore.Delete("Earnings_dates")
self.spy = self.AddEquity("SPY", Resolution.Daily)
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen("SPY", -10),
self.CheckEarningsRules)
# Long Entry Criteria
# at least 30 days since the last earnings report
# over 30 days until the next earnings report
#
# Short Entry Criteria
# less than 10 days until the next earnings report
#
# Short Exit Criteria
# over 30 days since last earnings report
#
def CheckEarningsRules(self):
if self.SAVE_EARNINGS: return
cur_date = self.Time.date()
for symbol, symbolData in self.symbolDataBySymbol.items():
symbol_earnings = symbolData.earnings_dates
symbol_earnings_series = pd.Series(symbol_earnings)
insertion_index = symbol_earnings_series.searchsorted(cur_date) ## Result is the index at which it will exit in the next list
prev_earnings_date = symbol_earnings[insertion_index-1]
next_earnings_date = symbol_earnings[insertion_index] ## WHEN RUNNING ALGORITHM, MAKE SURE self.EndDate IS LESS THAN THE LAST EARNINGS VALUE
delta_prev = cur_date - prev_earnings_date
delta_next = next_earnings_date - cur_date
if delta_prev.days >= 30 and delta_next.days > 30:
symbolData.long_entry_earnings = True
else:
symbolData.long_entry_earnings = False
if delta_next.days < 10:
symbolData.short_entry_earnings = True
else:
symbolData.short_entry_earnings = False
if delta_prev.days >= 30:
symbolData.short_exit_earnings = True
else:
symbolData.short_exit_earnings = False
self.Debug(f"{insertion_index} {self.Time.date()} {symbol.Value} : long etr - {symbolData.long_entry_earnings}, short etr - {symbolData.short_entry_earnings}, short ext - {symbolData.short_exit_earnings}")
def OnData(self, data: Slice):
if self.SAVE_EARNINGS:
for symbol, symbolData in self.symbolDataBySymbol.items():
symbolData.update_earnings(self.fineFundamentals[symbol].EarningReports.FileDate)
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
if security.Symbol.Value == "SPY": continue
symbolData = SymbolData(self, security)
if not self.SAVE_EARNINGS:
symbolData.earnings_dates = self.loaded_earnings[security.Symbol.Value]
self.symbolDataBySymbol[security.Symbol] = symbolData
def CoarseSelection(self, coarse):
filteredCoarse = [x.Symbol for x in coarse if x.Symbol.Value in self.tickers and x.HasFundamentalData]
return filteredCoarse
def FineSelection(self, fine):
for x in fine:
self.fineFundamentals[x.Symbol] = x
return [x.Symbol for x in fine]
def OnEndOfAlgorithm(self):
if self.SAVE_EARNINGS:
earnings_dict = {}
for symbol, symbolData in self.symbolDataBySymbol.items():
self.Debug(f"{symbol.Value} : {symbolData.earnings_dates}")
string_earnings = [t.strftime('%m/%d/%Y') for t in symbolData.earnings_dates]
earnings_dict[str(symbol.Value)] = str(string_earnings)
dump = json.dumps(earnings_dict)
self.ObjectStore.Save("Earnings_dates", dump)
self.Debug(earnings_dict)
else:
for symbol, symbolData in self.symbolDataBySymbol.items():
self.Debug(symbolData.earnings_dates)
class SymbolData:
def __init__(self, algo, security):
self.algo = algo
self.security = security
self.symbol = security.Symbol
self.earnings_dates = []
self.long_entry_earnings = False
self.short_entry_earnings = False
self.short_exit_earnings = False
def update_earnings(self, date):
if date.date() not in self.earnings_dates:
self.earnings_dates.append(date.date())