Backtest Kit uses Node.jsDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-kit-docs/llms.txt
Use this file to discover all available pages before exploring further.
AsyncLocalStorage to maintain a temporal execution context throughout the entire async call stack. Every function that runs inside a strategy tick — regardless of how deeply nested — automatically knows the current simulation timestamp, the active symbol, and whether the engine is in backtest or live mode. No parameter threading is required. The same strategy code runs identically in both environments.
What the Execution Context Contains
The execution context is a small, immutable record injected at the start of every tick:symbol
The trading pair currently being processed. When running multiple symbols in parallel, each async execution chain receives its own isolated context — there is no shared mutable state between symbols.
when
The authoritative timestamp for the current tick. In backtest mode this is the simulation time from the historical frame. In live mode it is the wall-clock
new Date() captured at the start of the tick. All candle and data queries are resolved relative to this value.backtest
A boolean flag that lets library internals and strategy helpers distinguish execution mode. Risk functions, persistence adapters, and candle fetchers all branch on this value to apply the correct behavior.
The Look-Ahead Bias Problem
Look-ahead bias is one of the most common and difficult-to-detect errors in backtesting systems. It occurs when a strategy accidentally uses data that would not have been available at the time of the decision — for example, callingnew Date() to determine “now” while simulating a trade from January.
In most frameworks, developers are expected to pass a timestamp parameter through every function call. This is error-prone: a single missed pass, a helper that ignores the parameter, or a third-party utility that calls Date.now() internally is enough to contaminate results.
Backtest Kit eliminates this failure mode at the infrastructure level. AsyncLocalStorage makes the when timestamp implicit. Every call to getCandles, getAveragePrice, getOrderBook, or any other time-sensitive API reads when from the context automatically — the developer never has a parameter to forget.
Automatic Temporal Resolution
The samegetCandles call produces correct results in both modes without any code change:
getCandles reads when from AsyncLocalStorage, aligns it to the requested interval boundary, computes since = alignedWhen - limit * stepMs, and fetches exactly limit closed candles. The caller never touches a timestamp.
Candle Timestamp Alignment
All candle queries align thewhen timestamp down to the nearest interval boundary before computing the fetch range. This prevents partial candles from contaminating indicator calculations.
alignedWhen (00:15:00 in this example) is excluded. At tick time 00:17:00, the 00:15:00 candle covers the period [00:15, 00:30) and is still open — its high, low, and close values are incomplete. Including it would mean the strategy sees partial OHLCV data that doesn’t reflect final price action for that period.
Only fully closed candles are returned. This rule is enforced identically for getCandles, getRawCandles, and all cache reads and writes.
Multi-Timeframe Synchronization
Because all intervals are aligned relative to the samewhen value, multi-timeframe queries are automatically synchronized. Requesting 1h, 15m, and 5m candles in the same tick produces three arrays that are all anchored to the same logical point in time, with no off-by-one errors between timeframes.
when-aligned temporal reference.
Context Propagation in Parallel Backtests
When running multiple symbols concurrently withBacktest.background, each symbol operates in its own isolated AsyncLocalStorage context. The engine wraps each tick in ExecutionContextService.runInContext, scoping { symbol, when, backtest } to that specific async execution chain. Parallel symbol backtests cannot read or overwrite each other’s context.
ExecutionContextService wrapping MethodContextService — ensures that schema lookups (strategy name, exchange name, frame name) are also scoped correctly per execution chain.