| 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