Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-0.668
Tracking Error
0.303
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
from System import *
from QuantConnect import *
from QuantConnect.Data.Consolidators import *
from QuantConnect.Data.Market import *
from QuantConnect.Orders import OrderStatus
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Indicators import *
import numpy as np
from datetime import timedelta, datetime

class MultipleSymbolMultipleIndicatorDatapoint(QCAlgorithm):
    
    def Initialize(self):
        
        RollingWindowSize = 2 # How many bars worth of data do you need?
        self.Data = {} # The dictionary to use
        EquitySymbols = ["AAPL","SPY","IBM"] # As many as you like. This can also work with a QC Universe

        # Date bookends
        self.SetStartDate(2020, 1, 1)
        self.SetEndDate(2020, 12, 31)
        self.SetWarmup(30)
        
        # initialize our equity data
        for symbol in EquitySymbols:
            equity = self.AddEquity(symbol, Resolution.Daily)
            self.Data[symbol] = SymbolData(equity.Symbol, RollingWindowSize) # See SymbolData class below
        
        # loop through all our symbols and request data subscriptions and initialize indicator
        for symbol, symbolData in self.Data.items():
            # define the indicator
            symbolData.MACD = MovingAverageConvergenceDivergence("MACD", 12, 26, 9, Resolution.Daily)
            # define a consolidator to consolidate data for this symbol on the requested period
            consolidator = TradeBarConsolidator(1) # Only need one day in the bar, but this could be any size
            # 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):
        
        if not SymbolData.IsReady: return # Don't bother if there's no data yet
        self.Data[bar.Symbol.Value].MACD.Update(bar.Time, bar.Close) # This updates the MACD indicator
        self.Data[bar.Symbol.Value].Bars.Add(bar) # This updates the ticker data in its rolling window

    def OnData(self,data):
            
            # loop through each symbol in our structure
            for symbol in self.Data.keys():
                symbolData = self.Data[symbol]
                
                if symbolData.IsReady():

                    ## All data points for the MACD are accessible through symbolData
                    self.Debug(str(symbol) + str(" slow MACD: ") + str(symbolData.MACD.Slow.Current.Value)) # See console for Debug messages
                    self.Debug(str(symbol) + str(" fast MACD: ") + str(symbolData.MACD.Fast.Current.Value))
                    
                    macd_signal = symbolData.MACD.Signal.Current.Value # This is just one of the MACD indicator data points

                    # The rolling window was declared in SymbolData class,
                    # now we save the datapoint we need to the rolling window.
                    # Remember, this is happening for every stock in our list
                    self.Data[symbol].MACDSignal.Add(macd_signal) 

                    # And now we can reference the window index 
                    latestMACDSignalValue = symbolData.MACDSignal[0]
                    self.Debug(str(symbol) + str(" latest MACD signal value is: ") + str(latestMACDSignalValue))


class SymbolData(object):
    
    def __init__(self, symbol, windowSize):
        
        self.Symbol = symbol
        self.Bars = RollingWindow[IBaseDataBar](windowSize)
        # The MACD indicator for our symbol
        self.MACDSignal = RollingWindow[float](windowSize) # There may be a better way to do this, but this works


    # Returns true if all the data in this instance is ready (indicators, rolling windows, ect...)
    def IsReady(self):
        return self.Bars.IsReady and self.MACD.IsReady