DocsStrategy APIlifecycle

init()

Declare indicators and initialize state. Called once before the backtest starts.

Signature

function init(ctx)

Parameters

NameTypeDescription
ctxInitContextContext for indicator declaration and state

ctx.indicator()

Declare indicators that will be pre-computed by the engine:

ctx.indicator(name, type, options)
ArgumentTypeDescription
namestringUnique name to access via ctx.ind.name
typestringIndicator type (see available indicators)
optionsobjectIndicator-specific options

Key insight: Indicators are computed by the engine on the host side before onBar runs. This is much faster than computing them yourself.

Display Option

Add display: true to show the indicator on the chart:

// This indicator will appear on the price chart ctx.indicator('ema', 'EMA', { period: 21, source: 'close', display: true }); // This indicator is computed but NOT shown on chart (default) ctx.indicator('rsi', 'RSI', { period: 14 });

Example

function init(ctx) { // Trend indicators - shown on chart ctx.indicator('fastEma', 'EMA', { period: ctx.p.fastLength, source: 'close', display: true }); ctx.indicator('slowEma', 'EMA', { period: ctx.p.slowLength, source: 'close', display: true }); // Momentum - not displayed (used for signal logic only) ctx.indicator('rsi', 'RSI', { period: 14 }); ctx.indicator('macd', 'MACD', { fastPeriod: 12, slowPeriod: 26, signalPeriod: 9 }); // Volatility ctx.indicator('atr', 'ATR', { period: 14 }); ctx.indicator('bbands', 'BBANDS', { period: 20, stdDev: 2 }); // Initialize state ctx.state.tradeCount = 0; ctx.state.lastSignalBar = -1; ctx.state.inPosition = false; }

Available Indicators

Moving Averages

IndicatorOptionsOutput
SMAperiod, sourcenumber[]
EMAperiod, sourcenumber[]
WMAperiod, sourcenumber[]
DEMAperiod, sourcenumber[]
TEMAperiod, sourcenumber[]

Trend

IndicatorOptionsOutput
MACDfastPeriod, slowPeriod, signalPeriod{ line, signal, histogram }
ADXperiod{ adx, pdi, mdi }
PSARstep, maxnumber[]
ICHIMOKUtenkanPeriod, kijunPeriod, senkouBPeriod{ tenkan, kijun, senkouA, senkouB, chikou }
TRIXperiod, sourcenumber[]

Momentum / Oscillators

IndicatorOptionsOutput
RSIperiod, sourcenumber[]
STOCHkPeriod, dPeriod{ k, d }
STOCHRSIrsiPeriod, stochPeriod, kPeriod, dPeriod{ k, d }
CCIperiodnumber[]
WILLIAMSRperiodnumber[]
ROCperiod, sourcenumber[]
AOfastPeriod, slowPeriodnumber[]
PPOshortGamma, longGamma, accuracynumber[]

Volatility

IndicatorOptionsOutput
BBANDSperiod, stdDev{ upper, middle, lower }
ATRperiodnumber[]
DONCHIANperiod{ upper, middle, lower }
KELTNERperiod, multiplier{ upper, middle, lower }

Volume

IndicatorOptionsOutput
OBVnumber[]
MFIperiodnumber[]
VWAPnumber[]
ADLnumber[]

Source Options

The source option can be:

  • 'open', 'high', 'low', 'close', 'volume'
  • 'hl2' — (high + low) / 2
  • 'hlc3' — (high + low + close) / 3
  • 'ohlc4' — (open + high + low + close) / 4

ctx.state

Initialize mutable state that persists across bars:

function init(ctx) { ctx.state.consecutiveLosses = 0; ctx.state.peakEquity = 0; ctx.state.lastEntryPrice = null; }

State is accessed in onBar via ctx.state:

function onBar(ctx, i) { ctx.state.consecutiveLosses++; }

Multi-Output Indicators

Some indicators return multiple series:

function init(ctx) { ctx.indicator('macd', 'MACD', { fastPeriod: 12, slowPeriod: 26, signalPeriod: 9 }); ctx.indicator('bbands', 'BBANDS', { period: 20, stdDev: 2 }); } function onBar(ctx, i) { // Access MACD components const macdLine = ctx.ind.macd.macd[i]; const signalLine = ctx.ind.macd.signal[i]; const histogram = ctx.ind.macd.histogram[i]; // Access Bollinger Bands const upper = ctx.ind.bbands.upper[i]; const middle = ctx.ind.bbands.middle[i]; const lower = ctx.ind.bbands.lower[i]; }

Common Mistakes

Computing indicators in onBar

// WRONG - Don't compute indicators yourself function onBar(ctx, i) { const ema = calculateEma(ctx.series.close, 20); // Slow! } // RIGHT - Declare in init, engine computes them function init(ctx) { ctx.indicator('ema', 'EMA', { period: 20 }); }

Forgetting to initialize state

// WRONG - state.count is undefined on first bar function onBar(ctx, i) { ctx.state.count++; // NaN! } // RIGHT - Initialize in init function init(ctx) { ctx.state.count = 0; }

Related

lifecycleinitindicatorsstateqsl