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
-3.998
Tracking Error
0.274
Treynor Ratio
0
Total Fees
$0.00
import numpy as np
class ATRMomentumUniverse(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2020, 4, 7)
        self.SetEndDate(2020, 5, 6)
        self.SetCash(10000)
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.CoarseSelectionFunction) 
        
        self.assets = { }                                                       # List of traded assets
        
    def CoarseSelectionFunction(self, universe):  
        
        selected = []
        
        universe = sorted(universe, key=lambda c: c.DollarVolume, reverse=True) # Sorts the whole 8k universe after volume 
        universe = [c for c in universe if c.Price > 10][:1000]                  # Take the first 100 assets if they trade above 10$
        
        for coarse in universe:                                                 # For every asset dict in the universe
            symbol = coarse.Symbol                                              # Take the symbol name out of the dict
            
            if symbol not in self.assets:                                       # If it is not in the traded asset list yet
                history = self.History(symbol, 20, Resolution.Daily)            # Pull the history of the last 20 days
                
                self.assets[symbol] = SelectionData(symbol, history)            # Insert history into the data class and run it for the symbol
                
        return selected[:1]
        
        
        
    #def OnSecuritiesChanged(self, changes):
        
        #for security in changes.AddedSecurities:
            #self.SetHoldings(security.Symbol, 0.1)
            #self.StopMarketOrder(security.Symbol, -self.Portfolio[security.Symbol].Quantity, security.Price*(0.995))
            
            
            
    def OnData(self, data):
        
        for symbol, selectionData in self.assets.items():
            
            if data.Bars.ContainsKey(symbol):
                selectionData.update(data.Bars[symbol])
                
                print('Ready')
                
                if self.Portfolio[symbol].Invested and selectionData.atr.Current.Value > 0.6:
                    self.Liquidate(symbol)
                    
                if self.assets[symbol].is_ready():                              # If the symbol is tradable
                    atr_quantile = np.quantile([x.Value for x in list(self.assets[symbol].atr_container)[0:15]], 0.25)  # Calculate the quantile value of the last 15 days of the ATR
                    
                    print('Ready2')
                    
                    self.Log(atr_quantile, self.assets[symbol].macd_container[0].Slow, self.assets[symbol].macd_container[0].Fast)
                    
                    # Trading Logic Long
                    if self.assets[symbol].atr_container[0].Value <= atr_quantile and self.assets[symbol].macd_container[0].Slow > self.assets[symbol].macd_container[0].Fast and self.assets[symbol].macd_container[0].Slow > 0:
                        #selected_longs.append(symbol)
                        self.StopMarketOrder(security.Symbol, 1, data.Bars[symbol].High[1])
                        
                    # Trading Logic Short
                    if self.assets[symbol].atr_container[0].Value <= atr_quantile and self.assets[symbol].macd_container[0].Slow < self.assets[symbol].macd_container[0].Fast and self.assets[symbol].macd_container[0].Slow < 0:
                        #selected_shorts.append(symbol)
                        self.StopMarketOrder(security.Symbol, -1, data.Bars[symbol].Low[1])
                        
                        
class SelectionData():
    def __init__(self, symbol, history):
        self.symbol = symbol
        
        self.macd = MovingAverageConvergenceDivergence(12, 26, 9)
        self.macd.Updated += self.macd_container_update
        self.macd_container = RollingWindow[IndicatorDataPoint](3)
        
        self.atr = AverageTrueRange(1)
        self.atr.Updated += self.atr_container_update
        self.atr_container = RollingWindow[IndicatorDataPoint](20)
        
        
        for bar in history.itertuples():
            
            tbar = TradeBar(bar.Index[1], self.symbol, bar.open, bar.high, bar.low, bar.close, bar.volume)
            self.atr.Update(tbar)
            #self.macd.Update(bar.close)
              
    def is_ready(self):
        return self.atr_container.IsReady
    
    def update(self, bar):
        self.atr.Update(bar)
        self.macd.Update(bar.close)
    
    def macd_container_update(self, sender, updated):
        self.macd_container.Add(updated)
        
    def atr_container_update(self, sender, updated):
        self.atr_container.Add(updated)