Skip to main content

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

All data fetching functions in Backtest Kit automatically read the current execution context timestamp from Node.js AsyncLocalStorage. This means you never pass a when or timestamp argument — the framework injects it automatically based on the current backtest tick or live clock. In backtest mode this is the simulated candle time; in live mode it is new Date(). The result is that look-ahead bias is structurally impossible: no function can return data from the future relative to the current execution context.
All candle timestamp boundaries are UTC-based. For intervals like 4h, boundaries fall at 00:00, 04:00, 08:00, 12:00, 16:00, 20:00 UTC. If your local timezone is not a multiple of the interval, timestamps may appear uneven when printed in local time — use .toUTCString() or .toISOString() to inspect the actual alignment.

getCandles(symbol, interval, limit)

Returns limit fully-closed candles ending before the current execution context time. The pending (currently forming) candle at the aligned boundary is always excluded — it has incomplete OHLCV data and would distort indicators.
import { getCandles } from 'backtest-kit';

// Inside getSignal, onActivePing, or any strategy callback:
const candles1h  = await getCandles('BTCUSDT', '1h', 24);   // last 24 closed 1h candles
const candles15m = await getCandles('BTCUSDT', '15m', 48);  // last 48 closed 15m candles
const candles1m  = await getCandles('BTCUSDT', '1m', 60);   // last 60 closed 1m candles
symbol
string
required
Trading pair symbol passed verbatim to the exchange adapter’s getCandles function.
interval
string
required
Candle interval. Supported values: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M.
limit
number
required
Number of closed candles to return. The adapter must return exactly this many candles.
Returns: Promise<ICandleData[]> — array of limit candles, ordered oldest to newest. Each candle has: timestamp (open time in ms), open, high, low, close, volume.

Timestamp alignment math

The engine aligns when down to the interval boundary and excludes the pending candle:
// For interval = '15m', stepMs = 15 * 60_000 = 900_000
// when = 1704067920000  (00:12:00 UTC)

alignedWhen = Math.floor(when / stepMs) * stepMs
// = Math.floor(1704067920000 / 900000) * 900000
// = 1704067200000  (00:00:00 UTC)

since = alignedWhen - limit * stepMs
// e.g. limit=4: since = 1704067200000 - 4 * 900000 = 1704063600000  (23:00:00 UTC)

// Returned range: [since, alignedWhen)
// Candle at alignedWhen (00:00:00) is EXCLUDED — it is the pending candle
The adapter contract requires that:
  1. The first candle’s timestamp equals since exactly
  2. Exactly limit candles are returned
  3. Candle timestamps are sequential: since + i * stepMs for i = 0 .. limit-1

getNextCandles(symbol, interval, limit)

Returns limit candles starting from the current execution context time (forward-looking). The first candle starts at alignedWhen — the current aligned boundary — and subsequent candles go forward in time.
getNextCandles is only valid in backtest mode. In live mode it throws immediately, because future candles do not exist. Use it only in backtest callbacks for simulating trade duration (e.g. passing minuteEstimatedTime candles to custom analysis code).
// Only valid inside Backtest.run() or Backtest.background() callbacks:
const futureCandles = await getNextCandles('BTCUSDT', '1m', 60);
// Returns the next 60 1m candles starting from current backtest tick
symbol
string
required
Trading pair symbol.
interval
string
required
Candle interval.
limit
number
required
Number of forward-looking candles to return.
Returns: Promise<ICandleData[]>limit candles ordered oldest to newest, starting from the current aligned boundary (inclusive).

getRawCandles(symbol, interval, limit?, sDate?, eDate?)

Flexible candle retrieval with multiple parameter combinations. All combinations respect look-ahead bias protection — the eDate or computed end is clamped to alignedWhen.
import { getRawCandles } from 'backtest-kit';

// (1) Equivalent to getCandles — last 100 closed candles
const candles = await getRawCandles('BTCUSDT', '1h', 100);

// (2) 100 candles starting from a specific date
const fromStart = await getRawCandles('BTCUSDT', '1h', 100, new Date('2025-01-01'));

// (3) 100 candles ending at a specific date (exclusive)
const toEnd = await getRawCandles('BTCUSDT', '1h', 100, undefined, new Date('2025-06-01'));

// (4) All candles in a date range (sDate inclusive, eDate exclusive)
const inRange = await getRawCandles('BTCUSDT', '1h', undefined, new Date('2025-01-01'), new Date('2025-06-01'));
symbol
string
required
Trading pair symbol.
interval
string
required
Candle interval.
limit
number
Number of candles to return. When omitted with both sDate and eDate, the limit is inferred from the date range.
sDate
Date
Start date (inclusive). When provided with limit, returns limit candles starting from align(sDate).
eDate
Date
End date (exclusive). When provided with limit, returns limit candles ending before align(eDate).
Returns: Promise<ICandleData[]>

getOrderBook(symbol, depth?)

Returns an order book snapshot aligned to the CC_ORDER_BOOK_TIME_OFFSET_MINUTES boundary. The from/to window passed to the exchange adapter is exactly one offsetMinutes period wide.
import { getOrderBook } from 'backtest-kit';

const book = await getOrderBook('BTCUSDT', 20); // top 20 bid/ask levels
console.log(book.bids[0].price, book.asks[0].price);
symbol
string
required
Trading pair symbol.
depth
number
Number of order book levels to return. Defaults to CC_ORDER_BOOK_MAX_DEPTH_LEVELS from config.
Returns: Promise<IOrderBookData>{ symbol, bids: IBidData[], asks: IBidData[] }. Each IBidData has price: string and quantity: string. Requires: getOrderBook must be defined in the active exchange schema (addExchangeSchema). If not defined, this call throws a runtime error.

getAggregatedTrades(symbol, limit?)

Returns aggregated trade records from the exchange, aligned to the 1-minute boundary. Without limit, returns one full window of CC_AGGREGATED_TRADES_MAX_MINUTES duration. With limit, paginates backwards until at least limit trades are collected, then slices to the most recent limit.
import { getAggregatedTrades } from 'backtest-kit';

// All trades in the last CC_AGGREGATED_TRADES_MAX_MINUTES window
const allTrades = await getAggregatedTrades('BTCUSDT');

// Most recent 500 trades (paginating backwards if needed)
const recentTrades = await getAggregatedTrades('BTCUSDT', 500);
symbol
string
required
Trading pair symbol.
limit
number
Maximum number of trades to return. If the most recent window has fewer trades than limit, the function paginates backwards automatically.
Returns: Promise<IAggregatedTradeData[]> — each entry has price, quantity, timestamp, isBuyerMaker: boolean, and id. Requires: getAggregatedTrades must be defined in the active exchange schema. Compatible with the volume-anomaly and garch packages which accept the same from/to time range format.

getAveragePrice(symbol)

Returns the VWAP (Volume Weighted Average Price) calculated from the last CC_AVG_PRICE_CANDLES_COUNT one-minute candles (default: 5). This is the same price used internally by the engine for all entry and exit decisions.
import { getAveragePrice } from 'backtest-kit';

const vwap = await getAveragePrice('BTCUSDT');
// Use as the reference price for TP/SL calculations
Returns: Promise<number> — VWAP. Falls back to the arithmetic mean of closing prices if volume data is unavailable.

Position Data Helpers

These functions read the state of the currently active position for the given symbol. All return null if no position is active.

getPositionPnlPercent(symbol)

Current unrealized PnL as a percentage, accounting for slippage, fees, DCA entries, and partial closes.
const pnl = await getPositionPnlPercent('BTCUSDT');
// e.g. 3.45 (means +3.45%)
Returns: Promise<number | null>

getPositionPnlCost(symbol)

Current unrealized PnL in dollars (quote currency). Accounts for cost basis after partial closes. Returns: Promise<number | null>

getPositionEntries(symbol)

Returns the list of all DCA entry levels for the current position.
const entries = await getPositionEntries('BTCUSDT');
// [{ price: 45000, cost: 100 }, { price: 43000, cost: 100 }]
Returns: Promise<Array<{ price: number; cost: number }> | null>

getPositionEntryOverlap(symbol, price, ladder?)

Returns true if price falls within a tolerance band around any existing DCA entry level. Use this to avoid stacking entries too close together.
const hasOverlap = await getPositionEntryOverlap('BTCUSDT', currentPrice, {
  upperPercent: 2,  // reject if within 2% above any existing entry
  lowerPercent: 2,  // reject if within 2% below any existing entry
});
symbol
string
required
Trading pair symbol.
price
number
required
Candidate price to check against existing entries.
ladder.upperPercent
number
Upper tolerance band as a percentage (0–100). Defaults to the framework’s overlap detection threshold.
ladder.lowerPercent
number
Lower tolerance band as a percentage (0–100).
Returns: Promise<boolean>true if overlap detected.

getPositionEffectivePrice(symbol)

Returns the current harmonic-mean (VWAP) entry price across all DCA entries, adjusted for any partial closes. This is the reference price used for PnL calculations. Returns: Promise<number | null>

getPositionInvestedCount(symbol)

Returns the number of DCA entries made so far. A value of 1 means only the initial entry; each subsequent commitAverageBuy increments this. Returns: Promise<number | null>

getPositionInvestedCost(symbol)

Returns the total dollar cost basis of the current position (sum of all accepted DCA entries minus proportional cost from partial closes). Returns: Promise<number | null>

getPositionHighestProfitPrice(symbol)

Returns the highest price reached by the position since it was opened (for longs) or the lowest price (for shorts). Used for trailing stop calculations. Returns: Promise<number | null>

getPositionMaxDrawdownPrice(symbol)

Returns the price at which the position experienced its maximum drawdown. Returns: Promise<number | null>

getPositionActiveMinutes(symbol)

Returns how many minutes the position has been open. Returns: Promise<number | null>

getPositionPartials(symbol)

Returns the history of partial profit and loss closes for the current position. Returns: Promise<Array<{ type: 'profit' | 'loss'; percentToClose: number; price: number; cost: number; totalEntries: number }> | null>

getPendingSignal(symbol)

Returns the current active signal row, or null if no position is open. Returns: Promise<ISignalRow | null>

getScheduledSignal(symbol)

Returns the current scheduled (pending entry at limit price) signal, or null if none. Returns: Promise<IScheduledSignalRow | null>

getBreakeven(symbol, currentPrice)

Returns true if currentPrice has cleared the breakeven threshold (entry price + slippage + fees). Use to gate commitBreakeven calls. Returns: Promise<boolean>

Build docs developers (and LLMs) love