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 Backtest singleton orchestrates historical strategy simulations. It wires together the registered exchange, frame, strategy, risk, and action schemas into a single execution pipeline that replays market data chronologically, evaluates signals at each tick, and streams results. The facade offers two consumption models—pull-based run() for research and scripting, and event-driven background() for production pipelines—both backed by the same engine and guarantees.

run()

Backtest.run(
  symbol: string,
  context: { strategyName: string; exchangeName: string; frameName: string }
): AsyncGenerator<IStrategyBacktestResult>
Pull-based execution. Returns an AsyncIterableIterator that yields one result per closed or cancelled signal. The generator is lazy—no work is done until you start consuming it. Use break or return inside for await to terminate early; the engine cleans up immediately.
import { Backtest } from 'backtest-kit';

for await (const result of Backtest.run('BTCUSDT', {
  strategyName: 'rsi-trend',
  exchangeName: 'binance',
  frameName:    '2025-dec-01',
})) {
  if (result.action === 'closed') {
    console.log(
      `${result.closeReason.padEnd(12)} PNL: ${result.pnl.pnlPercentage.toFixed(2)}%`,
    );
  }
  if (result.action === 'cancelled') {
    console.log(`Scheduled signal cancelled: ${result.reason}`);
  }
}

IStrategyBacktestResult

The yielded union includes the following discriminated variants:
actionDescription
"opened"A pending position was just activated (scheduled signal filled at priceOpen).
"scheduled"A new scheduled signal was created and is waiting for price to reach entry.
"active"Candles exhausted while monitoring a signal with minuteEstimatedTime: Infinity.
"closed"Signal completed with closeReason: take_profit, stop_loss, time_expired, or closed.
"cancelled"A scheduled signal was cancelled (timeout, price_reject, or user).

background()

Backtest.background(
  symbol: string,
  context: { strategyName: string; exchangeName: string; frameName: string }
): () => void
Event-driven background execution. Returns a stop function—call it to halt the backtest. Results are consumed internally; subscribe to global emitters to observe them.
import { Backtest, listenSignalBacktest, listenDoneBacktest } from 'backtest-kit';

const stop = Backtest.background('BTCUSDT', {
  strategyName: 'rsi-trend',
  exchangeName: 'binance',
  frameName:    '2025-dec-01',
});

listenSignalBacktest((event) => {
  if (event.action === 'closed') {
    console.log('Closed signal PNL:', event.pnl.pnlPercentage.toFixed(2) + '%');
  }
});

listenDoneBacktest(async (event) => {
  console.log(`Backtest done: ${event.strategyName} on ${event.symbol}`);
  await Backtest.dump(event.symbol, {
    strategyName: event.strategyName,
    exchangeName: event.exchangeName,
    frameName:    event.frameName,
  });
});

getData()

Backtest.getData(
  symbol: string,
  context: { strategyName: string; exchangeName: string; frameName: string }
): Promise<BacktestStatisticsModel>
Returns aggregated statistics calculated from all closed signals accumulated since the last clear() call. Key fields on BacktestStatisticsModel:
FieldDescription
signalListArray of all IStrategyTickResultClosed results.
totalSignalsCount of closed signals.
winCount / lossCountWin and loss counts.
winRateWin rate percentage (0–100), null if unsafe.
avgPnlAverage PNL per signal as percentage, null if unsafe.
totalPnlCumulative PNL across all signals, null if unsafe.
sharpeRatioRisk-adjusted return (avgPnl / stdDev), null if unsafe.
annualizedSharpeRatioSharpe × √tradesPerYear, null if unsafe.
sortinoRatioDownside deviation Sharpe variant.
calmarRatioAnnualized return / max drawdown.
recoveryFactorTotal PNL / max drawdown.
expectedYearlyReturnsProjected annual return based on average trade duration.

getReport()

Backtest.getReport(
  symbol: string,
  context: { strategyName: string; exchangeName: string; frameName: string }
): Promise<string>
Returns a Markdown-formatted report string containing a table of all closed signals, key statistics, and a performance summary. Suitable for writing to disk or displaying in a terminal.

dump()

Backtest.dump(
  symbol: string,
  context: { strategyName: string; exchangeName: string; frameName: string },
  path?: string
): Promise<void>
Generates the Markdown report and writes it to disk. Default output path: ./dump/backtest/. The filename includes the symbol, strategy name, exchange, frame, and a timestamp for uniqueness.

clear()

Backtest.clear(
  symbol: string,
  context: { strategyName: string; exchangeName: string; frameName: string }
): Promise<void>
Clears all accumulated signal data for the specified context. Call between runs when you want getData() and getReport() to reflect only the most recent execution.

stop()

Backtest.stop(
  symbol: string,
  context: { strategyName: string; exchangeName: string; frameName: string }
): Promise<void>
Stops the strategy from generating new signals without aborting the current active position. The running backtest completes naturally (current signal closes via TP/SL/time), then the generator terminates. Equivalent to calling stopStrategy on the underlying strategy instance.

Context Object

All methods accept a context with three required fields:
strategyName
string
required
Name of a registered strategy schema.
exchangeName
string
required
Name of a registered exchange schema.
frameName
string
required
Name of a registered frame schema (defines backtest period and tick interval).

Build docs developers (and LLMs) love