Python: register_indicator fails for SimpleMovingAverage with TradeBarConsolidator — "Indicator.value must be implemented"
Summary
Calling register_indicator(symbol, SimpleMovingAverage(n), TradeBarConsolidator) in a Python algorithm now throws a NotImplementedException during backtest initialization. The same code succeeds when a live deployment was launched ~3 weeks ago, but new backtests on an identical code path fail today. This appears to be a recent regression in the backtest engine.
Error
During the algorithm initialization, the following exception has occurred:
Indicator.value must be implemented. Please implement this missing method in SimpleMovingAverage
at initialize
self.register_indicator(self.es, ind, self.cons_5m)
in main.py: line 100
Reproduction (minimal)
from AlgorithmImports import *
from datetime import timedelta
class TestAlgo(QCAlgorithm):
def initialize(self):
self.set_start_date(2026, 1, 1)
self.set_end_date(2026, 6, 1)
self.set_cash(100_000)
future = self.add_future(Futures.Indices.SP_500_E_MINI, resolution=Resolution.MINUTE)
future.set_filter(0, 90)
es = future.symbol
cons_5m = TradeBarConsolidator(timedelta(minutes=5))
cons_5m.data_consolidated += self.on_5min_bar
self.subscription_manager.add_consolidator(es, cons_5m)
sma = SimpleMovingAverage(20)
self.register_indicator(es, sma, cons_5m) # <-- crashes here
def on_5min_bar(self, sender, bar):
pass
Root cause analysis
QCAlgorithm.Python.cs — ConvertPythonIndicator() is supposed to TryConvert<IndicatorBase> the PyObject:
private IndicatorBase ConvertPythonIndicator(PyObject pyIndicator)
{
IndicatorBase convertedIndicator;
if (pyIndicator.TryConvert(out PythonIndicator pythonIndicator))
{
convertedIndicator = WrapPythonIndicator(pyIndicator, pythonIndicator);
}
else if (!pyIndicator.TryConvert(out convertedIndicator))
{
convertedIndicator = WrapPythonIndicator(pyIndicator); // reached here for SMA
}
return convertedIndicator;
}
If TryConvert<IndicatorBase> now fails for SimpleMovingAverage, execution falls through to WrapPythonIndicator(pyIndicator) → new PythonIndicator(pyObject) → SetIndicator().
SetIndicator() checks for IsReady, Update, Value attributes. IndicatorBase has no direct Value property — only Current (which has Value). So HasAttr("Value") || HasAttr("value") returns false and throws NotImplementedException.
The name "SimpleMovingAverage" in the error (not "SMA(20)") confirms GetIndicatorName fell back to __class__.__name__, meaning the C# Name property was not reachable via the Python bindings at the time SetIndicator was called.
Notably, ExponentialMovingAverage and RelativeStrengthIndex registered earlier in the same loop succeed — the regression appears to be specific to SimpleMovingAverage (or possibly WindowIndicator<IndicatorDataPoint> subclasses).
Evidence of regression (not customer code bug)
- A live deployment (L-21a7579fdc93f6cde6b4360fa9b91617) launched 2026-05-25 with an identical
register_indicator(es, SimpleMovingAverage(20), cons_5m) call is currently running without error.
- The only code difference between the deployed (working) version and the current (failing) version is
set_start_date(2022, …) vs set_start_date(2026, …) — the register_indicator loop is byte-for-byte identical.
- This indicates a change in the backtest engine between May 25 and June 12 broke the Python →
IndicatorBase<IndicatorDataPoint> type conversion for SimpleMovingAverage.
Intercom conversation
215474661265601
Workaround (for affected customers)
Remove the SimpleMovingAverage from the register_indicator call and manually update it in the consolidator handler:
# In initialize — remove SMA from the auto-register loop
for ind in [self.ema_9, ...]: # vol_sma excluded
self.register_indicator(es, ind, cons_5m)
# In the consolidator handler — update SMA manually
def on_5min_bar(self, sender, bar):
self.vol_sma.update(bar.end_time, bar.volume) # or bar.close for price SMA
...
Python:
register_indicatorfails forSimpleMovingAveragewithTradeBarConsolidator— "Indicator.value must be implemented"Summary
Calling
register_indicator(symbol, SimpleMovingAverage(n), TradeBarConsolidator)in a Python algorithm now throws aNotImplementedExceptionduring backtest initialization. The same code succeeds when a live deployment was launched ~3 weeks ago, but new backtests on an identical code path fail today. This appears to be a recent regression in the backtest engine.Error
Reproduction (minimal)
Root cause analysis
QCAlgorithm.Python.cs—ConvertPythonIndicator()is supposed toTryConvert<IndicatorBase>the PyObject:If
TryConvert<IndicatorBase>now fails forSimpleMovingAverage, execution falls through toWrapPythonIndicator(pyIndicator)→new PythonIndicator(pyObject)→SetIndicator().SetIndicator()checks forIsReady,Update,Valueattributes.IndicatorBasehas no directValueproperty — onlyCurrent(which hasValue). SoHasAttr("Value") || HasAttr("value")returns false and throwsNotImplementedException.The name "SimpleMovingAverage" in the error (not "SMA(20)") confirms
GetIndicatorNamefell back to__class__.__name__, meaning the C#Nameproperty was not reachable via the Python bindings at the timeSetIndicatorwas called.Notably,
ExponentialMovingAverageandRelativeStrengthIndexregistered earlier in the same loop succeed — the regression appears to be specific toSimpleMovingAverage(or possiblyWindowIndicator<IndicatorDataPoint>subclasses).Evidence of regression (not customer code bug)
register_indicator(es, SimpleMovingAverage(20), cons_5m)call is currently running without error.set_start_date(2022, …)vsset_start_date(2026, …)— theregister_indicatorloop is byte-for-byte identical.IndicatorBase<IndicatorDataPoint>type conversion forSimpleMovingAverage.Intercom conversation
215474661265601
Workaround (for affected customers)
Remove the
SimpleMovingAveragefrom theregister_indicatorcall and manually update it in the consolidator handler: