Using indicators
Using indicators
Pull any SDK or built-in indicator into your strategy with a single factory call, and read its value bar by bar.
Using indicators
A strategy does not compute moving averages or ATR by hand — it reuses the same indicator types you
build elsewhere in the SDK. Declare one with DeclareIndicator(factory) inside
OnInitialize, passing a lambda that constructs and configures the indicator
(any IndicatorBase subclass). The framework feeds the instance the same bars your strategy
sees, so at runtime you just read its current value.
It takes a factory rather than a ready-made instance because of timing: the factory runs after parameter overrides are applied, so an indicator sized by a parameter picks up that run's value — which is what makes a declared indicator correct under an optimizer sweep, where each pass reconstructs it from that pass's overrides. A factory with a literal period works identically.
C#private StrategyIndicator<Sma> _sma = null!;
private StrategyIndicator<Atr> _atr = null!;
protected override void OnInitialize()
{
_sma = DeclareIndicator(() => new Sma { Period = _fastPeriod.Value }); // parameter-sized
_atr = DeclareIndicator(() => new Atr { Period = 14 });
}
protected override void OnBar()
{
double sma = _sma.Instance.Value; // Sma exposes a convenience .Value
double atr = _atr.Instance.Output[0]; // Atr publishes an ISeries<double> Output; [0] = latest
// ...
}
The handle & readiness
DeclareIndicator returns a typed StrategyIndicator<T> handle — hold
it in a field. You cannot be handed the indicator instance at declaration time because it does not exist
yet (the factory has not run). By the time OnStart runs, the runner has built
and backfilled every declared indicator over the run's pre-run history, so its values are
immediately usable. Read .Instance from OnStart onward; reading it earlier
(inside OnInitialize, or before the run started) throws rather than returning a half-built
indicator. IsReady is true once the instance is bound.
.Value (e.g. Sma.Value); others publish their
result as an ISeries<double> Output read with Output[0] for the latest
(e.g. Atr). Multi-plot indicators (MACD, Bollinger) expose one series per line. Check the
indicator type for which it offers — many provide both.
Guard your reads during warm-up. IsReady being true means the indicator is built, not that
it has enough bars to be meaningful — an SMA over 20 bars is not useful at bar 3. Gate on
BarCount before trusting a value.
new Sma { Period = _fastPeriod.Value } — and the optimizer
sweeps the indicator's period at no extra cost, since each run reconstructs the indicator from that run's
overrides.