Overall Statistics
Total Trades
57
Average Win
0.63%
Average Loss
-0.38%
Compounding Annual Return
5.744%
Drawdown
2.700%
Expectancy
0.046
Net Profit
1.201%
Sharpe Ratio
0.624
Probabilistic Sharpe Ratio
42.297%
Loss Rate
61%
Win Rate
39%
Profit-Loss Ratio
1.66
Alpha
-0.059
Beta
0.579
Annual Standard Deviation
0.063
Annual Variance
0.004
Information Ratio
-2.434
Tracking Error
0.054
Treynor Ratio
0.068
Total Fees
$65.03
Estimated Strategy Capacity
$43000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
# https://quantpedia.com/Screener/Details/14
class MomentumEffectAlgorithm(QCAlgorithm):

    def Initialize(self):

        self.SetStartDate(2021, 7, 1)  # Set Start Date
        self.SetCash(100000)           # Set Strategy Cash

        self.UniverseSettings.Resolution = Resolution.Minute

        self.macd = {}           # Dict of Momentum indicator keyed by Symbol
        self.atr = {}
        self.userlist = ["SPY"]      #User list
        self.spy = self.AddEquity("SPY", Resolution.Minute).Symbol
        self.AutomaticIndicatorWarmup = True
        self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
        self.counter = 0
        self.consolidatorCounter = 0
        
        # self.Schedule.On(self.DateRules.EveryDay("SPY"),
        #          self.TimeRules.Every(timedelta(minutes=31)),
        #          self.Trade)
        
        
    def ThirtyMinuteHandler(self, sender, bar):
        self.consolidatorCounter += 1
        if self.consolidatorCounter == self.counter:
            for i in self.Securities.Keys:
                self.Debug(self.atr[i].Current.Value)
                if self.macd[i].Current.Value > self.macd[i].Signal.Current.Value:
                    self.SetHoldings(i, 1)
                elif self.macd[i].Signal.Current.Value > self.macd[i].Current.Value:
                    self.Liquidate(i)
            self.consolidatorCounter = 0
            
    def Trade(self):
        pass

    def CoarseSelectionFunction(self, coarse):
        return [x.Symbol for x in coarse if x.Symbol.Value in self.userlist]

    def FineSelectionFunction(self, fine):
        return [x.Symbol for x in fine if x.Symbol.Value in self.userlist]

    def OnData(self, data):
        ''' Use scheduled event or this '''
        # if self.Time.minutes % 30 == 1:
        #     self.Trade()
        pass

    def OnSecuritiesChanged(self, changes):

        # Clean up data for removed securities and Liquidate
        for security in changes.RemovedSecurities:
            pass

        for security in changes.AddedSecurities:
            #if security.Symbol == self.spy: continue
            
            thirtyMinuteConsolidator = TradeBarConsolidator(timedelta(minutes=30))
            thirtyMinuteConsolidator.DataConsolidated += self.ThirtyMinuteHandler
        
            # Register consolidator to get automatically updated with minute data
            self.SubscriptionManager.AddConsolidator(security.Symbol, thirtyMinuteConsolidator)
            
            if security.Symbol not in self.macd:
                self.macd[security.Symbol] = MovingAverageConvergenceDivergence(12, 26, 9, MovingAverageType.Exponential)
                self.atr[security.Symbol] = AverageTrueRange(20, MovingAverageType.Simple)
                self.RegisterIndicator(security.Symbol, self.macd[security.Symbol], thirtyMinuteConsolidator, Field.Open)
                self.RegisterIndicator(security.Symbol, self.atr[security.Symbol], thirtyMinuteConsolidator)
                
        self.counter = len(self.macd.keys())
        
''' Manually warm up of a tradebar indicator '''
# history = algorithm.History(symbol, 14, Resolution.Daily)
# atr = algorithm.ATR(symbol, 14, MovingAverageType.Simple, Resolution.Daily)
# for tuple in history.loc[symbol].itertuples():
#     bar = TradeBar(tuple.Index, symbol, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume)
#     atr.Update(bar)