I am using the algorithm framework and on main.py I am trying to find 14 day RSI of SPY to use as one of several indicators of market conditions, others to be added later, which will determine model set used for alpha, universe, etc. but the RSI determination is not working. QC appears to be using LEAN v2.5.0.0.17034.  I set a 14-period daily RSI for SPY with TradeBarConsolidator and RegisterIndicator should be IsReady=True with ~36.55 on 2018-12-31 (Yahoo adjusted closes, 4 up/9 down days over 14 periods), but stays IsReady=False at Samples=14, crashing post-warm-up on 2019-01-03. Code uses standard v2 setup—expecting RSI ready after 14 daily bars from consolidator. Is this a v2.5 RSI bug? How do I make RSI work without crashing?

 

# region imports
from AlgorithmImports import *
from universe import (StrongBullUniverseModel, WeakBullUniverseModel, SidewaysUpUniverseModel,
                     SidewaysDownUniverseModel, WeakBearUniverseModel, StrongBearUniverseModel)
from alpha import (StrongBullAlphaModel, WeakBullAlphaModel, SidewaysUpAlphaModel,
                  SidewaysDownAlphaModel, WeakBearAlphaModel, StrongBearAlphaModel)
from portfolio import (StrongBullPortfolioModel, WeakBullPortfolioModel, SidewaysUpPortfolioModel,
                      SidewaysDownPortfolioModel, WeakBearPortfolioModel, StrongBearPortfolioModel)
from risk import (StrongBullRiskModel, WeakBullRiskModel, SidewaysUpRiskModel,
                 SidewaysDownRiskModel, WeakBearRiskModel, StrongBearRiskModel)
from execution import (StrongBullExecutionModel, WeakBullExecutionModel, SidewaysUpExecutionModel,
                      SidewaysDownExecutionModel, WeakBearExecutionModel, StrongBearExecutionModel)
# endregion

class MatrixMarketAlgo(QCAlgorithm):
    def initialize(self):
        self.set_start_date(2019, 1, 1)
        self.set_end_date(2019, 1, 7)
        self.set_cash(100000)
        
        self.UniverseSettings.Resolution = Resolution.Daily
        self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
        
        self.rsi = self.RSI(self.spy, 14, Resolution.Daily)
        consolidator = TradeBarConsolidator(TimeSpan.FromDays(1))
        consolidator.DataConsolidated += self.on_consolidated_data
        self.SubscriptionManager.AddConsolidator(self.spy, consolidator)
        self.RegisterIndicator(self.spy, self.rsi, consolidator)
        
        self.SetWarmUp(14, Resolution.Daily)
        
        self.market_condition = None
        self.prev_condition = None
        
        self.universe_models = {
            "strong_bull": StrongBullUniverseModel(), "weak_bull": WeakBullUniverseModel(),
            "sideways_up": SidewaysUpUniverseModel(), "sideways_down": SidewaysDownUniverseModel(),
            "weak_bear": WeakBearUniverseModel(), "strong_bear": StrongBearUniverseModel()
        }
        self.alpha_models = {
            "strong_bull": StrongBullAlphaModel(), "weak_bull": WeakBullAlphaModel(),
            "sideways_up": SidewaysUpAlphaModel(), "sideways_down": SidewaysDownAlphaModel(),
            "weak_bear": WeakBearAlphaModel(), "strong_bear": StrongBearAlphaModel()
        }
        self.portfolio_models = {
            "strong_bull": StrongBullPortfolioModel(), "weak_bull": WeakBullPortfolioModel(),
            "sideways_up": SidewaysUpPortfolioModel(), "sideways_down": SidewaysDownPortfolioModel(),
            "weak_bear": WeakBearPortfolioModel(), "strong_bear": StrongBearPortfolioModel()
        }
        self.risk_models = {
            "strong_bull": StrongBullRiskModel(), "weak_bull": WeakBullRiskModel(),
            "sideways_up": SidewaysUpRiskModel(), "sideways_down": SidewaysDownRiskModel(),
            "weak_bear": WeakBearRiskModel(), "strong_bear": StrongBearRiskModel()
        }
        self.execution_models = {
            "strong_bull": StrongBullExecutionModel(), "weak_bull": WeakBullExecutionModel(),
            "sideways_up": SidewaysUpExecutionModel(), "sideways_down": SidewaysDownExecutionModel(),
            "weak_bear": WeakBearExecutionModel(), "strong_bear": StrongBearExecutionModel()
        }
        
        self.universe_model = self.universe_models["strong_bull"]
        self.alpha_model = self.alpha_models["strong_bull"]
        self.portfolio_model = self.portfolio_models["strong_bull"]
        self.risk_model = self.risk_models["strong_bull"]
        self.execution_model = self.execution_models["strong_bull"]
        
        self.AddUniverseSelection(self.universe_model)
        self.AddAlpha(self.alpha_model)
        self.SetPortfolioConstruction(self.portfolio_model)
        self.SetRiskManagement(self.risk_model)
        self.SetExecution(self.execution_model)
        
        self.Schedule.On(self.DateRules.EveryDay(self.spy), self.TimeRules.At(16, 30), self.update_market_and_models)

    def on_consolidated_data(self, sender, bar):
        self.Debug(f"Consolidator at {bar.EndTime}: SPY Close={bar.Close}, RSI - Samples={self.rsi.Samples}, IsReady={self.rsi.IsReady}, Value={self.rsi.Current.Value if self.rsi.IsReady else 'N/A'}")

    def update_market_and_models(self):
        if self.IsWarmingUp:
            return
        
        self.Debug(f"Update at {self.Time}: RSI - IsReady={self.rsi.IsReady}, Value={self.rsi.Current.Value if self.rsi.IsReady else 'N/A'}")
        if self.rsi.IsReady:
            rsi_value = self.rsi.Current.Value
            if rsi_value >= 90:
                self.market_condition = "strong_bull"
            elif rsi_value >= 70:
                self.market_condition = "weak_bull"
            elif rsi_value >= 50:
                self.market_condition = "sideways_up"
            elif rsi_value >= 30:
                self.market_condition = "sideways_down"
            elif rsi_value >= 10:
                self.market_condition = "weak_bear"
            else:
                self.market_condition = "strong_bear"
        else:
            self.market_condition = None
        
        if self.market_condition is None:
            self.Log("ERROR: Market condition is None - insufficient data or RSI not ready")
            raise Exception("Market condition calculation failed - stopping algo")
        
        if self.prev_condition is not None and self.market_condition != self.prev_condition:
            self.Log(f"ALERT: Market condition changed from {self.prev_condition} to {self.market_condition}")
        
        self.universe_model = self.universe_models[self.market_condition]
        self.alpha_model = self.alpha_models[self.market_condition]
        self.portfolio_model = self.portfolio_models[self.market_condition]
        self.risk_model = self.risk_models[self.market_condition]
        self.execution_model = self.execution_models[self.market_condition]
        
        self.SetUniverseSelection(self.universe_model)
        self.SetAlpha(self.alpha_model)
        self.SetPortfolioConstruction(self.portfolio_model)
        self.SetRiskManagement(self.risk_model)
        self.SetExecution(self.execution_model)
        
        self.Log(f"Market condition set to: {self.market_condition}")
        self.prev_condition = self.market_condition

    def on_data(self, data):
        if self.spy in data and data[self.spy] is not None:
            self.Debug(f"on_data at {self.Time}: SPY Close={data[self.spy].Close}, RSI - Samples={self.rsi.Samples}, IsReady={self.rsi.IsReady}, Value={self.rsi.Current.Value if self.rsi.IsReady else 'N/A'}")
        
        self.Log(f"ON_DATA START: Slice at {self.Time}, Market: {self.market_condition}")
        for symbol in self.universe_model.symbols:
            if data.ContainsKey(symbol):
                self.Debug(f"on_data: {symbol.Value} received")
        insights = self.alpha_model.Update(self, data)
        targets = self.portfolio_model.CreateTargets(self, insights)
        adjusted_targets = self.risk_model.ManageRisk(self, targets)
        self.execution_model.Execute(self, adjusted_targets)
        self.Log(f"ON_DATA END: Slice processed")