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.95 Tracking Error 0.121 Treynor Ratio 0 Total Fees $0.00 |
class UniverseSelection(QCAlgorithm): def Initialize(self): self.SetStartDate(2021, 1, 1) # Set Start Date #self.SetEndDate(2021, 1, 5) # Set End Date self.SetCash(100000) # Set Strategy Cash self.UniverseSettings.Resolution = Resolution.Minute self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction) self.SPY = self.AddEquity('SPY', Resolution.Minute).Symbol self.day = -1 self.num_coarse = 20 self.min_days_after_earnings = 10 self.max_days_after_earnings = 80 self.ema_period = 8 # 5 min timeframe self.sma_period = 55 # 5 min timeframe self.bb_period = 20 # 30 min timeframe self.bb_k = 2 self.gap_distance = 0.02 # 2% self.data = {} self.selected = [] self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen(self.SPY, 30), self.Selection) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen(self.SPY, 1), self.AtMarketOpen) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose(self.SPY, 1), self.BeforeMarketCloses) def CoarseSelectionFunction(self, coarse): if self.day == self.Time.day: return Universe.Unchanged self.day = self.Time.day # drop stocks which have no fundamental data or have too low prices selected = [x for x in coarse if (x.HasFundamentalData) and (float(x.Price) > 5)] # rank the stocks by dollar volume filtered = sorted(selected, key=lambda x: x.DollarVolume, reverse=True) return [ x.Symbol for x in filtered[:self.num_coarse]] def FineSelectionFunction(self, fine): filtered = [x for x in fine if x.SecurityReference.IsPrimaryShare and x.SecurityReference.SecurityType == "ST00000001" and x.SecurityReference.IsDepositaryReceipt == 0 and x.CompanyReference.IsLimitedPartnership == 0 and x.EarningReports.FileDate < self.Time - timedelta(days=self.min_days_after_earnings) and x.EarningReports.FileDate > self.Time - timedelta(days=self.max_days_after_earnings)] return [x.Symbol for x in filtered] def Selection(self): for symbol in self.data.keys(): if self.data[symbol].GapUp and self.data[symbol].EMA > self.data[symbol].SMA and self.data[symbol].BB.UpperBand.Current.Value < self.Securities[symbol].Close: self.selected.append(symbol) #self.Debug(str(symbol)) def OnSecuritiesChanged(self, changes): for security in changes.RemovedSecurities: symbol_data = self.data.pop(security.Symbol, None) if symbol_data: symbol_data.dispose() for security in changes.AddedSecurities: if security.Symbol not in self.data: self.data[security.Symbol] = SymbolData(security.Symbol, self.ema_period, self.sma_period, self.bb_period, self.bb_k, self) def AtMarketOpen(self): for symbol in self.data.keys(): if self.data[symbol].LastClose == 0: self.data[symbol].GapUp = False continue gap = (self.Securities[symbol].Close - self.data[symbol].LastClose) / self.data[symbol].LastClose if gap > self.gap_distance: self.data[symbol].GapUp = True else: self.data[symbol].GapUp = False def BeforeMarketCloses(self): for symbol in self.data.keys(): self.data[symbol].LastClose = self.Securities[symbol].Close class SymbolData(object): def __init__(self, symbol, ema, sma, bb, k, algorithm): self.Symbol = symbol self.LastClose = 0 self.GapUp = False self.EMA = ExponentialMovingAverage(ema) self.SMA = SimpleMovingAverage(sma) self.BB = BollingerBands(bb, k, MovingAverageType.Exponential) self.algorithm = algorithm self.consolidator_5min = TradeBarConsolidator(timedelta(minutes=5)) self.consolidator_30min = TradeBarConsolidator(timedelta(minutes=30)) algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator_5min) algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator_30min) algorithm.RegisterIndicator(symbol, self.EMA, self.consolidator_5min) algorithm.RegisterIndicator(symbol, self.SMA, self.consolidator_5min) algorithm.RegisterIndicator(symbol, self.BB, self.consolidator_30min) # Warm up indicators history = algorithm.History(symbol, 1, Resolution.Daily) if history.empty or 'close' not in history.columns: return for index, row in history.loc[symbol].iterrows(): self.LastClose = row['close'] #history = algorithm.History(symbol, max(ema*5, sma*5, bb*30), Resolution.Minute) #if history.empty or 'close' not in history.columns: # return #for index, row in history.loc[symbol].iterrows(): # tradeBar = TradeBar() # tradeBar.Close = row['close'] # tradeBar.Open = row['open'] # tradeBar.High = row['high'] # tradeBar.Low = row['low'] # tradeBar.Volume = row['volume'] # tradeBar.Time = index # self.consolidator_5min.Update(tradeBar) # self.consolidator_30min.Update(tradeBar) def dispose(self): self.algorithm.SubscriptionManager.RemoveConsolidator(self.Symbol, self.consolidator_5min) self.algorithm.SubscriptionManager.RemoveConsolidator(self.Symbol, self.consolidator_30min)