TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-kit-redis-mongo-docker/llms.txt
Use this file to discover all available pages before exploring further.
backtest-kit-redis-mongo-docker project separates strategy logic from infrastructure wiring. Strategy code lives under src/logic/, with each strategy and its time-frame definition in their own files. The three entry points in src/main/ (backtest.ts, paper.ts, live.ts) bootstrap the application for their respective modes, wire up MongoDB/Redis adapters, then delegate to the strategy module. Rollup bundles the src/ tree into a single ./build/index.cjs artefact that backtest-kit loads at runtime via the STRATEGY_FILE environment variable or the --ui CLI flag.
Project layout
Strategy schema (addStrategySchema)
src/logic/strategy/jan_2026.strategy.ts registers a strategy by calling addStrategySchema. The getSignal callback is invoked by backtest-kit on every candle tick for each tracked symbol. It must return a signal object (including position direction and risk parameters) or null if no trade should be opened.
getSignal the strategy:
- Looks up the active signal for the current
symbol/whenpair usinggetActiveSignal. - Validates that the 1-minute close price falls within the signal’s
entry.from–entry.torange. - Reads two 4-hour candles to derive a range midpoint and determine whether the trade is
"long"or"short". - Returns a position object built with
Position.moonbag, a 24-hour estimated hold time, and the signal note.
The SIGNALS array
At module initialisation time the strategy file reads ./assets/entry.jsonl synchronously:
SignalEntryModel with the following shape:
| Field | Type | Description |
|---|---|---|
symbol | string | Trading pair, e.g. "TRXUSDT" |
publishedAt | string | ISO-8601 timestamp for when the signal fires |
direction | "long" | "short" | Suggested trade direction from the signal source |
entry.from | number | Lower bound of the valid entry price range |
entry.to | number | Upper bound of the valid entry price range |
targets | number[] | Array of target price levels for the trade |
stoploss | number | Suggested stop-loss price level |
note | string | Human-readable annotation stored on the position |
getActiveSignal(symbol, when) aligns publishedAt to the nearest 1-minute boundary and checks whether it matches the current simulation timestamp.
Active-ping hooks
TwolistenActivePing hooks run on every heartbeat for open positions:
Trailing take — closes the position once it has pulled back from its peak by more than TRAILING_TAKE (1 %):
PEAK_STALENESS_SINCE_PROFIT = 1 %) for longer than PEAK_STALENESS_SINCE_MINUTES (240 min = 4 hours) without closing naturally. This guards against positions that spike once and then stagnate.
Build pipeline
Rollup readssrc/index.ts (which re-exports both the frame and strategy modules) and bundles everything into ./build/index.cjs in CommonJS format:
backtest-kit imports are treated as peer-dependency externals so the bundle stays small. After running rollup -c, point backtest-kit at the bundle:
Strategy names, frame names, and exchange names are defined as TypeScript enums in the
src/enum/ directory (StrategyName.ts, FrameName.ts, ExchangeName.ts). Always use these enum values rather than raw strings to keep identifiers consistent across entry points, module registrations, and strategy schemas.