Overall Statistics
class MultipleSymbolConsolidationAlgorithm(QCAlgorithm):
    
    
    # Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
    def Initialize(self):
        
        #Initial investment and backtest period
        self.SetStartDate(2019,1,1)                                  
        self.SetEndDate(datetime.now().date() - timedelta(1))        
        self.SetCash(100000)

        #Brokerage Model
        self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage)    
       
        # This is the period of bars we'll be creating
        BarPeriod = TimeSpan.FromMinutes(20)
       
        
        
        # This is the period of our rsi indicators
        RSIPeriod = 30
        
        # This is the period of our vwap indicators
        VWAPPeriod = 10
        
        # This is the period of our sma indicators
        SimpleMovingAveragePeriod = 30
        
        # This is the period of our last price
        SimpleMovingAverageonePeriod = 1
       
        # This is the period of our TEma indicators
        TripleExponentialMovingAveragePeriod = 5
       
        # This is the period of our ema indicators
        ExponentialMovingAveragePeriod = 10
       
        # This is the period of our tema indicators
        TripleExponentialMovingAveragePeriod = 5
       
        # This is the number of consolidated bars we'll hold in symbol data for reference
        RollingWindowSize = 30
        
       
        # Holds all of our data keyed by each symbol
        self.Data = {}
        
        # Contains all of our equity symbols
        EquitySymbols = ["QQQ"]
        
        # initialize our equity data
        for symbol in EquitySymbols:
            equity = self.AddEquity(symbol)
            self.Data[symbol] = SymbolData(equity.Symbol, BarPeriod, RollingWindowSize)
        
        for symbol in EquitySymbols:
            if self.Portfolio[symbol].Invested:
                self.Schedule.On(self.DateRules.EveryDay(symbol), self.TimeRules.BeforeMarketClose(symbol, 15))
                self.Liquidate(symbol)
        

        # loop through all our symbols and request data subscriptions and initialize indicator
        for symbol, symbolData in self.Data.items():
            

            # define the indicator
            symbolData.VWAP = VolumeWeightedAveragePriceIndicator(self.CreateIndicatorName(symbol, "VWAP" + str(VWAPPeriod), Resolution.Minute), VWAPPeriod)
            

            # define the indicator
            symbolData.SMA = SimpleMovingAverage(self.CreateIndicatorName(symbol, "SMA" + str(SimpleMovingAveragePeriod), Resolution.Minute), SimpleMovingAveragePeriod)
            
            # define the indicator
            symbolData.RSI = RelativeStrengthIndex(self.CreateIndicatorName(symbol, "RSI" + str(RSIPeriod), Resolution.Minute), RSIPeriod, MovingAverageType.Simple)
            
            # define the indicator
            symbolData.SMAone = SimpleMovingAverage(self.CreateIndicatorName(symbol, "SMA" + str(SimpleMovingAverageonePeriod), Resolution.Minute), SimpleMovingAverageonePeriod)
            

            # define the indicator
            symbolData.TEMA = TripleExponentialMovingAverage(self.CreateIndicatorName(symbol, "TEMA" + str(TripleExponentialMovingAveragePeriod), Resolution.Minute), TripleExponentialMovingAveragePeriod)
            
            # define the indicator
            symbolData.EMA = ExponentialMovingAverage(self.CreateIndicatorName(symbol, "EMA" + str(ExponentialMovingAveragePeriod), Resolution.Minute), ExponentialMovingAveragePeriod)
            
            # define a consolidator to consolidate data for this symbol on the requested period
            if symbolData.Symbol.SecurityType == SecurityType.Equity:
                consolidator = TradeBarConsolidator(BarPeriod) 
            
            elif symbolData.Symbol == symbolData.VWAP: 
                consolidator = TradeBarConsolidator(BarPeriod)
           
            else: 
                consolidator = QuoteBarConsolidator(BarPeriod)
            
            # write up our consolidator to update the indicator
            consolidator.DataConsolidated += self.OnDataConsolidated
            
            # we need to add this consolidator so it gets auto updates
            self.SubscriptionManager.AddConsolidator(symbolData.Symbol, consolidator)


    def OnDataConsolidated(self, sender, bar):
        
        self.Data[bar.Symbol.Value].SMA.Update(bar.Time, bar.Close)
        self.Data[bar.Symbol.Value].SMAone.Update(bar.Time, bar.Close)
        self.Data[bar.Symbol.Value].RSI.Update(bar.Time, bar.Close)
        self.Data[bar.Symbol.Value].TEMA.Update(bar.Time, bar.Close)
        self.Data[bar.Symbol.Value].EMA.Update(bar.Time, bar.Close)
        self.Data[bar.Symbol.Value].VWAP.Update(bar)

        self.Data[bar.Symbol.Value].Bars.Add(bar)

    # OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
    # Argument "data": Slice object, dictionary object with your stock data 
    def OnData(self,data):
        
       
             
        # loop through each symbol in our structure
        for symbol in self.Data.keys():
            symbolData = self.Data[symbol]
            
            stopLossPercent = .98
            profitTargetPercent = 1.05
            
            
            # this check proves that this symbol was JUST updated prior to this OnData function being called
            if symbolData.IsReady() and symbolData.WasJustUpdated(self.Time):
                if not self.Portfolio[symbol].Invested:
                        if symbolData.SMAone.Current.Value > symbolData.TEMA.Current.Value:
                            if symbolData.SMAone.Current.Value > symbolData.VWAP.Current.Value:
                            
                                        
        
                                        self.Liquidate()
                                    
                                        openOrders = self.Transactions.GetOpenOrders()
                                        if len(openOrders)> 0:
                                            for x in openOrders:
                                                 self.Transactions.CancelOrder(x.Id)
                                    
                                    
                                
                                        posSize = self.CalculateOrderQuantity(symbol, 0.9)
                                        self.MarketOrder(symbol, posSize)
                                        
                                    
                                    
                                                                        
                                        self.StopLimitOrder(symbol, -posSize, float(symbolData.SMAone.Current.Value) * stopLossPercent, float(symbolData.SMAone.Current.Value) * profitTargetPercent)
                                    
        
                
    # End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets).
    # Method is called 10 minutes before closing to allow user to close out position.
    def OnEndOfDay(self):
        
        i = 0
        for symbol in sorted(self.Data.keys()):
            symbolData = self.Data[symbol]
            # we have too many symbols to plot them all, so plot every other
            i += 1
            if symbolData.IsReady() and i%2 == 0:
                self.Plot(symbol, symbol, symbolData.SMA.Current.Value)
                

        
    
       
class SymbolData(object):
    
    def __init__(self, symbol, barPeriod, windowSize):
        self.Symbol = symbol
        
        # The period used when population the Bars rolling window
        self.BarPeriod = barPeriod
        
        # A rolling window of data, data needs to be pumped into Bars by using Bars.Update( tradeBar ) and can be accessed like:
        # mySymbolData.Bars[0] - most first recent piece of data
        # mySymbolData.Bars[5] - the sixth most recent piece of data (zero based indexing)
        self.Bars = RollingWindow[IBaseDataBar](windowSize)
        
        # The simple moving average indicator for our symbol
        self.SMA = None
  
    # Returns true if all the data in this instance is ready (indicators, rolling windows, ect...)
    def IsReady(self):
        return self.Bars.IsReady and self.SMA.IsReady

    # Returns true if the most recent trade bar time matches the current time minus the bar's period, this
    # indicates that update was just called on this instance
    def WasJustUpdated(self, current):
        return self.Bars.Count > 0 and self.Bars[0].Time == current - self.BarPeriod