Overall Statistics
class NadionVentralGearbox(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 5, 28)  # Set Start Date
        self.SetEndDate(2020,5,30) # Set End Date
        self.SetCash(100000)  # Set Strategy Cash
        self.SetUniverseSelection(CoarseFundamentalUniverseSelectionModel(self.CoarseSelectionFunction))
        self.UniverseSettings.Resolution = Resolution.Daily
        
        self.AddAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(days=1), None, None))
        self.SetExecution(ImmediateExecutionModel())
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
        
        self.stateData = { }
        self.fastEMA = 25
        self.slowEMA = 50

    def OnData(self, data):
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
            Arguments:
                data: Slice object keyed by symbol containing the stock data
        '''


    def CoarseSelectionFunction(self, coarse):
        selected = []
        # filter by DollarVolume > 10m and Price > 5
        filtered = [ x for x in coarse 
                      if x.Price > 5 and x.DollarVolume > 50000000 ]
        # self.Debug(f'There are {len(filtered)} stocks in the Universe')
        
        for c in filtered:
            symbol = c.Symbol
            # Check that we've created an instance of stateData for this symbol
            if symbol not in self.stateData:
                # Call history to get an array of 50 days of history data
                history = self.History(symbol, self.slowEMA, Resolution.Daily)
                
                # Create a new instance of SelectionData and save to stateData[symbol]
                self.stateData[symbol] = SelectionData(symbol, history, self.fastEMA, self.slowEMA)
            
            # Update the symbol with the latest coarse.AdjustedPrice data
            self.stateData[symbol].update(self.Time, c.AdjustedPrice)
            if self.stateData[symbol].fast > self.stateData[symbol].slow:
                if self.stateData[symbol].is_ready():
                    selected.append(symbol)
            # self.Debug(f'There are {len(selected)} stocks in the selected universe')
        
        return selected
    
    
class SelectionData(object):
    def __init__(self, symbol, history, fast, slow):
        self.symbol = symbol
        self.fast = ExponentialMovingAverage(fast)
        self.slow = ExponentialMovingAverage(slow)
        
        # Loop over the history data and update the indicators
        for bar in history.itertuples():
            self.fast.Update(bar.Index[1], bar.close)
            self.slow.Update(bar.Index[1], bar.close)
        
    def update(self, time, price):
        # Use the update property to get the time and price of both indicators
        self.fast.Update(time, price) 
        self.slow.Update(time, price)

    def is_ready(self):
        return self.slow.IsReady and self.fast.IsReady