Overall Statistics
Total Trades
21
Average Win
7.07%
Average Loss
0%
Compounding Annual Return
99.400%
Drawdown
19.400%
Expectancy
0
Net Profit
99.777%
Sharpe Ratio
3.211
Probabilistic Sharpe Ratio
92.725%
Loss Rate
0%
Win Rate
100%
Profit-Loss Ratio
0
Alpha
0.798
Beta
0.126
Annual Standard Deviation
0.256
Annual Variance
0.066
Information Ratio
1.693
Tracking Error
0.367
Treynor Ratio
6.552
Total Fees
$77.62
class QInOut(QCAlgorithm):

    def Initialize(self):
        
        # ------------------------------------------- Parameters ---------------------------------------
        
        # Entry minute for the Trade algo after Market Open
        self.MinsAfter = int(self.GetParameter("minsAfter"))
        
        #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.RcDays = int(self.GetParameter("rcDays"))
        self.RcK = 2
        self.PpoSlowDays = int(self.GetParameter("ppoSlowDays"))
        self.PpoFastDays = int(self.GetParameter("ppoFastDays"))
       
        # Indicators gaps and factors
        self.RsiLowGap = int(self.GetParameter("rsiLowGap"))
        self.RsiHighGap = int(self.GetParameter("rsiHighGap"))   #Not Used ATM
        self.PpoGap = float(self.GetParameter("ppoGap"))
        self.SlopeGap = float(self.GetParameter("slopeGap"))
        self.MompGap = 100 # not in use ATM float(self.GetParameter("mompGap"))
        # MACD factors (Not Used ATM)
        self.MacdGap = float(self.GetParameter("macdGap"))
        self.MacdSignalGap = float(self.GetParameter("macdSignalGap"))
        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"))
        
        # Select Out Equity list of assests
        self.InAssetSelector = int(self.GetParameter("inAssetSelector"))
        
        # Debug Algo Input parameters
        #self.Debug(f"After Market Open. rsiLow:{self.RsiLowGap} rsiHigh:{self.RsiHighGap} ppo:{self.PpoGap} rsiDays:{self.RsiDays} 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.Settings.FreePortfolioValuePercentage = self.CashOut --- No need ATM. Consider for Live
        
        self.SetWarmUp(timedelta(days=60)) # Minimum should be RSI period X 2 + 1
        
        # --------------------------------------- Internal variables -----------------------------------
        
        #For Plots on Equity Graph
        self.IndexEquityHistory = []                   # now used for QQQ
        self.OutEquityHistory = []                  # now used to TLT

        self.FirstDay = True
        self.IndexEquity_RSI_DAY_BEFORE = 0
        self.IndexEquity_PPO_DAY_BEFORE = 0 
        self.IndexEquity_BIG_SMA_WINDOW_DAY_BEFORE = 0
        self.IndexEquity_SMA_WINDOW_DAY_BEFORE = 0
        self.IndexEquity_SLOPE_DAY_BEFORE = 0
        self.IndexEquity_MOMP_DAY_BEFORE = 0
        self.IndexEquity_SMA_DAY_BEFORE = 0
        self.IndexEquity_MACD_DAY_BEFORE = 0
        self.IndexEquity_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 = [] # Not Used ATM
        self.IndicatorRatio = 0     # Not Used ATM
        
        self.ReasonOut= ""      # String to report reason to go out of the Market/InEquity
        
        # ---------------------------------------- Defining Tickers and collection Indicators ---------------------------
        
        self.SetBenchmark("SPY")
        
        # --- List to assets to buy when in the market (Buy equal weights)
        self.InAssets = {1:["QQQ"],
                         2:["MSFT","AAPL","FB","GOOG","AMZN"],
                         3:["ARKK"],
                         4:["CRSP","NTLA","EDIT"],
                         5:["SPY"]
        }
        
        self.IndexEquity = "QQQ"                                           # Key index for In Out decisions
        self.OutEquity="TLT"                                            # Out of market Asset. Consider making it a list of assets
        
        self.InAssetList = self.InAssets[self.InAssetSelector]          # Asset List
    
        self.VXX = self.AddEquity("VXX", Resolution.Daily).Symbol       # Used for Graph
        self.tickers = ["QQQ","TLT"] + self.InAssetList                 # ,"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.Minute)
            
            # --------- Add Equity indicators
            
            #smaLong = self.SMA(ticker, self.SmaLongDays, Resolution.Daily)
            #smaShort = self.SMA(ticker, self.SmaShortDays, 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)
            
            rsi = self.RSI(ticker, self.RsiDays, MovingAverageType.DoubleExponential,  Resolution.Daily)  # MovingAverageType.Wilders,
            macd = self.MACD(ticker,  self.MacdFastDays,self.MacdSlowDays,self.MacdSignalDays,MovingAverageType.Exponential, Resolution.Daily)
            rc = self.RC(ticker,self.RcDays, self.RcK, Resolution.Daily)
            ppo = self.PPO(ticker, self.PpoFastDays, self.PpoSlowDays, MovingAverageType.Exponential, Resolution.Daily)
            
            symbolData = SymbolData(ticker, rsi, rc, ppo, macd)
            
            
            self.TickerTable[ticker] = symbolData


        # --------------------------------------------------- Schedules --------------------------------------------
        
        self.Schedule.On(self.DateRules.EveryDay("QQQ"),self.TimeRules.AfterMarketOpen("QQQ",self.MinsAfter), self.Trade)


    # ------------------------------------------------- On Data -----------------------------------------------------
    
    def OnData(self, data):
        
        if self.IsWarmingUp:
            return
        
        if not self.TickerTable[self.IndexEquity].Rsi.IsReady:
            self.Debug("RSI not ready")
            return
        if not self.TickerTable[self.IndexEquity].Ppo.IsReady:
            self.Debug("PPO not ready")
            return
        if not self.TickerTable[self.IndexEquity].Macd.IsReady:
            self.Debug("MACD not ready")
            return
        if not self.TickerTable[self.IndexEquity].Rc.IsReady:
            self.Debug("RC not ready")
            return
            
    
    # ---------------------------------------------------------------------------------------------------------------
    # ---------------------------------------------- Trade Function -------------------------------------------------
    # ---------------------------------------------------------------------------------------------------------------
    
    def Trade(self):
        
        self.TotalDays +=1
        self.CollectIndicatorsAndTrends()
        self.DecideInOrOut()
        
        if self.MyInOutIndicator == 1:
            self.TotalDaysIn +=1
            NumberOfAssets = len(self.InAssetList)
            if self.Securities[self.OutEquity].Invested:
                self.Liquidate()
            for asset in self.InAssetList:
                if not self.Securities[asset].Invested:
                    self.SetHoldings(asset, 1.00/NumberOfAssets, False,f"PPO:{round(self.IndexEquity_PPO,2)} SLOPE:{round(self.IndexEquity_SLOPE,2)} RSI(Double Expo):{round(self.IndexEquity_RSI,2)}")
                    self.Notify.Sms("+972542224488", asset +" In:" + str(self.Securities[asset].Price))
        else:
             if not self.Securities[self.OutEquity].Invested:
                self.SetHoldings(self.OutEquity, 1.00, True,"Out: "+self.ReasonOut)
                self.Notify.Sms("+972542224488", self.IndexEquity + " Out:" + str(self.Securities[self.IndexEquity].Price))

        self.AfterTradeUpdate()
        self.PlotIt()
    
    # --------------------------------  Decide IN or OUT ----------------------------------------
    
    def GoldenCross(self):
        if abs (self.IndexEquity_MACD - self.IndexEquity_MACD_Signal) <0.1 and self.IndexEquity_MACD > self.IndexEquity_MACD_DAY_BEFORE:
            return True
        else:
            return False
    
    def DeathCross(self):
        if abs(self.IndexEquity_MACD - self.IndexEquity_MACD_Signal) < 0.1 and self.IndexEquity_MACD < self.IndexEquity_MACD_DAY_BEFORE:
            return True
        else:
            return False
    
    
    def DecideInOrOut(self):
        
       
        #if self.DeathCross():
        #    self.Debug(str(self.Time) + " DC OUT")
        #if self.GoldenCross():
        #    self.Debug(str(self.Time) + " GC IN")
            
            
        # Should we go OUT ?
        self.ReasonOut=" "
        
        #if self.DeathCross():
        #    self.ReasonOut = self.ReasonOut + f" MACD DC:{round(self.IndexEquity_MACD,2)}"
            
        if self.IndexEquity_PPO < self.PpoGap:
            self.ReasonOut = self.ReasonOut + f" PPO:{round(self.IndexEquity_PPO,2)}"
            
        if self.IndexEquity_RSI < self.RsiLowGap:
            self.ReasonOut = self.ReasonOut + f" RSI:{round(self.IndexEquity_RSI,2)}"
            
        if self.IndexEquity_SLOPE < self.SlopeGap:
            self.ReasonOut = self.ReasonOut + f" SLOPE:{round(self.IndexEquity_SLOPE,2)}"
            
        if self.ReasonOut != " ":
            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.IndexEquity_BIG_SMA_WINDOW_DAY_BEFORE = self.IndexEquity_BIG_SMA_WINDOW
            #self.IndexEquity_SMA_WINDOW_DAY_BEFORE = self.IndexEquity_SMALL_SMA_WINDOW
            #self.IndexEquity_MOMP_DAY_BEFORE = self.IndexEquity_MOMP
            #self.IndexEquity_SMA_DAY_BEFORE = self.IndexEquity_SMA
            self.IndexEquity_RSI_DAY_BEFORE = self.IndexEquity_RSI
            self.IndexEquity_PPO_DAY_BEFORE = self.IndexEquity_PPO
            self.IndexEquity_MACD_DAY_BEFORE = self.IndexEquity_MACD
            self.IndexEquity_MACD_Signal_DAY_BEFORE = self.IndexEquity_MACD_Signal
            self.IndexEquity_MACD_Histogram_DAY_BEFORE = self.IndexEquity_MACD_Histogram
            self.IndexEquity_SLOPE_DAY_BEFORE = self.IndexEquity_SLOPE
        
        #self.IndexEquity_BIG_SMA_WINDOW = self.TickerTable[self.IndexEquity].SmaLong.Current.Value
        #self.IndexEquity_SMALL_SMA_WINDOW = self.TickerTable[self.IndexEquity].SmaShort.Current.Value
        #self.IndexEquity_MOMP = self.TickerTable[self.IndexEquity].Momp.Current.Value
        #self.IndexEquity_SMA = self.TickerTable[self.IndexEquity].Sma.Current.Value
        #self.IndexEquity_EMA = self.TickerTable[self.IndexEquity].Ema.Current.Value
        self.IndexEquity_RSI = self.TickerTable[self.IndexEquity].Rsi.Current.Value
        self.IndexEquity_PPO = self.TickerTable[self.IndexEquity].Ppo.Current.Value
        self.IndexEquity_MACD = self.TickerTable[self.IndexEquity].Macd.Current.Value
        self.IndexEquity_MACD_Signal = self.TickerTable[self.IndexEquity].Macd.Signal.Current.Value
        self.IndexEquity_MACD_Histogram = self.TickerTable[self.IndexEquity].Macd.Histogram.Current.Value
        self.IndexEquity_SLOPE = self.TickerTable[self.IndexEquity].Rc.Slope.Current.Value
        
        self.FirstDay = False
       
        #self.Debug(f"{self.Time}   PPO:{round(self.IndexEquity_PPO,2)}   Slope:{round(self.IndexEquity_SLOPE,2)}   RSI:{round(self.IndexEquity_RSI,2)}")
    
    
    # ------------------------------------  After Trade updates ---------------------------------------------

    def AfterTradeUpdate(self):
        
        
        #self.IndexEquity_BIG_SMA_WINDOW_DAY_BEFORE = self.IndexEquity_BIG_SMA_WINDOW
        #self.IndexEquity_SMA_WINDOW_DAY_BEFORE = self.IndexEquity_SMALL_SMA_WINDOW
        #self.IndexEquity_MOMP_DAY_BEFORE = self.IndexEquity_MOMP
        #self.IndexEquity_SMA_DAY_BEFORE = self.IndexEquity_SMA
        self.IndexEquity_RSI_DAY_BEFORE = self.IndexEquity_RSI
        self.IndexEquity_PPO_DAY_BEFORE = self.IndexEquity_PPO 
        self.IndexEquity_MACD_DAY_BEFORE = self.IndexEquity_MACD
        self.IndexEquity_MACD_Signal_DAY_BEFORE = self.IndexEquity_MACD_Signal
        self.IndexEquity_SLOPE_DAY_BEFORE = self.IndexEquity_SLOPE
        
        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:
            pass
    
    # -------------------------------------------- Plot Function ------------------------------------------------
    
    def PlotIt(self):    
        
        self.Plot("In/Out Indicator","InOut",self.MyInOutIndicator)
        self.Plot("RSI","RSI",self.IndexEquity_RSI)
        self.Plot("PPO","PPO",self.IndexEquity_PPO)
        self.Plot("Indicators","SLOPE",self.IndexEquity_SLOPE)
        self.Plot("Indicators","MACD",self.IndexEquity_MACD)        
        self.Plot("Indicators","MACD Signal",self.IndexEquity_MACD_Signal) 
        self.Plot("Indicators","MACD Hist",self.IndexEquity_MACD_Histogram)
        
        try:
            self.Plot("VXX","TLT",self.Securities[self.VXX.Value].Price)
        except:
            pass
        
        # Benchmark Ploting
        hist = self.History([self.IndexEquity], 2, Resolution.Daily)['close'].unstack(level= 0).dropna() 
        self.IndexEquityHistory.append(hist[self.IndexEquity].iloc[-1])
        perf = self.IndexEquityHistory[-1] / self.IndexEquityHistory[0] * self.StartCash
        self.Plot("Strategy Equity", self.IndexEquity, 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, rc, ppo, macd):
        self.Symbol = symbol
        self.Rsi = rsi
        self.Macd = macd
        self.Rc = rc
        self.Ppo = ppo
        #self.Momp = momp
        #self.Sma = sma
        #self.Ema = ema
        #self.SmaLong = smaLong
        #self.SmaShort = smaShort