Overall Statistics
Total Trades
1078
Average Win
0.78%
Average Loss
-0.79%
Compounding Annual Return
4.340%
Drawdown
22.600%
Expectancy
0.045
Net Profit
17.419%
Sharpe Ratio
0.334
Probabilistic Sharpe Ratio
6.030%
Loss Rate
47%
Win Rate
53%
Profit-Loss Ratio
0.98
Alpha
0.007
Beta
0.235
Annual Standard Deviation
0.107
Annual Variance
0.011
Information Ratio
-0.529
Tracking Error
0.167
Treynor Ratio
0.152
Total Fees
$3528.72
Estimated Strategy Capacity
$7900000.00
Lowest Capacity Asset
MSFT R735QTJ8XC9X
class EmotionalFluorescentPinkSalmon(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2018, 1, 1)
        self.SetEndDate(2021, 11, 1)
        self.SetCash(100000)
        
        self.atrs = {}
        self.tickers = {}

        symbols = ["AMZN", "MSFT", "AAPL"]
        
        for ticker in symbols:
            self.tickers[ticker] = symbolData(self, ticker)
        
        # Compare the warmed up values
        self.tickers = {k: v for k, v in sorted(self.tickers.items(), 
                                                key=lambda item: item[1].atrOverPrice.Current.Value, 
                                                reverse=True)[:1]}
        
        
        self.portfolio_targets = []
        
        for stock, value in self.tickers.items():
            self.portfolio_targets.append(value.symbol)
                
        self.spy = self.AddEquity("SPY", Resolution.Minute).Symbol
        self.yest_close = self.Identity(self.spy, Resolution.Daily, Field.Close)
        self.SetWarmUp(1, Resolution.Daily)
            
    def OnData(self, data):
        
        if self.IsWarmingUp or not self.yest_close.IsReady or not len(data.Bars) > 0: 
            return 
        
        # If SPY is above yesterday's close at 9:45, go long the stock in ticker_symbols
        if self.Time.hour == 9 and self.Time.minute == 45:
            for stock in self.portfolio_targets:
                price = self.Securities[self.spy].Price
                yest_close = self.yest_close.Current.Value
            
                if price > yest_close:
                    self.SetHoldings(stock, 1/len(self.portfolio_targets))
        
        if self.Time.hour == 15 and self.Time.minute == 45:
            self.Liquidate()
            
class symbolData:
    
    def __init__(self, algo, ticker):
        self.symbol = algo.AddEquity(ticker, Resolution.Minute).Symbol
        
        self.atr = algo.ATR(self.symbol, 14, MovingAverageType.Simple, Resolution.Minute)
        self.id = algo.Identity(self.symbol, Resolution.Daily, Field.Close)
        self.atrOverPrice = IndicatorExtensions.Over(self.atr, self.id)
        
        # Warm up ATR
        history = algo.History(self.symbol, 14, Resolution.Minute)
        for bar in history.itertuples():
            tradeBar = TradeBar(bar.Index[1], bar.Index[0], bar.open, bar.high, 
                                bar.low, bar.close, bar.volume)
            self.atr.Update(tradeBar)
            
        # Warm up Identity, since it should be using 2-day-prior close price
        history = algo.History(self.symbol, 2, Resolution.Daily).iloc[0]
        self.id.Update(pd.to_datetime(history.name[1]), history.close)
        
        # IndicatorExtension will update automatically