Backtest Kit’s persistence layer is fully pluggable. The framework defines 15 separate persistence contracts — one per domain (signals, candles, schedules, risk, partials, and more) — and ships default implementations that work out of the box. Swapping any or all of them for a production-grade backend requires a singleDocumentation 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.
setup() call and a few environment variables; your strategy code never changes.
Default: File-Based Storage
The default adapter writes every state mutation to disk using atomic file writes (writeFileAtomic). A partial write can never corrupt saved state because the OS swaps in the completed file only after the write succeeds.
- Process crashes mid-trade.
- On restart,
ClientStrategy.waitForInit()reads the last persisted JSON from disk. - The engine resumes monitoring the open position from the exact state it was in before the crash.
- No trades are lost; no duplicate signals are generated.
In-Memory Storage
For fast iteration during development or unit tests, swap individual adapters for in-memory implementations:Production: MongoDB + Redis
For production deployments,@backtest-kit/mongo replaces all 15 file-based adapters with MongoDB as the source of truth and Redis as an O(1) lookup cache. All 15 IPersist*Instance contracts are implemented — strategy code stays unchanged.
Installation
Setup
Createconfig/setup.config.ts and call setup() before any trading operations:
Environment Variables
Calling
setup() disables all default file-based adapters and replaces them
with MongoDB-backed implementations. After setup(), your process is the owner
of the persistence layer — ensure MongoDB and Redis are reachable before calling
Backtest.background() or Live.background().How Redis O(1) Caching Works
Every domain has two layers: a DbService that talks to MongoDB and a CacheService that talks to Redis. When the engine reads state for a context key (for examplesymbol + strategyName + exchangeName for a signal), the DbService first asks Redis for the MongoDB _id. If the key is present, the document is fetched directly by _id — two O(1) operations total. On a cache miss, it falls back to an indexed MongoDB query and then writes the _id back to Redis so the next call is instant.
Atomic Writes
All writes use a singlefindOneAndUpdate round-trip with upsert: true:
Soft Delete
Measure, Interval, and Memory records are never physically deleted. CallingremoveMeasureData, removeIntervalData, or removeMemoryData sets removed: true on the document. All listing operations automatically filter on removed: false. This preserves the audit trail for LLM reasoning history and backtest session data.
The 15 Persistence Contracts
Full list of IPersist*Instance contracts
Full list of IPersist*Instance contracts
| Adapter | MongoDB Collection | Unique Index | Notes |
|---|---|---|---|
| Candle | candle-items | symbol + interval + timestamp | Immutable — first write wins |
| Signal | signal-items | symbol + strategyName + exchangeName | Core position state |
| Schedule | schedule-items | symbol + strategyName + exchangeName | Limit order scheduling |
| Risk | risk-items | riskName + exchangeName | Risk profile state |
| Partial | partial-items | symbol + strategyName + exchangeName + signalId | Partial profit/loss events |
| Breakeven | breakeven-items | symbol + strategyName + exchangeName + signalId | Breakeven SL moves |
| Storage | storage-items | backtest + signalId | General key-value storage per signal |
| Notification | notification-items | backtest + notificationId | Alert deduplication |
| Log | log-items | entryId | Structured log entries |
| Measure | measure-items | bucket + entryKey | LLM/API response cache (soft delete) |
| Interval | interval-items | bucket + entryKey | Time-window state (soft delete) |
| Memory | memory-items | signalId + bucketName + memoryId | Persistent LLM context (soft delete) |
| Recent | recent-items | symbol + strategyName + exchangeName + frameName + backtest | Last-seen signal per context |
| State | state-items | signalId + bucketName | Arbitrary strategy state per signal |
| Session | session-items | strategyName + exchangeName + frameName | Cached indicator calculations |
API Reference
Persistence Configuration per Mode
In production multi-symbol setups, you often want different adapters for backtest vs live runs. Theconfig/setup.config.ts pattern from backtest-monorepo-parallel shows how:
| Subsystem | Live | Backtest |
|---|---|---|
| Session | MongoDB (durable) | Local file |
| Storage | MongoDB | In-memory |
| Recent | MongoDB | In-memory |
| Notification | MongoDB | In-memory |
| Memory | MongoDB | Local file |
| State | MongoDB | Local file |
| Candle cache | MongoDB | MongoDB |
| Log | JSONL | JSONL |