Backtest Lab

Strategy & Parameters

Strategies are TypeScript, written and saved in the Editor module, then run from Backtest's Configure tab. This page covers the shape of a strategy, what ctx gives you, and how parameter sweeps work.

Writing a strategy

A strategy exports onBar(bar, ctx) (called once per bar) and optionally init(ctx) (called once before the run — register indicators here so they're precomputed).

export const config = { params: { fast: 10, slow: 30 } };

export function init(ctx: StrategyContext) {
	// Register indicators once; the engine precomputes and caches the series.
	ctx.fast = ctx.indicator('sma', { period: ctx.params.fast ?? 10 });
	ctx.slow = ctx.indicator('sma', { period: ctx.params.slow ?? 30 });
}

export function onBar(bar: OHLCV, ctx: StrategyContext) {
	if (ctx.crossover(ctx.fast, ctx.slow) && ctx.position.isFlat) {
		ctx.buy({ qty: ctx.size.percentOfEquity(90) });
	} else if (ctx.crossunder(ctx.fast, ctx.slow) && ctx.position.isLong) {
		ctx.sell({ qty: ctx.position.qty });
	}
}

The one rule that matters most: fills happen at the NEXT bar's open. You decide on bar i, you get filled at bar i+1's open. There are no same-bar fills, which is what keeps results honest.

What's on ctx:

See the Strategy API reference for the full member list and every field's exact semantics.

Parameters and sweeps

A strategy declares its own parameters in config.params (as in the example above); Configure's Optimization group renders one row per declared parameter, seeded with the strategy's defaults. Names are read-only there — add or rename a parameter by editing the strategy source — but each row's sweep mode (fixed / list / range, with from/to/step) is set right in that row. The run count preview updates live — every param combination × every symbol becomes a run.

  • Grid vs. random search — grids explode fast; random search samples N combos from the grid (set with Samples). Use random when the preview count gets large.
  • Early stopping — Early stop aborts the sweep after N runs without leaderboard improvement (0 = off).
  • Results — sortable leaderboard (pick your columns; they persist), a threshold filter on any metric, and a param heatmap showing how a chosen metric varies across two chosen parameter axes. A strategy whose good region is one isolated cell is curve-fit; a broad plateau is a real edge.