Backtest Kit uses Node.jsDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/theonetrade/backtest-kit/llms.txt
Use this file to discover all available pages before exploring further.
AsyncLocalStorage (via ExecutionContextService) to implicitly carry the current virtual timestamp — when — into every candle request. You never pass a timestamp yourself; the framework reads it from the async execution context and aligns it down to the nearest interval boundary before calculating the window to fetch. The same code path works unchanged in both backtest mode (where when comes from the timeframe iterator) and live mode (where when is new Date()), making look-ahead bias structurally impossible.
getCandles — historical window ending before when
limit closed candles ending before the current aligned time. The pending (incomplete) candle at alignedWhen is always excluded.
Timestamp math:
getCandles("BTCUSDT", "15m", 4) at when = 00:12:00:
00:00:00 is NOT returned as an additional result — it is alignedWhen itself, which is exclusive. The last returned candle has timestamp = 23:45:00.
getNextCandles — forward window (backtest only)
limit candles starting from alignedWhen, going forward. Used internally by BacktestLogicPrivateService to simulate how a signal plays out after entry.
getRawCandles — flexible combinations
eDate <= when to prevent look-ahead:
| Parameters | Behaviour |
|---|---|
(limit) | since = alignedWhen - limit * stepMs, range [since, alignedWhen) |
(limit, sDate) | since = align(sDate), fetch limit forward from there |
(limit, undefined, eDate) | since = align(eDate) - limit * stepMs, range [since, eDate) |
(undefined, sDate, eDate) | since = align(sDate), limit calculated from range |
(limit, sDate, eDate) | since = align(sDate), returns limit candles |
Alignment in detail — the 15-minute example
Every request first aligns the reference timestamp down to the nearest interval boundary:alignedWhen (00:00:00) is exclusive — the candle covering [00:00, 00:15) is still open at when = 00:12:00 and is not returned.
The
timestamp field on every candle is its openTime, not closeTime. A candle with timestamp = 00:00:00 and a 15-minute step covers the period [00:00, 00:15) — it closes at 00:15.Supported intervals
| Interval | Step |
|---|---|
"1m" | 60 000 ms |
"3m" | 180 000 ms |
"5m" | 300 000 ms |
"15m" | 900 000 ms |
"30m" | 1 800 000 ms |
"1h" | 3 600 000 ms |
"2h" | 7 200 000 ms |
"4h" | 14 400 000 ms |
"6h" | 21 600 000 ms |
"8h" | 28 800 000 ms |
"12h" | 43 200 000 ms |
"1d" | 86 400 000 ms |
Persistent cache
Backtest Kit maintains a per-symbol/per-interval/per-exchange on-disk candle cache (viaPersistCandleAdapter). On every getCandles or getRawCandles call:
- The cache lookup computes expected timestamps:
since + i * stepMsfori = 0..limit-1 - If all expected timestamps are present → return cached candles immediately (no API call)
- If any timestamp is missing → fetch from the exchange, write to cache, return fresh data
openTime. Incomplete candles (where closeTime > now) are never written to cache, ensuring cache entries are always final OHLCV data.
getOrderBook — aligned time window
Order book fetching uses the same AsyncLocalStorage context but aligns to a configurable offset window rather than a candle interval:
when = 00:12:00 UTC:
(symbol, depth, from, to, backtest) where depth defaults to CC_ORDER_BOOK_MAX_DEPTH_LEVELS. In live mode the from/to range is typically ignored and the adapter fetches the current order book snapshot.
Most exchanges (e.g. Binance
GET /api/v3/depth) only expose the current order book with no historical query support. For backtesting you must supply your own snapshot storage and implement the getOrderBook function in your exchange schema to query it.getAggregatedTrades — 1-minute aligned pagination
Aggregated trades always align to down to the 1-minute boundary to prevent future trades leaking in:
limit, one full window is returned. With limit, the function paginates backwards in CC_AGGREGATED_TRADES_MAX_MINUTES chunks until at least limit trades are collected, then slices to the most recent limit.
Example — 200 trades with 60-minute window, when = 00:12:00 UTC:
Timezone warning
All alignment uses UTC (Unix epoch). For intervals like4h, boundaries are 00:00, 04:00, 08:00, 12:00, 16:00, 20:00 UTC. If your local timezone offset is not a multiple of the interval step, timestamps in logs may appear uneven in local time but are perfectly aligned in UTC.
toUTCString() or toISOString() when logging timestamps to always see the actual aligned UTC time.