| Overall Statistics |
|
Total Trades 146 Average Win 0.03% Average Loss -0.04% Compounding Annual Return -2.187% Drawdown 1.300% Expectancy -0.117 Net Profit -0.375% Sharpe Ratio -0.574 Probabilistic Sharpe Ratio 20.842% Loss Rate 54% Win Rate 46% Profit-Loss Ratio 0.90 Alpha -0.027 Beta 0.049 Annual Standard Deviation 0.026 Annual Variance 0.001 Information Ratio -2.485 Tracking Error 0.103 Treynor Ratio -0.306 Total Fees $146.00 Estimated Strategy Capacity $13000000.00 Lowest Capacity Asset SMID XJLTRYSI6U79 Portfolio Turnover 2.71% |
# region imports
from AlgorithmImports import *
# endregion
class EarningsContinuation(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 9, 12) # Set Start Date
self.SetEndDate(2021, 11, 12)
self.SetCash(100000) # Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
#self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw
self.entryTime = datetime.min
self.gaps= {}
self.strongclose = 0
self.openPositions ={}
self.finalfilter = []
self.longs = []
self.tickets = []
self.AddEquity("SPY", Resolution.Daily)
self.SetBenchmark("SPY")
self.Schedule.On(self.DateRules.EveryDay("SPY"),self.TimeRules.AfterMarketOpen("SPY", 5),self.EveryMarketOpen)
def CoarseSelectionFunction(self,coarse):
sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
byprice = [x for x in sortedByDollarVolume if x.DollarVolume > 1000000 and x.Price > 5 and x.HasFundamentalData]
byprice = [x.Symbol for x in byprice]
return byprice
def FineSelectionFunction(self,fine):
fineUniverse = []
yesterday = self.Time - timedelta(days=1)
for x in fine:
if x.EarningReports.FileDate == yesterday and x.MarketCap > 5e7:
self.Log(f'stock{x.Symbol.Value} has earnings on {x.EarningReports.FileDate}')
fineUniverse.append(x)
symbols = [x.Symbol for x in fineUniverse]
#if self.IsWarmingUp: return
price = self.History(symbols, timedelta(days=2), Resolution.Daily) # two days index - 0 is yesterday
#price = self.History(Tradebar, symbols, start_time = yesterday, end_time = self.Time, Resolution.Daily)
#dataNormalizationMode=DataNormalizationMode.Raw
#Strong earnings close, then buy the next day
#ex. ORCL 9/13/2021 reported earnings after the market closed
for sec in symbols:
try:
earningsdayopen = price.loc[sec]['open'][0]
earningsdayclose = price.loc[sec]['close'][0]
earningsdayhigh = price.loc[sec]['high'][0]
afterearningsopen = price.loc[sec]['open'][-1]
except:
self.Debug(f"History data unavailable for {sec}")
continue
closestrength= (earningsdayclose-earningsdayopen)/(earningsdayhigh-earningsdayopen)
percentGap = (afterearningsopen / earningsdayclose) - 1
if closestrength >=0.8 and percentGap > 0.01:
self.longs.append(sec)
self.Log(f"adding {sec} to long list with strength close{closestrength} and gap up of {percentGap}")
return self.longs
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
if security != 'SPY':
self.Log(f'about to trade {security}')
self.MarketOrder(security,10)
self.entryTime = self.Time
self.openPositions[security] = self.entryTime
def EveryMarketOpen(self):
for position in list(self.openPositions.keys()):
if self.openPositions[position] + timedelta(days=5) <= self.Time :
self.Liquidate(position.Symbol)
self.openPositions.pop(position)
else:
continue