Overall Statistics
Total Trades
786
Average Win
0.36%
Average Loss
-0.27%
Compounding Annual Return
24.371%
Drawdown
7.600%
Expectancy
0.451
Net Profit
60.711%
Sharpe Ratio
1.685
Probabilistic Sharpe Ratio
86.353%
Loss Rate
38%
Win Rate
62%
Profit-Loss Ratio
1.35
Alpha
0.139
Beta
0.163
Annual Standard Deviation
0.1
Annual Variance
0.01
Information Ratio
-0.069
Tracking Error
0.196
Treynor Ratio
1.034
Total Fees
$0.00
Estimated Strategy Capacity
$130000.00
Lowest Capacity Asset
DDOG X7ZCS8BRO6ZP
from datetime import date, timedelta

class EarningsDatesStocks(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 1, 1)
        self.SetCash(2500)
        self.AddUniverse(self.CoarseSelectionFilter, self.FineSelectionFunction)
        self.UniverseSettings.Leverage = 1
        self.UniverseSettings.Resolution = Resolution.Daily
        self.SetSecurityInitializer(lambda x: x.SetFeeModel(CustomFeeModel()))
        self._changes = None
        self._symbolsInvested = {}
        self._openTrade = 5
        self._levStock = 5
        self._closeTrade = 10
        self._removeKeys  = list()
        self.AddEquity("SPY")
        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen("SPY", 100), Action(self.LiquidateSymbols))
        
    def CoarseSelectionFilter(self, coarse):
        sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
        filteredByPrice = [c.Symbol for c in sortedByDollarVolume if c.Price > 10 and c.Price < 100]
        return filteredByPrice
        
    def FineSelectionFunction(self, fine):
        hist = self.History([i.Symbol for i in fine], 1, Resolution.Daily)
        earnings_fine = [x for x in fine if self.Time > x.EarningReports.FileDate + timedelta(days=self._openTrade) 
                                and x.EarningReports.FileDate != date.today()]

        marketcap_fine = [x for x in earnings_fine if (x.ValuationRatios.EVToEBITDA > 0) 
                                                and (x.EarningReports.BasicAverageShares.ThreeMonths > 0) 
                                                and float(x.EarningReports.BasicAverageShares.ThreeMonths) * hist.loc[str(x.Symbol)]['close'][0] > 1e9]

        selected_fine = sorted(marketcap_fine, key = lambda x: x.ValuationRatios.EVToEBITDA, reverse=True)
        return [i.Symbol for i in selected_fine[:100]] #[:int(100/self._levStock)]
        
    def OnData(self, data):
        for month in [1,4,7,10]:
            if int(self.Time.month) == int(month):
                if self._changes is None: return
                for security in self._changes.AddedSecurities: #[:int(100/self._levStock)]
                    try:
                        orderStocks = round(((self.Portfolio.TotalPortfolioValue / 100) * self._levStock) \
                                / self.Securities[str(security)].Price)
                        #if self.Portfolio.UnsettledCash < 500: return
                        if self.Securities[str(security)].Invested: return
                        #self.Debug(str(security))
                        self.MarketOrder(str(security), orderStocks)
                        self._symbolsInvested[str(security)] = [(self.Time + timedelta(self._closeTrade))]
                    except:
                        pass
                for security in self._changes.RemovedSecurities:
                    pass
                self._changes = None

    def OnSecuritiesChanged(self, changes):
        self._changes = changes
        self.Log(f"OnSecuritiesChanged({self.UtcTime}):: {changes}")
        
    def LiquidateSymbols(self):
        for key,value in list(self._symbolsInvested.items()):
            #self.Debug(str(value[0].date()) +' '+ str(self.Time.date()))
            if value[0].date() <= self.Time.date():
                try:
                    self.Liquidate(key)
                    self._symbolsInvested.pop(key, None)
                except:
                    pass
                
class CustomFeeModel:
    def GetOrderFee(self, parameters):
        return OrderFee(CashAmount(0, 'USD'))