Overall Statistics
Total Trades
14
Average Win
0.00%
Average Loss
0.00%
Compounding Annual Return
373.352%
Drawdown
0%
Expectancy
0.962
Net Profit
1.718%
Sharpe Ratio
32.458
Probabilistic Sharpe Ratio
99.767%
Loss Rate
50%
Win Rate
50%
Profit-Loss Ratio
2.92
Alpha
3.234
Beta
-0.645
Annual Standard Deviation
0.059
Annual Variance
0.004
Information Ratio
-0.847
Tracking Error
0.111
Treynor Ratio
-2.99
Total Fees
$16.15
class EMAMomentumUniverse(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2019, 1, 7)
        self.SetEndDate(2019, 1, 10)
        self.SetCash(100000)
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.CoarseSelectionFunction) 
        self.averages = { }
        self.buy =  []
    
    def CoarseSelectionFunction(self, universe):  
        selected = []
        universe = sorted(universe, key=lambda c: c.DollarVolume, reverse=True)  
        universe = [c for c in universe if c.Price > 10][:100]

        for coarse in universe:  
            symbol = coarse.Symbol
            
            if symbol not in self.averages:
                # 1. Call history to get an array of 200 days of history data
                history = self.History(symbol, 200, Resolution.Daily)
                
                #2. Adjust SelectionData to pass in the history result
                self.averages[symbol] = SelectionData(history) 

            self.averages[symbol].update(self.Time, coarse.AdjustedPrice)
            
            if  self.averages[symbol].is_ready(): # and self.averages[symbol].fast > self.averages[symbol].slow:
                selected.append(symbol)
        
        return selected[:10]
        
    def OnSecuritiesChanged(self, changes):
        for security in changes.AddedSecurities:
            self.buy.extend([security.Symbol])
            
    def OnData(self, data):
        for symbol in self.buy:
            if data.ContainsKey(symbol) and data[symbol] is not None:
                self.SetHoldings(symbol, 0.1)
        self.buy = [symbol for symbol in self.buy if not self.Portfolio[symbol].Invested]
            
class SelectionData():
    #3. Update the constructor to accept a history array
    def __init__(self, history):
        self.slow = ExponentialMovingAverage(200)
        self.fast = ExponentialMovingAverage(50)
        
        self.rsi = RelativeStrengthIndex(10)
        self.macd = MovingAverageConvergenceDivergence(12, 26, 9)
        
        #4. Loop over the history data and update the indicators
        
        for data in history.itertuples():
            time = data.Index[1]
            close = data.close
            self.fast.Update(time, close)
            self.slow.Update(time, close)
            
            self.rsi.Update(time, close)
            self.macd.Update(time, close)
            
            
    
    def is_ready(self):
        return self.slow.IsReady and self.fast.IsReady and self.rsi.IsReady and self.macd.IsReady
    
    def update(self, time, price):
        self.fast.Update(time, price)
        self.slow.Update(time, price)
            
        self.rsi.Update(time, price)
        self.macd.Update(time, price)