Skip to main content

Documentation 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.

The candle-fetching functions are the primary data source for strategies. They use AsyncLocalStorage to read the current execution context (symbol, timestamp, backtest flag) and align all requests to the correct interval boundary automatically, making it impossible to accidentally introduce look-ahead bias. Results are backed by a persistent file-based cache (PersistCandleAdapter) — a cache hit means all expected timestamps were found; a miss triggers a fresh fetch from the registered exchange adapter.

ICandleData

All candle functions return arrays of ICandleData:
interface ICandleData {
  timestamp: number; // Unix ms — candle openTime (inclusive)
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
}
timestamp is always the openTime of the candle, not the close time. A candle at 00:00 for a 15-minute interval covers the period [00:00, 00:15).

getCandles

Fetch historical candles backwards from the current execution context timestamp.
getCandles(symbol: string, interval: CandleInterval, limit: number): Promise<ICandleData[]>
symbol
string
required
Trading pair symbol (e.g., "BTCUSDT").
interval
CandleInterval
required
Candle time interval. One of: "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h" | "12h" | "1d".
limit
number
required
Number of candles to return.
Alignment semantics:
  • alignedWhen = Math.floor(when / stepMs) * stepMs — rounded down to interval boundary.
  • since = alignedWhen - limit * stepMs (inclusive start).
  • alignedWhen is exclusive — the candle opening at that moment is still pending/incomplete and is never included.
  • Returns exactly limit fully-closed candles.
Works identically in backtest (uses virtual when from the frame iterator) and live (uses Date.now() aligned to the minute).

getNextCandles

Fetch candles forward from the current execution context timestamp. Backtest only.
getNextCandles(symbol: string, interval: CandleInterval, limit: number): Promise<ICandleData[]>
symbol
string
required
Trading pair symbol.
interval
CandleInterval
required
Candle time interval.
limit
number
required
Number of future candles to return.
getNextCandles throws an error in live mode to prevent look-ahead bias. It is only valid during backtest execution, where historical data guarantees the “future” candles are truly in the past.
alignedWhen is inclusive for getNextCandles — the first candle starts at the aligned timestamp. Range: [alignedWhen, alignedWhen + limit * stepMs).

getRawCandles

Fetch candles with flexible date range and limit combinations.
getRawCandles(
  symbol: string,
  interval: CandleInterval,
  limit?: number,
  sDate?: number,
  eDate?: number
): Promise<ICandleData[]>
symbol
string
required
Trading pair symbol.
interval
CandleInterval
required
Candle time interval.
limit
number
Optional number of candles to fetch.
sDate
number
Optional start date in milliseconds (inclusive after alignment).
eDate
number
Optional end date in milliseconds (exclusive — the candle opening at eDate is not included).
Valid parameter combinations:
limitsDateeDateBehaviour
limit candles backward from context when
limit candles forward from align(sDate)
limit candles ending before align(eDate)
All candles in [align(sDate), align(eDate))
limit candles starting at align(sDate)
All combinations enforce look-ahead bias protection: eDate or the calculated end timestamp must not exceed the current execution when.

getAveragePrice

Calculate the VWAP (Volume Weighted Average Price) from the last CC_AVG_PRICE_CANDLES_COUNT 1-minute candles (default: 5 candles).
getAveragePrice(symbol: string): Promise<number>
symbol
string
required
Trading pair symbol.
Formula: VWAP = Σ(typicalPrice × volume) / Σ(volume) where typicalPrice = (high + low + close) / 3. Falls back to a simple average of close prices if volume is zero.

Persistent Cache Behavior

The cache uses PersistCandleAdapter with a file-based backend by default. On every getCandles or getNextCandles call:
  1. Cache key is computed as the aligned since timestamp.
  2. Cache hit — all expected timestamps (since + i * stepMs for i = 0..limit-1) are present → returns cached candles immediately.
  3. Cache miss — any timestamp is absent → calls the exchange adapter’s getCandles implementation, validates the result (first candle must match since), then writes to cache.
Incomplete candles (where closeTime > now) are never written to cache. Switch the adapter with PersistCandleAdapter.useDummy() (disable caching) or PersistCandleAdapter.usePersistCandleAdapter(CustomCtor) (custom backend).

Cache Management Utilities

checkCandles

Validate that candles for a given date range are present in the persistent cache. Issues one ranged read — if any expected timestamp is missing, the check fails without loading the full dataset.
checkCandles(params: ICheckCandlesParams): Promise<void>
interface ICheckCandlesParams {
  symbol: string;
  exchangeName: string;
  interval: CandleInterval;
  from: Date;
  to: Date;
}
Throws if any candle in the requested range is absent from the cache.

warmCandles

Pre-populate the persistent cache for a symbol and interval by downloading all candles from from to to via the registered exchange adapter.
warmCandles(params: IWarmCandlesParams): Promise<void>
interface IWarmCandlesParams {
  symbol: string;
  exchangeName: string;
  interval: CandleInterval;
  from: Date;
  to: Date;
}
Use before running a backtest to ensure all required data is available locally without any live exchange calls during the backtest.

cacheCandles

Run a combined check-then-warm flow with one retry. First validates the cache; on a miss, downloads the missing data via warmCandles and re-validates. Lifecycle callbacks allow progress reporting.
cacheCandles(params: ICacheCandlesParams): Promise<void>
interface ICacheCandlesParams extends IWarmCandlesParams, ICheckCandlesParams {
  onCheckStart?: (symbol, interval, from, to) => void; // before validation phase
  onWarmStart?: (symbol, interval, from, to) => void;  // before warm-up phase
}
import { cacheCandles } from 'backtest-kit';

await cacheCandles({
  symbol: 'BTCUSDT',
  exchangeName: 'binance',
  interval: '1m',
  from: new Date('2025-01-01'),
  to: new Date('2025-02-01'),
  onWarmStart: (symbol, interval) => console.log(`Warming ${symbol} ${interval}…`),
});

Multi-Timeframe Example

import { addStrategySchema, getCandles, getAveragePrice } from 'backtest-kit';

addStrategySchema({
  strategyName: 'multi-tf-strategy',
  interval: '5m',
  getSignal: async (symbol) => {
    const [candles1h, candles15m, candles5m] = await Promise.all([
      getCandles(symbol, '1h', 24),   // last 24 hours
      getCandles(symbol, '15m', 48),  // last 12 hours
      getCandles(symbol, '5m', 60),   // last 5 hours
    ]);

    const vwap = await getAveragePrice(symbol);

    // ... indicator logic
    return null;
  },
});

Build docs developers (and LLMs) love