Overall Statistics |
Total Trades 12 Average Win 0.27% Average Loss -0.13% Compounding Annual Return 19.023% Drawdown 1.100% Expectancy 0.231 Net Profit 0.143% Sharpe Ratio 3.55 Probabilistic Sharpe Ratio 0% Loss Rate 60% Win Rate 40% Profit-Loss Ratio 2.08 Alpha 0.424 Beta -1.26 Annual Standard Deviation 0.036 Annual Variance 0.001 Information Ratio -2.244 Tracking Error 0.047 Treynor Ratio -0.102 Total Fees $12.00 Estimated Strategy Capacity $15000000.00 Lowest Capacity Asset OSH XGSEQC44B4O5 |
''' Gap and Go Strategy Shorts stocks gapping down >2% 1/1 Risk-to-Reward -change the support levels from close to low? ''' class MeasuredRedSalmon(QCAlgorithm): success_count = 1 loss_count = 1 success_countt = 1 loss_countt = 1 def Initialize(self): self.SetStartDate(2021, 5, 25) # Set Start Date self.SetEndDate(2021, 5,27) self.SetCash(50000) # Set Strategy Cash self.spy = self.AddEquity("SPY", Resolution.Minute, Market.USA, True, 1.0, True) self.UniverseSettings.Resolution = Resolution.Second self.UniverseSettings.ExtendedMarketHours = True self.AddUniverse(self.Coarse, self.Fine) self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.05)) self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 0), self.collectPreMarketData) self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 0), self.prevspyclose) self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 1), self.trackMarket) self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 90), self.endMarket) self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 100), self.LiquidatePositions) self.isMarket = False self.spyisred = False self.lastPrePrice = -1 self.yesterday = -1 self.isGapped = False self.maxTraded = 4 self.securityWeight = .2 self.lastMonth = -1 self.activeSecurities = {} self.todaysSecurities = {} self.tradedToday = [] self.tradingSecurities = {} self.oneMinuteHigh = {} self.quarterPositions = {} self.oneMinuteLow = {} self.lastMinute = {} self.prevoneminutelow = {} self.prevoneminutehigh = {} self.SetWarmUp(timedelta(days = 2)) def endMarket(self): remove =[] self.isMarket = False self.tradedToday = [] for symbol, symbolData in self.todaysSecurities.items(): remove.append(symbol) for symbol in remove: self.todaysSecurities.pop(symbol, None) self.tradingSecurities.pop(symbol, None) self.Liquidate(symbol, "End of Trading") self.RemoveSecurity(symbol) self.oneMinuteHigh self.oneMinuteLow self.lastMinute def collectPreMarketData(self): remove = [] for symbol, symbolData in self.activeSecurities.items(): symbolData.Open = self.Securities[symbol].Price symbolData.Logged = False historyMinute = self.History(symbol, 300, Resolution.Minute) historyDay = self.History(symbol, 1, Resolution.Daily) if symbol.Value == 'JWN': self.Log("JWN in activeSecurities") try: symbolData.YesterdayClose = float(historyDay["close"]) except: remove.append(symbol) continue preMarketLow = 100000 resistance1 = 1 resistance2 = 1 resistance3 = 1 counter = 0 for tuple in historyMinute.itertuples(): symbolData.premarketavg.Update(tuple.Index[1], tuple.volume) symbolData.premarketstd.Update(tuple.Index[1], tuple.volume) symbolData.currentpremarketavg.Update(tuple.Index[1], tuple.volume) symbolData.sum = symbolData.sum + tuple.volume if tuple.close < preMarketLow: if tuple.open < tuple.close: preMarketLow = tuple.open else: preMarketLow = tuple.close if tuple.close > resistance1: if tuple.open > tuple.close: resistance1 = tuple.open else: resistance1 = tuple.close if counter >= 100: if tuple.close > resistance2: if tuple.open > tuple.close: resistance2 = tuple.open else: resistance2 = tuple.close if counter >= 240: if tuple.close > resistance3: if tuple.open > tuple.close: resistance3 = tuple.open else: resistance3 = tuple.close counter += 1 if resistance1 <= resistance2 and resistance1 <= resistance3: lowest_resistance = resistance1 if resistance2 <= resistance3: mid_resistance = resistance2 high_resistance = resistance3 else: mid_resistance = resistance3 high_resistance = resistance2 if resistance2 < resistance1 and resistance2 <= resistance3: lowest_resistance = resistance2 if resistance1 <= resistance3: mid_resistance = resistance1 high_resistance = resistance3 else: mid_resistance = resistance3 high_resistance = resistance1 if resistance3 < resistance1 and resistance3 < resistance2: lowest_resistance = resistance3 if resistance1 <= resistance2: mid_resistance = resistance1 high_resistance = resistance3 else: mid_resistance= resistance3 high_resistance = resistance1 symbolData.resistance1 = round(lowest_resistance, 1) symbolData.resistance2 = round(mid_resistance, 1) symbolData.resistance3 = round(high_resistance, 1) symbolData.firstresistanceBroke = False symbolData.secondresistanceBroke = False symbolData.thirdresistanceBroke = False symbolData.AlreadyBrokeOut = False symbolData.preMarketLow = preMarketLow if symbolData.Open <= symbolData.YesterdayClose*0.98: symbolData.isGap = True else: symbolData.isGap = False symbolData.isGapPercent = (symbolData.YesterdayClose - symbolData.Open) / symbolData.YesterdayClose symbolData.RVOL = symbolData.currentpremarketavg.Current.Value/(symbolData.premarketstd.Current.Value + symbolData.premarketavg.Current.Value + 0.01) for symbol in remove: self.activeSecurities.pop(symbol, None) self.Liquidate(symbol, "End of Trading") self.RemoveSecurity(symbol) def trackMarket(self): for symbol, symbolData in self.activeSecurities.items(): if symbolData.RVOL > 1 and symbolData.sum >= 50000: if symbol.Value == 'JWN': self.Log("JWN in todaysSecurities") self.todaysSecurities[symbol] = self.activeSecurities[symbol] sortedByGap = [x for x in self.todaysSecurities.keys()] gapPercentBySymbol = {x.Symbol:x.isGapPercent for x in self.todaysSecurities.values()} sortedByGap = sorted(sortedByGap, key = lambda x: self.todaysSecurities[x].isGapPercent, reverse = True) finalGap = sortedByGap[:self.maxTraded] for symbol in finalGap: if symbol.Value == 'JWN': self.Log("JWN in FinalGap") self.tradingSecurities[symbol] = self.todaysSecurities[symbol] # self.oneMinuteHigh[symbol] = self.Securities[symbol].High # self.oneMinuteLow[symbol] = self.Securities[symbol].Low for symbol, symbolData in self.tradingSecurities.items(): if symbol.Value == 'JWN': self.Log("JWN in tradingSecurities") self.isMarket = True def LiquidatePositions(self): self.spyisred = False self.Liquidate() def prevspyclose(self): History = self.History(self.spy.Symbol, 1, Resolution.Daily) Close = float(History["close"]) if self.Securities[self.spy.Symbol].Price <= Close: self.spyisred = True def OnData(self, data): if self.isMarket == True: # removed = [] # for symbol in removed: # self.tradingSecurities.pop(symbol, None) # self.Liquidate(symbol) # self.RemoveSecurity(symbol) for symbol, symbolData in self.tradingSecurities.items(): if symbolData.isGap == True: if symbol.Value == 'JWN': self.Log("JWN in tradingSecurities OnData") if len([x for x in self.Portfolio if x.Value.Invested]) >= self.maxTraded: break if symbolData.Logged == False: self.Log(str(symbol) + "tradingSecurities with gap") self.Log(str(symbol) + "resistance1 = " + str(symbolData.resistance1)) self.Log(str(symbol) + "preMarketLow = " + str(symbolData.preMarketLow)) symbolData.Logged = True # if symbolData.lastMinute == self.Time.minute: # if symbolData.oneMinuteLow > self.Securities[symbol].Low: # symbolData.oneMinuteLow = self.Securities[symbol].Low # if symbolData.oneMinuteHigh < self.Securities[symbol].High: # symbolData.oneMinuteHigh = self.Securities[symbol].High # # elif symbolData.prevoneminutelow == symbolData.oneMinuteLow: # symbolData.prevoneminutelow = self.Securities[symbol].Low # symbolData.prevoneminutehigh = self.Securities[symbol].High # symbolData.lastMinute = self.Time.minute # # else: # symbolData.prevoneminutelow = symbolData.oneMinuteLow # symbolData.prevoneminutehigh = symbolData.oneMinuteHigh # symbolData.oneMinuteLow = self.Securities[symbol].Low # symbolData.oneMinuteHigh = self.Securities[symbol].High # symbolData.lastMinute = self.Time.minute if self.Portfolio[symbol].Invested: if symbolData.AlreadyBrokeOut == False and self.Securities[symbol].Price <= symbolData.preMarketLow: self.SetHoldings([PortfolioTarget(symbol, -self.securityWeight)]) symbolData.AlreadyBrokeOut = True # self.Log(str(symbol) + "resistance1 = " + str(symbolData.resistance1)) # self.Log(str(symbol) + "preMarketLow = " + str(symbolData.preMarketLow)) if not self.Portfolio[symbol].Invested and symbol not in self.tradedToday: if self.Securities[symbol].Price >= symbolData.resistance1: symbolData.firstresistanceBroke = True if self.Securities[symbol].Price >= symbolData.preMarketLow: symbolData.secondresistanceBroke = True if symbolData.firstresistanceBroke == True and self.Securities[symbol].Price <= symbolData.resistance1: self.SetHoldings([PortfolioTarget(symbol, -self.securityWeight/2)]) self.tradedToday.append(symbol) # self.Log(str(symbol) + "resistance1 = " + str(symbolData.resistance3)) # self.Log(str(symbol) + "preMarketLow = " + str(symbolData.preMarketLow)) if symbolData.secondresistanceBroke == True and self.Securities[symbol].Price <= symbolData.preMarketLow: self.SetHoldings([PortfolioTarget(symbol, -self.securityWeight/2)]) self.tradedToday.append(symbol) symbolData.AlreadyBrokeOut = True self.Log(str(symbol) + " just traded") # self.Log(str(symbol) + "resistance1 = " + str(symbolData.resistance1)) # self.Log(str(symbol) + "preMarketLow = " + str(symbolData.preMarketLow)) # if symbol in self.quarterPositions: # self.quarterPositions.pop(symbol, None) continue # if symbol not in self.quarterPositions: # self.quarterPositions[symbol] = self.securityWeight/4 # else: # self.quarterPositions[symbol] += self.securityWeight/4 # # if self.quarterPositions[symbol] >=1: # continue self.manageProfit() def manageProfit(self): investedSecurities = [x.Key for x in self.Portfolio if x.Value.Invested] for symbol, symbolData in self.tradingSecurities.items(): if symbol.Value == 'JWN': self.Log("JWN in manageprofit") symbolData.takeprofit = (symbolData.resistance1 - symbolData.preMarketLow) if self.Portfolio[symbol].Invested and symbolData.AlreadyBrokeOut == False and (self.Securities[symbol].Price <= (symbolData.resistance1 - symbolData.takeprofit)): self.Liquidate(symbol, "PROFIT for resistance") # self.Log("resistance success count = " + str(self.success_count)) # self.success_count = self.success_count + 1 elif self.Portfolio[symbol].Invested and symbolData.AlreadyBrokeOut == False and self.Securities[symbol].Price >= (symbolData.resistance1 + symbolData.takeprofit): self.Liquidate(symbol, "Hit resistance Stop") self.Log("resistance loss count = " + str(self.loss_count)) self.loss_count = self.loss_count + 1 continue if self.Portfolio[symbol].Invested and symbolData.AlreadyBrokeOut == True and self.Securities[symbol].Price <= (symbolData.preMarketLow - symbolData.takeprofit): self.Liquidate(symbol, "PROFIT for Breakout") # self.Log("PMH success count = " + str(self.success_countt)) # self.success_countt = self.success_countt + 1 elif self.Portfolio[symbol].Invested and symbolData.AlreadyBrokeOut == True and self.Securities[symbol].Price >= (symbolData.preMarketLow + symbolData.takeprofit): self.Liquidate(symbol, "Hit Breakout resistance") # self.Log("PMH loss count = " + str(self.loss_countt)) # self.loss_countt = self.loss_countt + 1 def OnSecuritiesChanged(self, changes): addedSecurities = [x.Symbol for x in changes.AddedSecurities] removedSecurities = [x.Symbol for x in changes.RemovedSecurities] for symbol in addedSecurities: if symbol == self.spy.Symbol: continue sma = SimpleMovingAverage(960) std = StandardDeviation(960) currentavg = SimpleMovingAverage(120) history = self.History(symbol, 6720, Resolution.Minute) for tuple in history.itertuples(): CurrentHour = int(str(tuple.Index[1])[11:13]) if CurrentHour > 6 and CurrentHour < 9: sma.Update(tuple.Index[1], tuple.volume) std.Update(tuple.Index[1], tuple.volume) currentavg.Update(tuple.Index[1], tuple.volume) symbolData = SymbolData(symbol, sma, std, currentavg) self.activeSecurities[symbol] = symbolData for symbol in removedSecurities: if symbol in self.tradingSecurities: self.tradingSecurities.pop(symbol, None) if self.Portfolio[symbol].Invested: self.Liquidate(symbol, "Removed from Trading Securities") def Coarse(self, coarse): if self.lastMonth == self.Time.month: return Universe.Unchanged self.lastMonth = self.Time.month selectedCoarse = [x for x in coarse if x.HasFundamentalData and x.Price > 30 and x.Volume > 1000000] self.dollarVolumeBySymbol = {x.Symbol:x.Volume for x in selectedCoarse} # If no security has met the QC500 criteria, the universe is unchanged. # A new selection will be attempted on the next trading day as self.lastMonth is not updated if len(self.dollarVolumeBySymbol) == 0: return Universe.Unchanged return [x.Symbol for x in selectedCoarse] def Fine(self, fine): hist = self.History([i.Symbol for i in fine], 1, Resolution.Daily) sortedByVolume = sorted([x.Symbol for x in fine if x.CompanyReference.CountryId == "USA" and x.CompanyReference.PrimaryExchangeID in ["NYS","NAS"] and float(x.EarningReports.BasicAverageShares.ThreeMonths) * hist.loc[str(x.Symbol)]['close'][0] > 1e9], key = lambda x: self.dollarVolumeBySymbol[x], reverse=True) count = len(sortedByVolume) if count == 0: return Universe.Unchanged return sortedByVolume[:400] class SymbolData: def __init__(self, symbol, sma, std, currentavg): self.Open = -1 self.YesterdayClose = -1 self.preMarketLow = 10000 self.isGap = False self.RVOL = 0 self.Symbol = symbol self.isGapPercent = 0.0 self.resistance1 = 1 self.resistance2 = 1 self.resistance3 = 1 self.firstresistanceBroke = False self.secondresistanceBroke = False self.thirdresistanceBroke = False self.AlreadyBrokeOut = False self.premarketavg = sma self.premarketstd = std self.currentpremarketavg = currentavg self.lastMinute = 30 self.prevoneminutelow = 0 self.prevoneminutehigh = 0 self.oneMinuteLow = 0 self.oneMinuteHigh = 0 self.takeprofit = 0 self.Logged = False self.sum = 0