Overall Statistics
Total Trades
1
Average Win
0%
Average Loss
0%
Compounding Annual Return
-95.059%
Drawdown
3.600%
Expectancy
0
Net Profit
-1.904%
Sharpe Ratio
-6.603
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0.076
Beta
2.613
Annual Standard Deviation
0.121
Annual Variance
0.015
Information Ratio
-5.853
Tracking Error
0.079
Treynor Ratio
-0.306
Total Fees
$3.66
Estimated Strategy Capacity
$5000000.00
Lowest Capacity Asset
TQQQ UK280CGTCB51
"""
SEL(stock selection part)
Based on the 'Momentum Strategy with Market Cap and EV/EBITDA' strategy introduced by Jing Wu, 6 Feb 2018
adapted and recoded by Jack Simonson, Goldie Yalamanchi, Vladimir, Peter Guenther, Leandro Maia and Simone Pantaleoni
https://www.quantconnect.com/forum/discussion/3377/momentum-strategy-with-market-cap-and-ev-ebitda/p1
https://www.quantconnect.com/forum/discussion/9678/quality-companies-in-an-uptrend/p1
https://www.quantconnect.com/forum/discussion/9632/amazing-returns-superior-stock-selection-strategy-superior-in-amp-out-strategy/p1
https://www.quantconnect.com/terminal/#live-view-tab
I/O(in & out part)
The Distilled Bear in & out algo
Dan's original notes: 
"This is based on Peter Guenther great “In & Out” algo.
Included Tentor Testivis recommendation to use volatility adaptive calculation of WAIT_DAYS and RET.
Included Vladimir's ideas to eliminate fixed constants
Help from Thomas Chang"

https://www.quantopian.com/posts/new-strategy-in-and-out
https://www.quantconnect.com/forum/discussion/9597/the-in-amp-out-strategy-continued-from-quantopian/
"""

from QuantConnect.Data.UniverseSelection import *
import math
import numpy as np
import pandas as pdv
import scipy as sp

class EarningsFactorWithMomentum_InOut(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2021, 7, 29)
        self.SetEndDate(2021, 7, 30)  #Set End Date
        self.cap = 100000
        self.SetCash(self.cap)
        self.DISTILLED_BEAR_Init = 0
        res = Resolution.Minute
        
        # Holdings
        ### 'Out' holdings and weights
        self.BND1 = self.AddEquity('TMF', res).Symbol #TLT; TMF for 3xlev
        
        
        self.TMF = self.AddEquity('TMF', res).Symbol
        self.BOND = self.AddEquity('TLT', res).Symbol
        self.quantity = {self.BND1: 0, self.BOND:0}
        self.TQQQ = self.AddEquity('TQQQ', res).Symbol
        
        ##### In & Out parameters #####
        # Feed-in constants
        self.INI_WAIT_DAYS = 15  # out for 3 trading weeks
        self.wait_days = self.INI_WAIT_DAYS
        
        # Market and list of signals based on ETFs
        self.MRKT = self.AddEquity('SPY', res).Symbol  # market
        self.QQQ = self.AddEquity('QQQ', res).Symbol  # tech market
        self.TQQQ = self.AddEquity('TQQQ', res).Symbol 
        self.GOLD = self.AddEquity('GLD', res).Symbol  # gold
        self.SLVA = self.AddEquity('SLV', res).Symbol  # vs silver
        self.UTIL = self.AddEquity('XLU', res).Symbol  # utilities
        self.INDU = self.AddEquity('XLI', res).Symbol  # vs industrials
        self.METL = self.AddEquity('DBB', res).Symbol  # input prices (metals)
        self.USDX = self.AddEquity('UUP', res).Symbol  # safe haven (USD)
        
        self.FORPAIRS = [self.GOLD, self.SLVA, self.UTIL, self.INDU, self.METL, self.USDX]
        
        # Specific variables
        self.DISTILLED_BEAR = 1#999
        self.BE_IN = 1#999
        self.BE_IN_PRIOR = 0
        self.VOLA_LOOKBACK = 126
        self.WAITD_CONSTANT = 85
        self.DCOUNT = 0 # count of total days since start
        self.OUTDAY = (-self.INI_WAIT_DAYS+1) # dcount when self.be_in=0, initial setting ensures trading right away
        self.fill_act = 0
        # Variables for charts
        self.spy = []
        self.qqq = []
        self.benchmark = []
        self.portfolio_value = [self.cap] * 60
        self.year = self.Time.year
        self.saw_qqq_base = []
        self.saw_portfolio_base = []
        
        # set a warm-up period to initialize the indicator
        self.SetWarmUp(timedelta(350))
        
        
        
        ##### Momentum & fundamentals strategy parameters #####
        self.UniverseSettings.Resolution = res
        self.AddUniverse(self.UniverseCoarseFilter, self.UniverseFundamentalsFilter)
        self.num_coarse = 100 #200
        self.num_screener = 30 #100  # changed from 15
        self.num_stocks = 4 # lowered from 10
        self.formation_days = 126 #126 was original value
        self.lowmom = False
        self.data = {}
        self.setrebalancefreq = 60 # X days, update universe and momentum calculation
        self.updatefinefilter = 0
        self.symbols = None
        self.reb_count = 0
        self.fill_act_symbol = None
        

        self.Schedule.On(
            self.DateRules.EveryDay(),
            self.TimeRules.AfterMarketOpen('SPY', 30), # reduced time 
            self.rebalance_when_out_of_the_market)
        
        self.Schedule.On(
            self.DateRules.EveryDay(), 
            self.TimeRules.BeforeMarketClose('SPY', 0), 
            self.record_vars)  
            
            
        self.Schedule.On(
            self.DateRules.WeekEnd(), 
            self.TimeRules.AfterMarketOpen('SPY', 29), 
            self.Weeklydeposit)     
            
            
        self.Schedule.On(
            self.DateRules.EveryDay(),
            self.TimeRules.AfterMarketOpen('SPY', 25), # reduced time 
            self.first_day_liquidation)
            
        
        #Calculate the share per min based on the trading volume per min    
        fill_time = []
        p = 1 #interval(minutues)
        y = int((390-30)/p) # total market open hour (minutes)   (390(Total minute)-Dealying 30mins after open )
        
        for i in range(1, y):
            fill_time.append(i*p + 30)  


        for x in fill_time:
            self.Schedule.On(
                self.DateRules.EveryDay(),
                self.TimeRules.AfterMarketOpen('SPY', x), # reduced time 
                self.fill)    
        
        self.vollookback = 30 #volume calculation lookback (15mins)
        self.volcalsymbols = [self.BND1] + [self.TQQQ] 

        # Setup daily consolidation
        symbols = [self.MRKT] + [self.QQQ] + self.FORPAIRS 
        for symbol in symbols:
            self.consolidator = TradeBarConsolidator(timedelta(days=1))
            self.consolidator.DataConsolidated += self.consolidation_handler
            self.SubscriptionManager.AddConsolidator(symbol, self.consolidator)
        
        # Warm up history
        self.lookback = 126
        self.history = self.History(symbols, self.lookback, Resolution.Daily)

        
        #calculate close price
        if self.history.empty or 'close' not in self.history.columns:
            return
        self.history = self.history['close'].unstack(level=0).dropna()

        #EMA data
        self.averages = {}
        self.buy = 3
        
    def UniverseCoarseFilter(self, coarse):
        
        if not (((self.DCOUNT-self.reb_count)==self.setrebalancefreq) or (self.DCOUNT == self.OUTDAY + self.wait_days - 1)):
            self.updatefinefilter = 0
            return Universe.Unchanged
        
        self.updatefinefilter = 1
            
        # drop stocks which have no fundamental data or have too low prices
        selected = [x for x in coarse if (x.HasFundamentalData) and (float(x.Price) > 5)]
        # rank the stocks by dollar volume 
        filtered = sorted(selected, key=lambda x: x.DollarVolume, reverse=True)
        return [x.Symbol for x in filtered[:self.num_coarse]]
        
        
    def UniverseFundamentalsFilter(self, fundamental):
        if self.updatefinefilter == 0:
            return Universe.Unchanged
            
        filtered_fundamental = [x for x in fundamental if (x.ValuationRatios.EVToEBITDA > 0) 
                                        and x.OperationRatios.OperationRevenueGrowth3MonthAvg.Value > 0
                                        and (x.EarningReports.BasicAverageShares.ThreeMonths > 0) 
                                        and float(x.EarningReports.BasicAverageShares.ThreeMonths) * x.Price > 6e9
                                        and x.SecurityReference.IsPrimaryShare
                                        and x.SecurityReference.SecurityType == "ST00000001"
                                        and x.SecurityReference.IsDepositaryReceipt == 0
                                        and x.CompanyReference.IsLimitedPartnership == 0]

        top = sorted(filtered_fundamental, key = lambda x: x.ValuationRatios.EVToEBITDA, reverse=True)[:self.num_screener]

        self.symbols = [x.Symbol for x in top]
        self.updatefinefilter = 0
        self.reb_count = self.DCOUNT

        # fine_series = pd.Series(self.symbols)
        # self.Log('EV/EBITDA Rank: ' + str(fine_series))
        # self.Notify.Sms("+18605138853",  'EV/EBITDA Rank: ' + str(fine_series))
        
        return self.symbols
        
    
    def OnSecuritiesChanged(self, changes):

        #for security in changes.AddedSecurities:
        #    if security.Symbol not in self.data:
        #        self.data[security.Symbol] = SymbolData(security.Symbol, self.formation_days, self)
    
        addedSymbols = []
        for security in changes.AddedSecurities:
            addedSymbols.append(security.Symbol)
            if security.Symbol not in self.data:
                self.data[security.Symbol] = SymbolData(security.Symbol, self.formation_days, self)
   
        if len(addedSymbols) > 0:
            history = self.History(addedSymbols, 1 + self.formation_days, Resolution.Daily).loc[addedSymbols]
            for symbol in addedSymbols:
                try:
                    self.data[symbol].Warmup(history.loc[symbol])
                except:
                    self.Debug("not added in Universe :" + str(symbol))
                    
                    continue
    
    
    def consolidation_handler(self, sender, consolidated):
        self.history.loc[consolidated.EndTime, consolidated.Symbol] = consolidated.Close
        self.history = self.history.iloc[-self.lookback:]

        
    def derive_vola_waitdays(self):
        volatility = 0.6 * np.log1p(self.history[[self.MRKT]].pct_change()).std() * np.sqrt(252)
        wait_days = int(volatility * self.WAITD_CONSTANT)
        returns_lookback = int((1.0 - volatility) * self.WAITD_CONSTANT)
        return wait_days, returns_lookback
    
    
    def first_day_liquidation(self):
        if self.DCOUNT == 0:
            self.Liquidate()
            self.Log("first day liquidation")

        
    def rebalance_when_out_of_the_market(self):
        
        if self.Portfolio.TotalPortfolioValue > 10000000:
            if self.fill_act == 0:
                del self.quantity[self.BND1]
                self.BND1 = self.BOND
                self.quantity = {self.BND1 : 0}
                self.volcalsymbols = [self.BND1] + [self.TQQQ] 

        elif self.Portfolio.TotalPortfolioValue <= 10000000 :   
            if self.fill_act == 0:
                del self.quantity[self.BND1]
                self.BND1 = self.TMF
                self.quantity = {self.BND1 : 0}
                self.volcalsymbols = [self.BND1] + [self.TQQQ] 

        self.vol_history = self.History(self.volcalsymbols, 150, Resolution.Minute)
        self.volumes = self.vol_history['volume'].unstack(level = 0).dropna()
        self.TQQQsharepertick = self.volumes[self.TQQQ].rolling(window=self.vollookback).mean().iloc[-1]*0.3
        self.BND1sharepertick = self.volumes[self.BND1].rolling(window=self.vollookback).mean().iloc[-1]
        self.TQQQsharepertick = math.floor(self.TQQQsharepertick)
        self.BND1sharepertick = math.floor(self.BND1sharepertick) 

        self.wait_days, returns_lookback = self.derive_vola_waitdays()
        
        ## Check for Bears
        returns = self.history.pct_change(returns_lookback).iloc[-1]
    
        silver_returns = returns[self.SLVA]
        gold_returns = returns[self.GOLD]
        industrials_returns = returns[self.INDU]
        utilities_returns = returns[self.UTIL]
        metals_returns = returns[self.METL]
        dollar_returns = returns[self.USDX]
        
        self.DISTILLED_BEAR = (((gold_returns > silver_returns) and
                       (utilities_returns > industrials_returns)) and 
                       (metals_returns < dollar_returns)
                       )
         
        if self.DISTILLED_BEAR_Init == 0:
            if self.DISTILLED_BEAR:
                self.DISTILLED_BEAR_Init = 1
                self.Debug("Market Sentiment : Distilled Bear - Initialized")
                self.Notify.Sms("+18605138853",  "Market Sentiment : Distilled Bear - Initialized")
        

       
       
        if self.DISTILLED_BEAR:
        
            
            SPY_hist = self.History(self.Symbol("SPY"), 200, Resolution.Daily)
            SPY_hist_price = SPY_hist.close 
    
            if (SPY_hist_price.rolling(window = 3).mean()[-1] - SPY_hist_price.rolling(window = 30).mean()[-1])/SPY_hist_price.rolling(window = 30).mean()[-1] >  0.025:
                self.DISTILLED_BEAR = False
                self.BE_IN = True
                self.Debug("Market Sentiment : Distilled Bear - In the market")
                self.Notify.Sms("+18605138853",  "Market Sentiment : Distilled Bear - In the market")
                self.DISTILLED_BEAR_Init = 0
                
            # elif SPY_hist_price.rolling(window = 3).mean()[-1] > SPY_hist_price.rolling(window = 9).mean()[-1] > SPY_hist_price.rolling(window = 32).mean()[-1] > SPY_hist_price.rolling(window = 72).mean()[-1] > SPY_hist_price.rolling(window = 180).mean()[-1] :
            #     self.DISTILLED_BEAR = False
            #     self.BE_IN = True
            #     self.Debug("Market Sentiment : Distilled Bear - In the market")
            #     self.Notify.Sms("+18605138853",  "Market Sentiment : Distilled Bear - In the market")
            #     self.DISTILLED_BEAR_Init = 0
            
            else:
                self.Debug("Market Sentiment : Distilled Bear - Out of the market")
                self.Notify.Sms("+18605138853",  "Market Sentiment : Distilled Bear - Out of the market")
            
        
        elif self.DISTILLED_BEAR == False and self.BE_IN == True:
            self.Debug("Market Sentiment : Bull")
            self.Notify.Sms("+18605138853",  "Market Sentiment : Bull")
            
        elif self.DISTILLED_BEAR == False and self.BE_IN == False:
            self.Debug("Market Sentiment : Distilled Bear - Wait for the confirmation (15 trading days)")
            self.Notify.Sms("+18605138853",  "Market Sentiment : Wait for the confirmation (15 trading days)")
                
           
        
        
        # Determine whether 'in' or 'out' of the market
        if self.DISTILLED_BEAR:
            self.BE_IN = False
            self.OUTDAY = self.DCOUNT
            
            # if self.quantity[self.BND1] == 0:
            for symbol in self.quantity.copy().keys():
                if symbol == self.BND1: continue
            
                elif self.quantity[symbol] <= self.TQQQsharepertick:

                        self.Order(symbol, - self.quantity[symbol])
                        self.Debug([str(self.Time), str(symbol), str(-self.quantity[symbol])])
                        self.quantity[symbol] = 0
                        del self.quantity[symbol]
                        self.fill_act = 0
                        
                        
                elif self.quantity[symbol] > self.TQQQsharepertick:
                    if self.fill_act == 3:

                        self.Order(symbol, - self.TQQQsharepertick)
                        self.Debug([str(self.Time), str(symbol), str(-self.TQQQsharepertick)])
                        self.quantity[symbol] -= self.TQQQsharepertick    
                        self.fill_act = 2
                        self.fill_act_symbol = symbol

            quantity = self.Portfolio.TotalPortfolioValue * 0.99 / self.Securities[self.BND1].Close
            
            
            
            
            history_BND1 = self.History(self.BOND, 300, Resolution.Daily)
            Open = history_BND1.open.unstack(0)[self.BOND][-1]
            
            Close = history_BND1.close.unstack(0)[self.BOND][-1]   
            Stable_PriceAction = Open  < Close * 1.02
            hlc3 = (history_BND1.close.unstack(0)[self.BOND][-1] + history_BND1.open.unstack(0)[self.BOND][-1] + history_BND1.high.unstack(0)[self.BOND][-1]) /3 
                                
            Close_history = history_BND1.close.unstack(0)[self.BOND]   
            
            self.averages[self.BND1] = SelectionDataShort(Close_history)
            
            if ((hlc3 > self.averages[self.BND1].MA13.Current.Value and 
                self.averages[self.BND1].MA5.Current.Value > self.averages[self.BND1].MA13.Current.Value and 
                Close_history.pct_change(1)[-1] > -0.015) or 
                Stable_PriceAction):
                    self.buy = 1
                    
            else:
                self.buy = 0
           
      
            
            if self.buy == 1:
                
                if self.fill_act == 0 and self.quantity[self.BND1] == 0:

                    if math.floor(quantity) <= self.BND1sharepertick:
                        self.quantity[self.BND1] = math.floor(quantity)
                        self.Order(self.BND1, self.quantity[self.BND1])
                        self.Debug([str(self.Time), str(self.BND1), str(self.quantity[self.BND1])])
                        
                        self.fill_act = 3
        
                    elif math.floor(quantity) > self.BND1sharepertick:    
                    
                            
                        sym = self.BND1  
                        self.Order(sym, self.BND1sharepertick)
                        self.Debug([str(self.Time), str(sym), self.BND1sharepertick])
                        self.quantity[sym] = self.BND1sharepertick
                
                
                        self.fill_act = 1    
                        self.fill_act_symbol = self.BND1
                            
                
                            

            elif self.buy == 0:
                
                if self.fill_act == 3 and self.quantity[self.BND1] > 0:
                    
                    if self.quantity[self.BND1] <= self.BND1sharepertick:
                        
                        self.Order(self.BND1, - self.quantity[self.BND1])
                        self.Debug([str(self.Time), str(self.BND1), str(-self.quantity[self.BND1])])
                        self.quantity[self.BND1] = 0
                        
                        self.fill_act = 0
                        
                    elif self.quantity[self.BND1] > self.BND1sharepertick:
        
                        self.Order(self.BND1, - self.BND1sharepertick)
                        self.Debug([str(self.Time), str(self.BND1), str(-self.BND1sharepertick)])
                        self.quantity[self.BND1] -= self.BND1sharepertick    
                        self.fill_act = 2
                        self.fill_act_symbol = self.BND1

            
        if (self.DCOUNT >= self.OUTDAY + self.wait_days):
            self.BE_IN = True
        
        # Update stock ranking/holdings, when swithing from 'out' to 'in' plus every X days when 'in' (set rebalance frequency)
        if (self.BE_IN and not self.BE_IN_PRIOR) or (self.BE_IN and (self.DCOUNT==self.reb_count)):

            chosen_df = self.calc_return(self.symbols)
            self.rebalance() 
            self.Debug('Best momentum (EV/EBITDA): ' + str(chosen_df))
            self.Notify.Sms("+18605138853",  'Best momentum (EV/EBITDA): ' + str(chosen_df))
    
        
        self.BE_IN_PRIOR = self.BE_IN
        self.DCOUNT += 1

        
        
        
        self.Notify.Sms("+18605138853", "Net LIQ :" + str(self.Portfolio.TotalPortfolioValue)) 

        self.create_charts()


    def rebalance(self):
            
        # chosen_df = self.calc_return(self.symbols)
        # self.Log('Best momentum (EV/EBITDA): ' + str(chosen_df))
        # self.Notify.Sms("+18605138853",  'Best momentum (EV/EBITDA): ' + str(chosen_df))
        # self.chosen_df = chosen_df.iloc[:self.num_stocks]
        # self.Log("Chosen 4 tickers :" + str(self.chosen_df))
 
        if self.quantity[self.BND1] > 0 :
            
            if self.quantity[self.BND1] <= self.BND1sharepertick:
                self.Order(self.BND1, - self.quantity[self.BND1])
                self.Debug([str(self.Time), str(self.BND1), str(-self.quantity[self.BND1])])
                self.quantity[self.BND1] = 0
                self.fill_act = 0
                
                
            elif self.quantity[self.BND1] > self.BND1sharepertick:
                if self.fill_act == 3 :
                    self.Order(self.BND1, - self.BND1sharepertick)
                    self.Debug([str(self.Time), str(self.BND1), str(-self.BND1sharepertick)])
                    self.quantity[self.BND1] -= self.BND1sharepertick    
                    self.fill_act = 2
                    self.fill_act_symbol = self.BND1
            
            
        # weight = 1 / self.num_stocks
        
        
        for symbol in self.quantity.copy().keys():
            if symbol == self.BND1 and self.quantity[symbol] > 0: 
                pass

        #     # elif symbol != self.TQQQ:
        #     #     self.Order(symbol, - self.quantity[symbol])
        #     #     self.Debug([str(self.Time), str(symbol), str(-self.quantity[symbol])])
        #     #     del self.quantity[symbol]
        #     #     self.fill_act = 0
        #     elif symbol == self.TQQQ:
        #         # self.Debug("Availible funds :" + str(self.Portfolio.TotalPortfolioValue * 0.99))
        #         quantity = self.Portfolio.TotalPortfolioValue * 0.1 / self.Securities[symbol].Close
        #         # self.Log(f'Quantity for {symbol} is {quantity} (line 338)...')
        #         if self.fill_act == 3:
        #             if math.floor(quantity) != self.quantity[symbol]:
        #                     if (math.floor(quantity) - self.quantity[symbol]) > 0:
        #                         if (math.floor(quantity) - self.quantity[symbol]) > self.TQQQsharepertick:
        #                             self.Order(symbol, (math.floor(quantity) - self.quantity[symbol]))
        #                             self.Debug([str(self.Time), str(symbol), (math.floor(quantity) - self.quantity[symbol])])
        #                             self.quantity[symbol] += (math.floor(quantity) - self.quantity[symbol])
        #                             self.fill_act = 1
        #                             self.fill_act_symbol = self.TQQQ
        #                         elif (math.floor(quantity) - self.quantity[symbol]) <= self.TQQQsharepertick:
        #                             self.Order(symbol, math.floor(quantity) - self.quantity[symbol])
        #                             self.Debug([str(self.Time), str(symbol), str(math.floor(quantity) -self.quantity[symbol])])
        #                             self.quantity[symbol] += (math.floor(quantity) - self.quantity[symbol])
        #                             self.fill_act = 3

        if self.TQQQ not in self.quantity.keys():
            quantity = self.Portfolio.TotalPortfolioValue * 0.99 / self.Securities[self.TQQQ].Close
            if self.fill_act == 0 :
                if math.floor(quantity) <= self.TQQQsharepertick:
                    self.quantity[self.TQQQ] = math.floor(quantity)
                    self.Order(self.TQQQ, self.quantity[self.TQQQ])
                    self.Debug([str(self.Time), str(self.TQQQ), str(self.quantity[self.TQQQ])])
                    self.fill_act = 3
                    
                    
                elif math.floor(quantity) > self.TQQQsharepertick:    
                        sym = self.TQQQ
                        self.Order(sym, self.TQQQsharepertick)
                        self.Debug([str(self.Time), str(sym), self.TQQQsharepertick])
                        self.quantity[sym] = self.TQQQsharepertick
                        self.fill_act = 1 
                        self.fill_act_symbol = self.TQQQ

    
    def Weeklydeposit(self):

        if self.fill_act == 3: #Only when all buying fill activity is finished, also you can avoid first day error since some self. are not identified.
            for symbol in self.quantity.copy().keys():
                if symbol == self.BND1 and self.quantity[symbol] > 0: 
                    quantity = self.Portfolio.TotalPortfolioValue * 0.99 / self.Securities[symbol].Close
                    if math.floor(quantity) != self.quantity[symbol]:
                            if (math.floor(quantity) - self.quantity[symbol]) > 0:
                                if (math.floor(quantity) - self.quantity[symbol]) > self.BND1sharepertick:
                                    self.Order(symbol, (math.floor(quantity) - self.quantity[symbol]))
                                    self.Debug([str(self.Time), str(symbol), (math.floor(quantity) - self.quantity[symbol]), "Weekly Rebalance"])
                                    self.quantity[symbol] += (math.floor(quantity) - self.quantity[symbol])
                                    self.fill_act = 1
                                    self.fill_act_symbol = self.BND1
                                elif (math.floor(quantity) - self.quantity[symbol]) <= self.BND1sharepertick:
                                    self.Order(symbol, math.floor(quantity) - self.quantity[symbol])
                                    self.Debug([str(self.Time), str(symbol), str(math.floor(quantity) -self.quantity[symbol]), "Weekly Rebalance"])
                                    self.quantity[symbol] += math.floor(quantity) - self.quantity[symbol]
                                    self.fill_act = 3

                elif symbol == self.TQQQ and self.quantity[symbol] > 0:
                    quantity = self.Portfolio.TotalPortfolioValue * 0.99 / self.Securities[symbol].Close
                    if math.floor(quantity) != self.quantity[symbol]:
                            if (math.floor(quantity) - self.quantity[symbol]) > 0:
                                if (math.floor(quantity) - self.quantity[symbol]) > self.TQQQsharepertick:
                                    self.Order(symbol, (math.floor(quantity) - self.quantity[symbol]))
                                    self.Debug([str(self.Time), str(symbol), (math.floor(quantity) - self.quantity[symbol]), "Weekly Rebalance"])
                                    self.quantity[symbol] += (math.floor(quantity) - self.quantity[symbol])
                                    self.fill_act = 1
                                    self.fill_act_symbol = self.TQQQ
                                elif (math.floor(quantity) - self.quantity[symbol]) <= self.TQQQsharepertick:
                                    self.Order(symbol, math.floor(quantity) - self.quantity[symbol])
                                    self.Debug([str(self.Time), str(symbol), str(math.floor(quantity) -self.quantity[symbol]), "Weekly Rebalance"])
                                    self.quantity[symbol] += (math.floor(quantity) - self.quantity[symbol])
                                    self.fill_act = 3
                                    
                            
                    

    def fill(self): 
        if self.fill_act_symbol :
            if self.fill_act ==1 or self.fill_act ==2:
                sym = self.fill_act_symbol    
                # self.Debug(["ongoing fill activity symbol", str(sym)])
                
        # algorithm.Portfolio[security.Symbol].Invested:
        
                
        
        if self.fill_act == 2: #Sell fill
            
                    
            if sym == self.TQQQ:
                sharepertick = self.TQQQsharepertick
            elif sym == self.BND1:
                sharepertick = self.BND1sharepertick
            
            
            if self.quantity[sym] > sharepertick:
                self.Order(sym, - sharepertick)
                self.Debug([str(self.Time), str(sym), str(-sharepertick)])
                self.quantity[sym] -= sharepertick    
                self.fill_act = 2
                    
            
            elif self.quantity[sym] <= sharepertick:
                self.Order(sym, - self.quantity[sym])
                self.Debug([str(self.Time), str(sym), str(-self.quantity[sym])])
                self.quantity[sym] = 0
                self.fill_act = 0
                
                if sym != self.BND1:
                    if sym != self.BOND:
                        del self.quantity[sym]
                    
                if self.BE_IN:
                    self.rebalance()
                    
                elif self.BE_IN == False and self.quantity[self.BND1] == 0:
                    self.rebalance_when_out_of_the_market()
                    
                    
                    
        elif self.fill_act == 1:
            if sym == self.BND1:
                sharepertick = self.BND1sharepertick
            
            elif sym == self.TQQQ:
                sharepertick = self.TQQQsharepertick
            
            quantity = self.Portfolio.TotalPortfolioValue * 0.99 / self.Securities[sym].Close
            if (math.floor(quantity) - self.quantity[sym]) > 0:
                if math.floor(quantity) != self.quantity[sym] and self.quantity[sym] != 0:
                        if (math.floor(quantity) - self.quantity[sym]) > sharepertick:
                            self.Order(sym, sharepertick)
                            self.Debug([str(self.Time), str(sym), sharepertick])
                            self.quantity[sym] += sharepertick
                            self.fill_act = 1
                            
                            
                        elif (math.floor(quantity) - self.quantity[sym]) <= sharepertick:
                            self.Order(sym, math.floor(quantity) - self.quantity[sym])
                            self.Debug([str(self.Time), str(sym), str(math.floor(quantity) - self.quantity[sym])])
                            self.quantity[sym] += math.floor(quantity) - self.quantity[sym]
                            self.fill_act = 3
                        
                        
            else:
                self.fill_act = 3    

            
            
        
    def calc_return(self, stocks):
        
        ret = {}
        for symbol in stocks:
            try:
                ret[symbol] = self.data[symbol].Roc.Current.Value
            except:
                self.Debug(str(symbol))
                continue
            
        df_ret = pd.DataFrame.from_dict(ret, orient='index')
        df_ret.columns = ['return']
        sort_return = df_ret.sort_values(by = ['return'], ascending = self.lowmom)
        
        return sort_return
    
        
    def record_vars(self): 
        pass
        
        
    def create_charts(self):
        # Record variables
        ### SPY benchmark
        self.spy.append(self.history[self.MRKT].iloc[-1])
        spy_perf = self.spy[-1] / self.spy[0] * self.cap
        self.Plot('Strategy Equity', 'SPY', spy_perf)
        
        ### Annual saw tooth return comparison: Portfolio VS QQQ
        self.portfolio_value.append(self.Portfolio.TotalPortfolioValue)
        if (self.DCOUNT==1) or (self.Time.year!=self.year):
            self.saw_qqq_base = self.history[self.QQQ].iloc[-1]
            self.saw_portfolio_base = self.Portfolio.TotalPortfolioValue
        self.benchmark = self.history[self.QQQ].iloc[-1]
        saw_qqq_return = (self.benchmark / self.saw_qqq_base -1)
        saw_portfolio_return = self.portfolio_value[-1] / self.saw_portfolio_base - 1
        self.Plot('Annual Saw Tooth Returns: Portfolio VS QQQ', 'Annual portfolio return', round(saw_portfolio_return, 4))
        self.Plot('Annual Saw Tooth Returns: Portfolio VS QQQ', 'Annual QQQ return', round(float(saw_qqq_return), 4))
        
        ### IN/Out indicator and wait days
        self.Plot("In Out", "in_market", int(self.BE_IN))
        self.Plot("Wait Days", "waitdays", self.wait_days)
        
        ### Leverage
        account_leverage = self.Portfolio.TotalHoldingsValue / self.Portfolio.TotalPortfolioValue
        self.Plot('Leverage', 'leverage', round(account_leverage, 4))
   
        self.year = self.Time.year
    
        
class SymbolData(object):
    def __init__(self, symbol, roc, algorithm):
        self.Symbol = symbol
        self.Roc = RateOfChange(roc)
        self.algorithm = algorithm
        
        self.consolidator = algorithm.ResolveConsolidator(symbol, Resolution.Daily)
        algorithm.RegisterIndicator(symbol, self.Roc, self.consolidator)
        
    def Warmup(self, history):
        for index, row in history.iterrows():
            self.Roc.Update(index, row['close'])
            
  
                
class SelectionDataShort():
    #3. Update the constructor to accept a history array
    def __init__(self, Close_history):
        self.MA1 = ExponentialMovingAverage(1)
        self.MA3 = ExponentialMovingAverage(3)
        self.MA5 = ExponentialMovingAverage(7)
        self.MA9 = ExponentialMovingAverage(9)
        self.MA13 = ExponentialMovingAverage(13)
        self.MA20 = ExponentialMovingAverage(20)
        self.MA25 = ExponentialMovingAverage(25)
        self.MA34 = ExponentialMovingAverage(34)
        self.MA50 = ExponentialMovingAverage(50)
        self.MA55 = ExponentialMovingAverage(55)
        self.MA72 = ExponentialMovingAverage(72)
        self.MA89 = ExponentialMovingAverage(89)
        self.MA100 = ExponentialMovingAverage(100)
        self.MA200 = ExponentialMovingAverage(200)
        self.MA75 = ExponentialMovingAverage(75)
        self.RSI = RelativeStrengthIndex(14, MovingAverageType.Simple)
      
        
        #4. Loop over the history data and update the indicators
        for time, price in Close_history.items():
            self.update(time, price)
    
    def is_ready(self):
        return self.MA9.IsReady and self.MA1.IsReady and self.MA3.IsReady and self.MA5.IsReady and self.MA13.IsReady and self.MA20.IsReady and self.MA25.IsReady and self.MA34.IsReady and self.MA50.IsReady and self.MA55.IsReady and self.MA72.IsReady and self.MA89.IsReady and self.MA75.IsReady and self.MA100.IsReady and self.MA200.IsReady and self.RSI.IsReady
        
    def update(self, time, price):
        self.MA1.Update(time, price)
        self.MA3.Update(time, price)
        self.MA5.Update(time, price)
        self.MA9.Update(time, price)
        self.MA13.Update(time, price)
        self.MA20.Update(time, price)
        self.MA25.Update(time, price)
        self.MA34.Update(time, price)
        self.MA55.Update(time, price)
        self.MA72.Update(time, price)
        self.MA89.Update(time, price)
        self.MA75.Update(time, price)
        self.MA20.Update(time, price)
        self.MA50.Update(time, price)
        self.MA100.Update(time, price)
        self.MA200.Update(time, price)
        self.RSI.Update(time, price)