DocsErrors
Runtime Errors
Runtime errors happen after your code passes validation but fails during execution. The backtest stops and the error is reported with a stack trace.
TypeError: Cannot read properties of undefined
TypeError: Cannot read properties of undefined (reading '14')
Common cause: Accessing an indicator that was not declared in init().
function init(ctx) { ctx.indicator('sma', 'SMA', { period: 20 }); } function onBar(ctx, i) { // Wrong — 'ema' was never declared const val = ctx.ind.ema[i]; // TypeError: ctx.ind.ema is undefined // Correct — use the name from init() const val = ctx.ind.sma[i]; }
ReferenceError: variable is not defined
ReferenceError: threshold is not defined
Common cause: Using a parameter name directly instead of ctx.p.name.
// Wrong — bare variable if (ctx.ind.rsi[i] < threshold) { } // Correct — access via ctx.p if (ctx.ind.rsi[i] < ctx.p.threshold) { }
NaN Results
Your strategy runs but produces no trades or strange values.
Common cause: Using an indicator before it has enough data.
function onBar(ctx, i) { // An SMA(20) is NaN for the first 19 bars // Always guard against NaN if (q.isNaN(ctx.ind.sma[i])) return; // Now safe to use if (ctx.series.close[i] > ctx.ind.sma[i]) { ctx.order.market('ASSET', 1); } }
No Trades Generated
Your strategy runs without errors but produces zero trades.
Checklist:
- Are conditions too strict? — Print intermediate values or simplify the logic
- Is the guard too broad? — If you return early on NaN, make sure you only check the indicators that matter
- Wrong signal direction? — In LONG_ONLY mode, short signals are ignored
- Already in position? — Check if you're trying to enter when already holding
- Date range too short? — Ensure enough bars for indicators to warm up
Dry Run Validation
When you save a strategy, the platform runs a dry run — a short execution against a small sample of candles. If the dry run crashes, you will see the runtime error before submitting a full backtest. Fix the error shown in the dry run output.
Debugging Tips
- Start with a minimal strategy and add complexity gradually
- Use
ctx.stateto track intermediate values you can inspect in trade metadata - Add signal metadata:
ctx.order.market('ASSET', 1, { signal: 'buy', rsi: ctx.ind.rsi[i] }) - Test with a narrow date range first to iterate quickly
runtimeTypeErrorReferenceErrorundefinedNaNcrashdebug