backtest-kit separates market data fetching from strategy logic through a named exchange schema. You register one or more schemas at startup, each identified by anDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/theonetrade/backtest-kit-redis-mongo-docker/llms.txt
Use this file to discover all available pages before exploring further.
exchangeName string. Adapters and strategies reference that name rather than importing exchange clients directly, which makes it straightforward to swap exchanges or use different configurations in backtest, paper, and live modes. This project ships with a single CCXT-based Binance spot schema that covers all three modes.
What addExchangeSchema() Does
addExchangeSchema() registers a named provider for four market-data operations: historical candles, live order books, price formatting, and quantity formatting. When the runner needs candle data for a symbol, it calls the getCandles implementation you registered under the matching exchangeName. The function is idempotent within a process — registering the same exchangeName twice overwrites the first registration.
Global Configuration
Before registering the schema, callsetConfig to tune framework-level constants. The most important one for this project is CC_MAX_STOPLOSS_DISTANCE_PERCENT, which caps how far a stop-loss can be placed from the entry price. Setting it to 100 disables the cap and allows strategies to place stops at any distance:
The default value for
CC_MAX_STOPLOSS_DISTANCE_PERCENT in backtest-kit is much lower than 100. If your strategy uses Position.moonbag() with a large stop, you will see silent rejections unless you raise this limit.The Singleton Exchange Instance
Creating a CCXT exchange object is expensive: it allocates HTTP clients and, whenloadMarkets() is called, fetches the full symbol catalogue from the exchange. Use singleshot from functools-kit to create the exchange exactly once and reuse the same instance across all calls:
| Option | Effect |
|---|---|
defaultType: "spot" | Targets the Binance spot market, not futures |
adjustForTimeDifference: true | Compensates for clock drift between the host and Binance servers |
recvWindow: 60000 | Extends the Binance receive window to 60 s, reducing timestamp-related rejections |
enableRateLimit: true | Activates CCXT’s built-in request throttle to stay within API limits |
The Four Required Functions
getCandles
Fetches OHLCV bars for a symbol. The function receives a since Date (start of the requested range) and a limit count. CCXT’s fetchOHLCV returns an array of [timestamp, open, high, low, close, volume] tuples; map them to backtest-kit’s named-field format:
getOrderBook
Fetches the live order book. Because historical order book snapshots are not available through CCXT, this function must throw in backtest mode. The backtest boolean parameter signals which mode is active:
formatPrice
Rounds a raw price to the market’s tick size. Use roundTicks from backtest-kit when the tick size is available from CCXT market metadata, and fall back to CCXT’s own priceToPrecision otherwise:
formatQuantity
Mirrors formatPrice but for order quantities. Uses the market’s step size (minimum lot increment) rather than the tick size:
Complete Schema Registration
Putting all four functions together inmodules/backtest.module.ts:
ExchangeName enum ties the string literal to a compile-time constant so strategies and adapters never hard-code the exchange name:
The Three Module Files
The project contains three parallel module files for the three run modes:ccxt.binance spot schema with the same options. This is intentional — the Binance spot API is the correct data source for all three modes and no per-mode configuration differences are needed.
The separation exists so you can diverge them later without restructuring the project. Common reasons to differentiate them include:
Backtest
Use a local OHLCV cache or a different data vendor to avoid hitting Binance rate limits during long historical replays.
Paper
Connect to Binance testnet instead of production to validate order placement logic without real funds.
Live
Add API keys, switch to a co-located endpoint, or enable futures/margin types that are inappropriate for backtesting.
Using a Different Exchange
To switch from Binance to any other CCXT-supported exchange, replaceccxt.binance with the appropriate class and adjust the constructor options. The rest of the schema — getCandles, getOrderBook, formatPrice, formatQuantity — is exchange-agnostic because CCXT normalises the interface: