Overall Statistics
Total Trades
61
Average Win
0.50%
Average Loss
-0.72%
Compounding Annual Return
17.684%
Drawdown
12.700%
Expectancy
0.391
Net Profit
3.863%
Sharpe Ratio
0.723
Probabilistic Sharpe Ratio
43.090%
Loss Rate
18%
Win Rate
82%
Profit-Loss Ratio
0.70
Alpha
0.299
Beta
-0.219
Annual Standard Deviation
0.248
Annual Variance
0.062
Information Ratio
-1.334
Tracking Error
0.275
Treynor Ratio
-0.822
Total Fees
$98.88
class EMAMomentumUniverse(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2019, 1, 7)
        self.SetEndDate(2019, 4, 1)
        self.SetCash(100000)
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.CoarseSelectionFunction) 
        self.cciscan = { }
    
    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.cciscan:
                history = self.History(symbol, 20, Resolution.Daily)
                self.cciscan[symbol] = SelectionData(symbol, history) 
            
            if  self.cciscan[symbol].is_ready() and self.cciscan[symbol].cci.Current.Value < -100:
                selected.append(symbol)
        
        return selected[:10]
        
    def OnSecuritiesChanged(self, changes):
        
        for security in changes.AddedSecurities:
            self.SetHoldings(security.Symbol, 0.1)
            
    def OnData(self, data):
        
        for symbol, selectionData in self.cciscan.items():
            
            if data.Bars.ContainsKey(symbol):
                selectionData.update(data.Bars[symbol])
            
                if self.Portfolio[symbol].Invested and selectionData.cci.Current.Value > 100:
                        self.Liquidate(symbol)
        
class SelectionData():
    def __init__(self, symbol, history):
        self.symbol = symbol
        self.cci = CommodityChannelIndex(20, MovingAverageType.Simple)
        
        #4. Loop over the history data and update the indicators
        for bar in history.itertuples():
            #need some way to update CCI with history - currently throws an error.
            tbar = TradeBar(bar.Index[1], self.symbol, bar.open, bar.high, bar.low, bar.close, bar.volume)
            self.cci.Update(tbar)
            #self.cci.Update(bar.Index[1], bar.close)
              
    def is_ready(self):
        return self.cci.IsReady
    
    def update(self, bar):
        self.cci.Update(bar)