Overall Statistics |
Total Trades 29 Average Win 7.00% Average Loss -0.62% Compounding Annual Return 99.504% Drawdown 15.700% Expectancy 9.606 Net Profit 113.568% Sharpe Ratio 3.352 Probabilistic Sharpe Ratio 95.052% Loss Rate 14% Win Rate 86% Profit-Loss Ratio 11.37 Alpha 0.78 Beta 0.092 Annual Standard Deviation 0.246 Annual Variance 0.06 Information Ratio 0.944 Tracking Error 0.376 Treynor Ratio 8.911 Total Fees $119.47 |
class QInOut(QCAlgorithm): def Initialize(self): # ------------------------------------------- Parameters --------------------------------------- # Entry minute for the Trade algo after MArket Open self.MinsAfterOpen = int(self.GetParameter("minsAfterOpen")) #Indicators' Days input self.SmaDays = int(self.GetParameter("smaDays")) self.MacdFastDays = int(self.GetParameter("macdFastDays")) self.MacdSlowDays = int(self.GetParameter("macdSlowDays")) self.MacdSignalDays = int(self.GetParameter("macdSignalDays")) self.RsiDays = int(self.GetParameter("rsiDays")) self.SmaLongDays = 30 # not in use ATM int(self.GetParameter("smaLongDays")) self.SmaShortDays = int(self.GetParameter("smaShortDays")) self.PpoSlowDays = int(self.GetParameter("ppoSlowDays")) self.PpoFastDays = int(self.GetParameter("ppoFastDays")) # Indicators gaps and factors self.RsiLowGap = int(self.GetParameter("rsiLow")) self.RsiHighGap = int(self.GetParameter("rsiHigh")) self.PpoGap = float(self.GetParameter("ppo")) self.SlopeGap = float(self.GetParameter("slope")) self.MompGap = 100 # not in use ATM float(self.GetParameter("momp")) self.MacdGap = float(self.GetParameter("macd")) self.MacdSignalGap = float(self.GetParameter("macdSignal")) # MACD factors self.MacdFactorOut = float(self.GetParameter("macdFactorOut")) self.MacdFactorIn = float(self.GetParameter("macdFactorIn")) self.MacdIn2Factor = float(self.GetParameter("macdIn2Factor")) # Trade time in minutes after market open self.MinDaysOut = int(self.GetParameter("daysOut")) # Debug Algo Input parameters #self.Debug(f"After Market Open. rsiLow:{self.RsiLowGap} rsiHigh:{self.RsiHighGap} ppo:{self.PpoGap} rsiDays:{self.RsiDays} smaLongDays:{self.SmaLongDays} smaShortDays:{self.SmaShortDays} ppoFastDays:{self.PpoFastDays} ppoSlowDays:{self.PpoSlowDays}") self.StartYear = int(self.GetParameter("startYear")) self.EndYear = int(self.GetParameter("endYear")) # For Back testing self.SetStartDate(self.StartYear,1,1) self.SetEndDate(self.EndYear,12,31) self.StartCash = 100000 self.SetCash(self.StartCash) self.SetWarmUp(timedelta(days=30)) # --------------------------------------- Internal variables ----------------------------------- #For Plots on Equity Graph self.InEquityHistory = [] # now used for QQQ self.OutEquityHistory = [] # now used to TLT self.FirstDay = True self.InEquity_RSI_DAY_BEFORE = 0 self.InEquity_PPO_DAY_BEFORE = 0 self.InEquity_BIG_SMA_WINDOW_DAY_BEFORE = 0 self.InEquity_SMA_WINDOW_DAY_BEFORE = 0 self.InEquity_SLOPE_DAY_BEFORE = 0 self.InEquity_MOMP_DAY_BEFORE = 0 self.InEquity_SMA_DAY_BEFORE = 0 self.InEquity_MACD_DAY_BEFORE = 0 self.InEquity_MACD_Signal_DAY_BEFORE = 0 self.TickerTable = {} self.MyInOutIndicator = 1 # Default Enter the Market self.DaysOut = 0 # Cooldown days after exiting the Market self.TotalDays =0 # Counter for total days self.TotalDaysIn = 0 # Counter for days in the MArket self.Indicator_history = [] self.IndicatorRatio = 0 # ---------------------------------------- Defining Tickers and collection Indicators --------------------------- self.SetBenchmark("QQQ") self.OutEquity="TLT" # Out of market portfolio. Divide Cash among list (TLT VXX VIXY) self.InEquity ="QQQ" # In market asset (QQQ QQEW) self.VXX = self.AddEquity("VXX", Resolution.Daily).Symbol self.tickers = ["QQQ","TLT"] # ,"FDN","SPY","ARKK","SQQQ","GLD","PSQ","SH","EMTY", "XLU","XLP","TBT","IEF", "FDN","TLH"] for ticker in self.tickers: # --------- Add Equity self.AddEquity(ticker, Resolution.Daily) # --------- Add Equity indicators rsi = self.RSI(ticker, self.RsiDays, Resolution.Daily) smaLong = self.SMA(ticker, self.SmaLongDays, Resolution.Daily) smaShort = self.SMA(ticker, self.SmaShortDays, Resolution.Daily) rcShort = self.RC(ticker,self.SmaShortDays, Resolution.Daily) ppo = self.PPO(ticker, self.PpoFastDays, self.PpoSlowDays, MovingAverageType.Simple, Resolution.Daily) momp = self.MOMP(ticker, 28, Resolution.Daily) sma = self.SMA(ticker, self.SmaDays, Resolution.Daily) ema = self.EMA(ticker, self.SmaDays, Resolution.Daily) macd = self.MACD(ticker, self.MacdFastDays,self.MacdSlowDays,self.MacdSignalDays,MovingAverageType.Exponential, Resolution.Daily) symbolData = SymbolData(ticker, rsi, smaLong, smaShort, rcShort, ppo, momp, sma, ema, macd) self.TickerTable[ticker] = symbolData # --------------------------------------------------- Schedules -------------------------------------------- self.Schedule.On(self.DateRules.EveryDay(self.InEquity),self.TimeRules.AfterMarketOpen(self.InEquity,self.MinsAfterOpen), self.Trade) # ------------------------------------------------- On Data ----------------------------------------------------- def OnData(self, data): pass # --------------------------------------------------------------------------------------------------------------- # ---------------------------------------------- Trade Function ------------------------------------------------- # --------------------------------------------------------------------------------------------------------------- def Trade(self): self.TotalDays +=1 self.CollectIndicatorsAndTrends() self.DecideInOrOut() if self.MyInOutIndicator == 1: self.TotalDaysIn +=1 if not self.Securities[self.InEquity].Invested: self.SetHoldings(self.InEquity, 1.00, True,f"PPO:{self.InEquity_PPO} SLOPE:{self.InEquity_SLOPE} RSI:{self.InEquity_RSI}") self.Notify.Sms("+972542224488", self.InEquity +" In:" + str(self.Securities[self.InEquity].Price)) else: if not self.Securities[self.OutEquity].Invested: self.SetHoldings(self.OutEquity, 1.00, True,f"PPO:{self.InEquity_PPO} SLOPE:{self.InEquity_SLOPE} RSI:{self.InEquity_RSI}") self.Notify.Sms("+972542224488", self.InEquity + " Out:" + str(self.Securities[self.InEquity].Price)) self.AfterTradeUpdate() self.PlotIt() # -------------------------------- Decide IN or OUT ---------------------------------------- def GoldenCross(self): if self.InEquity_MACD > self.InEquity_MACD_Signal * self.MacdFactorIn and self.InEquity_MACD_DAY_BEFORE - self.MacdIn2Factor < self.InEquity_MACD: return True else: return False def DeathCross(self): if self.InEquity_MACD < self.InEquity_MACD_Signal * self.MacdFactorOut and self.InEquity_MACD > self.InEquity_MACD_DAY_BEFORE: return True else: return False def DecideInOrOut(self): #if self.InEquity_SLOPE < self.SlopeGap or self.InEquity_PPO <= self.PpoGap or self.InEquity_RSI < self.RsiLowGap: #if ((self.InEquity_MACD < (self.InEquity_MACD_Signal * self.MacdFactorOut) and self.InEquity_MACD < self.InEquity_MACD_DAY_BEFORE-0.2) #or self.InEquity_PPO <= self.PpoGap #or self.InEquity_RSI < self.RsiLowGap): #try: # temp = (self.InEquity_RSI_DAY_BEFORE - self.InEquity_RSI)/ self.InEquity_RSI_DAY_BEFORE #except: # temp = 0 #if self.DeathCross(): # or temp > 0.1:#self.RsiLowGap: # Should we go OUT ? if self.InEquity_PPO< self.PpoGap or self.InEquity_RSI < self.RsiLowGap or self.InEquity_SLOPE < self.SlopeGap: self.MyInOutIndicator = 0 self.DaysOut = 0 # Zero the DaysOut counter # Should we get IN? elif True: #self.GoldenCross(): if self.DaysOut >= self.MinDaysOut: self.MyInOutIndicator = 1 self.DaysOut = 0 else: self.DaysOut +=1 # ---- Unless in Market out Cooldown else: if self.MyInOutIndicator == 0: self.DaysOut +=1 # ------------------------- Collect Indicators and trends before Trade --------------------------------- def CollectIndicatorsAndTrends(self): if not self.FirstDay: self.InEquity_RSI_DAY_BEFORE = self.InEquity_RSI self.InEquity_PPO_DAY_BEFORE = self.InEquity_PPO self.InEquity_BIG_SMA_WINDOW_DAY_BEFORE = self.InEquity_BIG_SMA_WINDOW self.InEquity_SMA_WINDOW_DAY_BEFORE = self.InEquity_SMALL_SMA_WINDOW self.InEquity_SLOPE_DAY_BEFORE = self.InEquity_SLOPE self.InEquity_MOMP_DAY_BEFORE = self.InEquity_MOMP self.InEquity_SMA_DAY_BEFORE = self.InEquity_SMA self.InEquity_MACD_DAY_BEFORE = self.InEquity_MACD self.InEquity_MACD_Signal_DAY_BEFORE = self.InEquity_MACD_Signal self.InEquity_RSI = self.TickerTable[self.InEquity].Rsi.Current.Value self.InEquity_PPO = self.TickerTable[self.InEquity].Ppo.Current.Value self.InEquity_BIG_SMA_WINDOW = self.TickerTable[self.InEquity].SmaLong.Current.Value self.InEquity_SMALL_SMA_WINDOW = self.TickerTable[self.InEquity].SmaShort.Current.Value self.InEquity_SLOPE = self.TickerTable[self.InEquity].RcShort.Slope.Current.Value self.InEquity_MOMP = self.TickerTable[self.InEquity].Momp.Current.Value self.InEquity_SMA = self.TickerTable[self.InEquity].Sma.Current.Value self.InEquity_EMA = self.TickerTable[self.InEquity].Ema.Current.Value self.InEquity_MACD = self.TickerTable[self.InEquity].Macd.Current.Value self.InEquity_MACD_Signal = self.TickerTable[self.InEquity].Macd.Signal.Current.Value self.FirstDay = False #self.Debug(f"{self.Time} PPO:{round(self.InEquity_PPO,2)} Slope:{round(self.InEquity_SLOPE,2)} RSI:{round(self.InEquity_RSI,2)} BIG_SMA_WINDOW:{round(self.InEquity_BIG_SMA_WINDOW,2)} SMALL_SMA_WINDOW:{round(self.InEquity_SMALL_SMA_WINDOW,2)}") #self.Debug(f"{self.Time} Slope:{round(self.InEquity_SLOPE,2)} RSI:{round(self.InEquity_RSI,2)}") # ------------------------------------ After Trade updates --------------------------------------------- def AfterTradeUpdate(self): self.InEquity_RSI_DAY_BEFORE = self.InEquity_RSI self.InEquity_PPO_DAY_BEFORE = self.InEquity_PPO self.InEquity_BIG_SMA_WINDOW_DAY_BEFORE = self.InEquity_BIG_SMA_WINDOW self.InEquity_SMA_WINDOW_DAY_BEFORE = self.InEquity_SMALL_SMA_WINDOW self.InEquity_SLOPE_DAY_BEFORE = self.InEquity_SLOPE self.InEquity_MOMP_DAY_BEFORE = self.InEquity_MOMP self.InEquity_SMA_DAY_BEFORE = self.InEquity_SMA self.InEquity_MACD_DAY_BEFORE = self.InEquity_MACD self.InEquity_MACD_Signal_DAY_BEFORE = self.InEquity_MACD_Signal self.Indicator_history.append(self.MyInOutIndicator) self.Indicator_history_changes = [x1 - x2 for x1, x2 in zip(self.Indicator_history[1:], self.Indicator_history)][-15:] try: self.IndicatorRatio = 1.0000 * (len([x for x in self.Indicator_history_changes if x != 0])/ len(self.Indicator_history_changes)) #if self.IndicatorRatio > 0: # self.Debug(str(self.Time) + str(self.IndicatorRatio)) except: self.Debug("START !!") # -------------------------------------------- Plot Function ------------------------------------------------ def PlotIt(self): self.Plot("In/Out Indicator","InOut",self.MyInOutIndicator) self.Plot("RSI","RSI",self.InEquity_RSI) self.Plot("PPO","PPO",self.InEquity_PPO) self.Plot("Slope","SLOPE",self.InEquity_SLOPE) #self.Plot("Momp","MOMP", self.InEquity_MOMP) self.Plot("MACD","Value",self.InEquity_MACD) self.Plot("MACD","Signal",self.InEquity_MACD_Signal) try: self.Plot("VXX","TLT",self.Securities[self.VXX.Value].Price) except: pass # Benchmark Ploting hist = self.History([self.InEquity], 2, Resolution.Daily)['close'].unstack(level= 0).dropna() self.InEquityHistory.append(hist[self.InEquity].iloc[-1]) perf = self.InEquityHistory[-1] / self.InEquityHistory[0] * self.StartCash self.Plot("Strategy Equity", self.InEquity, perf) hist = self.History([self.OutEquity], 2, Resolution.Daily)['close'].unstack(level= 0).dropna() self.OutEquityHistory.append(hist[self.OutEquity].iloc[-1]) perf = self.OutEquityHistory[-1] / self.OutEquityHistory[0] * self.StartCash self.Plot("Strategy Equity", self.OutEquity, perf) # ----------------------------------------------- End of Algo --------------------------------------------------- def OnEndOfAlgorithm(self): self.Liquidate() if self.TotalDays>0: self.Debug(f"TPV:{round(self.Portfolio.TotalPortfolioValue,2)} Total Days:{self.TotalDays} Total Days In:{self.TotalDaysIn} {round(self.TotalDaysIn/self.TotalDays*100,2)}%") # ---------------------------------------------- SymbolData -------------------------------------------------- class SymbolData: def __init__(self, symbol, rsi, smaLong, smaShort, rcShort, ppo, momp, sma, ema, macd): self.Symbol = symbol self.Rsi = rsi self.SmaLong = smaLong self.SmaShort = smaShort self.RcShort = rcShort self.Ppo = ppo self.Momp = momp self.Sma = sma self.Ema = ema self.Macd = macd