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.
@backtest-kit/cli is the fastest path from a strategy idea to a running backtest. Point it at your strategy file, choose a mode, and it handles exchange connectivity, candle cache warming, web dashboard startup, and Telegram notifications — no infrastructure code required. The same command you use to run your first backtest on day one scales to a monorepo of dozens of strategies in production: no rewrite, no language switch, no framework migration when the business grows.
Install
Add @backtest-kit/cli as a project dependency to use it in package.json scripts:
npm install @backtest-kit/cli
Init — Scaffold a New Project
Scaffold a new project with a single command:
npx @backtest-kit/cli --init --output my-trading-bot
cd my-trading-bot && npm install
This generates a ready-to-use project containing only your strategy files. All boilerplate (storage, candle caching, Telegram, UI wiring) stays inside @backtest-kit/cli and is invoked via npm start.
Execution Modes
@backtest-kit/cli resolves the full run lifecycle automatically. Choose the mode that matches your workflow:
| Mode | Flag | Description |
|---|
| Backtest | --backtest | Run strategy on historical candle data using a registered FrameSchema |
| Walker | --walker | A/B compare multiple strategy files on the same historical period and print a ranked report |
| Paper | --paper | Live prices, no real orders — identical code path to live |
| Live | --live | Real trades via exchange API |
| Main | --main | Run a custom entry point with full CLI environment (.env, setup.config, loader.config) but no trading harness |
| UI Dashboard | --ui | Start the @backtest-kit/ui web dashboard at http://localhost:60050 |
| Telegram | --telegram | Send formatted trade notifications with 1m/15m/1h price charts |
| PineScript | --pine | Execute a local .pine indicator against exchange data and print a Markdown table |
| Pine Editor | --editor | Open the visual Pine Script editor in the browser |
| Candle Dump | --dump | Fetch and save raw OHLCV candles to JSON or JSONL |
| PnL Debug | --pnldebug | Simulate per-minute PnL for a given entry price and direction |
| Broker Debug | --brokerdebug | Fire a single broker commit against the live broker adapter |
| Flush | --flush | Delete report/log/markdown/agent folders from a strategy’s dump directory |
| Init Project | --init | Scaffold a new backtest-kit project |
CLI Flags Reference
| Flag | Type | Description |
|---|
--backtest | boolean | Run historical backtest (default: false) |
--walker | boolean | Run Walker A/B strategy comparison (default: false) |
--paper | boolean | Paper trading — live prices, no orders (default: false) |
--live | boolean | Run live trading (default: false) |
--main | boolean | Run a custom entry point with full CLI environment but no trading harness (default: false) |
--ui | boolean | Start web UI dashboard (default: false) |
--telegram | boolean | Enable Telegram notifications (default: false) |
--verbose | boolean | Log each candle fetch (default: false) |
--noCache | boolean | Skip candle cache warming before backtest (default: false) |
--noFlush | boolean | Skip removing report/log/markdown/agent folders before a run (default: false) |
--symbol | string | Trading pair (default: "BTCUSDT") |
--strategy | string | Strategy name (default: first registered) |
--exchange | string | Exchange name (default: first registered) |
--frame | string | Backtest frame name (default: first registered) |
--cacheInterval | string | Comma-separated intervals to pre-cache (default: "1m, 15m, 30m, 4h") |
--brokerdebug | boolean | Fire a single broker commit against the live broker adapter (default: false) |
--commit | string | Commit type for --brokerdebug (default: "signal-open") |
--entry | boolean | Modifier for --backtest/--live/--paper/--walker — hands full control of symbol selection and *.background() calls to your entry file (default: false) |
The positional argument (required for most modes) is the path to your strategy entry point file. Set it once in package.json scripts:
{
"scripts": {
"backtest": "npx @backtest-kit/cli --backtest ./src/index.ts",
"paper": "npx @backtest-kit/cli --paper ./src/index.ts",
"start": "npx @backtest-kit/cli --live ./src/index.ts"
}
}
Monorepo Usage
@backtest-kit/cli is designed for monorepos where each strategy lives in its own subdirectory. When the CLI loads your entry point, it automatically changes the working directory to the file’s location — so dump/, modules/, and template/ all resolve relative to that strategy’s folder, not the project root.
monorepo/
├── .env # shared API keys
└── strategies/
├── oct_2025/
│ ├── index.mjs # entry point
│ ├── .env # overrides root .env for this strategy
│ ├── modules/
│ │ ├── live.module.mjs
│ │ └── backtest.module.mjs
│ └── dump/ # candle cache + backtest reports
└── dec_2025/
├── index.mjs
└── dump/
Every resource is isolated per strategy:
| Resource | Path (relative to strategy dir) | Isolated |
|---|
| Candle cache | ./dump/data/candle/ | ✅ per-strategy |
| Backtest reports | ./dump/ | ✅ per-strategy |
| Broker module (live) | ./modules/live.module.mjs | ✅ per-strategy |
| Broker module (paper) | ./modules/paper.module.mjs | ✅ per-strategy |
| Broker module (backtest) | ./modules/backtest.module.mjs | ✅ per-strategy |
| Telegram templates | ./template/*.mustache | ✅ per-strategy |
| Environment variables | ./.env (overrides root) | ✅ per-strategy |
Module Hooks
Drop a mode-specific module file into your strategy’s modules/ directory to register a broker adapter before the run starts. The CLI loads it as a side-effect import — your code runs, registers the adapter, and from that point every trade-mutating call is intercepted before internal state changes.
| Mode flag | Module file | Loaded before |
|---|
--live | ./modules/live.module.mjs | Live.background() |
--paper | ./modules/paper.module.mjs | Live.background() (paper) |
--backtest | ./modules/backtest.module.mjs | Backtest.background() |
--walker | ./modules/walker.module.mjs | Walker.background() |
--main | ./modules/main.module.mjs | the custom entry point |
--brokerdebug | ./modules/brokerdebug.module.mjs | broker commit test |
Extensions .mjs, .cjs, and .ts are tried automatically. A missing module is a soft warning — not an error.
// modules/live.module.mjs
import { Broker } from 'backtest-kit';
class MyBroker {
async onSignalOpenCommit({ symbol, priceOpen, direction }) {
await myExchange.openPosition(symbol, direction, priceOpen);
}
async onSignalCloseCommit({ symbol, priceClosed }) {
await myExchange.closePosition(symbol, priceClosed);
}
}
Broker.useBrokerAdapter(MyBroker);
Broker.enable();
Config Hooks
Three config files let you take ownership of the persistence layer and async initialization without touching strategy code.
config/setup.config
Loaded once before any module hooks or strategy code run. Use it to swap the default file-based persistence for a production backend. When setup.config is present, the CLI skips its own default adapter registration — your config takes full ownership.
// config/setup.config.ts
import { setup } from '@backtest-kit/mongo';
setup();
config/loader.config
Loaded after setup.config. The CLI awaits the exported function before any strategy code runs. Use it to wait for async dependencies — database connections, cache warm-up, schema migrations, or monorepo service wiring.
// config/loader.config.ts
import mongoose from 'mongoose';
export default async () => {
await mongoose.connect(process.env.CC_MONGO_CONNECTION_STRING!);
console.log('mongo connection verified, starting backtest');
};
config/alias.config
Loaded once on the first import call. Export a mapping from module name to replacement module to redirect any dependency without touching node_modules. Useful for swapping heavy libraries with lightweight stubs during backtests or CI runs.
// config/alias.config.ts
export default async () => ({
nanoid: await import('nanoid'),
});
TypeScript strategy files (.ts) run directly via tsx — no tsc compilation step is required. Add tsx to your devDependencies and point --backtest at your .ts file.