Overall Statistics
Total Trades
117
Average Win
5.39%
Average Loss
-1.29%
Compounding Annual Return
39.523%
Drawdown
12.600%
Expectancy
2.293
Net Profit
445.883%
Sharpe Ratio
1.959
Probabilistic Sharpe Ratio
95.753%
Loss Rate
36%
Win Rate
64%
Profit-Loss Ratio
4.16
Alpha
0.223
Beta
0.505
Annual Standard Deviation
0.171
Annual Variance
0.029
Information Ratio
0.666
Tracking Error
0.17
Treynor Ratio
0.663
Total Fees
$764.64
class OnInOut(QCAlgorithm):

    def Initialize(self):
        
        self.MinsAfterOpen = int(self.GetParameter("minsAfterOpen"))
        
        # Indicators
        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"))
        
        #Indicators' 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"))
      
        # used with the SMA indicator. Not used ATM.
        self.Factor = float(self.GetParameter("factor"))
      
        self.StartYear = int(self.GetParameter("startYear"))
        self.EndYear = int(self.GetParameter("endYear"))
        
        # Trade time in minutes after market open
        self.MinDaysOut = int(self.GetParameter("daysOut"))
        
        self.OutEquity="TLT" #,"VXX"]                # Out of market portfolio. Divide Cash among list
        self.InEquity ="QQQ"                        # In market asset
        
        #For Plots on Equity Graph
        self.InEquityHistory = []                   # now used for QQQ
        self.OutEquityHistory = []                  # now used to TLT
       
        self.SetStartDate(self.StartYear, 1, 1)
        self.SetEndDate(self.EndYear,12,31)
        
        self.StartCash = 100000
        self.SetCash(self.StartCash)
        
        # 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}")
 
        # ------------------------------------------- Defining Tickers and collection Indicators -----------------------------
        self.VXX = self.AddEquity("VXX", Resolution.Daily).Symbol
        self.VIXY = self.AddEquity("VIXY", Resolution.Daily).Symbol
        self.tickers = ["QQQ","TLT"]  # ,"FDN","SPY","ARKK","SQQQ","GLD","PSQ","SH","EMTY", "XLU","XLP","TBT","IEF", "FDN","TLH"]
       
       
        self.TickerTable = {}
        
        for ticker in self.tickers:
            
            # --------- Add Equity
            self.AddEquity(ticker, Resolution.Hour)
            
            # --------- Add Equity indicators
            #self.Debug(f"{self.RsiDays}    {self.SmaShortDays}  {self.SmaLongDays}   {self.PpoFastDays}    {self.PpoSlowDays}   ")
            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
            

        self.Schedule.On(self.DateRules.EveryDay(self.InEquity),self.TimeRules.AfterMarketOpen(self.InEquity,self.MinsAfterOpen), self.Trade)


        self.SetBenchmark("QQQ")
        
        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.SetWarmUp(timedelta(days=30))

    # ------------------------------------------------- On Data -----------------------------------------------------
    def OnData(self, data):
        pass
        
        
    # ---------------------------------------------- Trade Function --------------------------------------------------
    def Trade(self):
        
        self.TotalDays +=1
        
        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.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)}")
     
        
        #if self.InEquity_MACD < self.InEquity_MACD_Signal * self.Factor:
        #if self.InEquity_EMA > self.Securities[self.InEquity].Price * self.Factor:
        
        # Go out if SIGNAL is High and VALUE is Low
        #if self.InEquity_MACD_Signal > self.MacdSignalGap and self.InEquity_MACD < self.MacdGap:
       
        #if self.InEquity_MACD_Signal > self.InEquity_MACD * 1.2:
        
        if self.InEquity_PPO <= self.PpoGap or self.InEquity_SLOPE < self.SlopeGap or self.InEquity_RSI < self.RsiLowGap:
            self.MyInOutIndicator = 0
            self.DaysOut = 0                                            # Zero the DaysOut counter
            self.Log(f"{self.Time} {self.InEquity_PPO} {self.InEquity_RSI} {self.InEquity_SLOPE}")
        else:
            if self.DaysOut >= self.MinDaysOut:
                self.MyInOutIndicator = 1
                self.DaysOut = 0
            else:
                self.DaysOut +=1                                        # ---- Unless in Market out Cooldown
        
        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.PlotIt()
    
    # ----------------------------------------------- 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)}%")
    
    # ---------------------------------------------- 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)


# ---------------------------------------------- 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