This project ships 16 custom persist adapters registered inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/theonetrade/backtest-kit-minio-s3-docker/llms.txt
Use this file to discover all available pages before exploring further.
src/config/setup.ts. Each adapter implements the corresponding IPersist*Instance interface from backtest-kit and stores data as JSON objects inside a single MinIO bucket (backtest-kit). The persistence layer is a transparent drop-in replacement for backtest-kit’s default file-based ./dump/ store — strategy code, runners, and the CLI entrypoint remain unchanged.
Common Adapter Skeleton
Every adapter follows the same structural pattern. ThewaitForInfra gate ensures infrastructure is ready before any adapter first touches MinIO or Redis.
src/config/setup.ts (pattern)
Adapter Reference
Everything lives in one MinIO bucketbacktest-kit — each entity gets its own root folder. The BaseStorage("backtest-kit/<entity>-items") name format is parsed as bucket/parent-folder: the first path segment is the physical bucket name, the rest becomes a transparent key prefix. A name without a slash (e.g., BaseStorage("breakeven-items")) means a dedicated bucket — fully backward compatible.
| Adapter | Folder in MinIO | Object key format | Purpose |
|---|---|---|---|
| Candle | candle-items/ | exchange/symbol/interval/timestamp | OHLCV cache; immutable inserts |
| Signal | signal-items/ | symbol/strategy/exchange | Live signal state per context |
| Schedule | schedule-items/ | symbol/strategy/exchange | Pending scheduled signal |
| Strategy | strategy-items/ | symbol/strategy/exchange | Deferred commit queue snapshot |
| Risk | risk-items/ | riskName/exchange | Active risk positions snapshot |
| Partial | partial-items/ | symbol/strategy/exchange/signalId | Partial profit/loss levels per signal |
| Breakeven | breakeven-items/ | symbol/strategy/exchange/signalId | Breakeven reached flag |
| Storage | storage-items/ | backtest/signalId | Closed/opened signal log per mode † |
| Notification | notification-items/ | backtest/⟲ts_notificationId | Event notifications † |
| Log | log-items/ | ⟲ts_entryId | Strategy log entries † |
| Measure | measure-items/ | bucket/entryKey | LLM/API response cache |
| Interval | interval-items/ | bucket/entryKey | Once-per-interval markers |
| Memory | memory-items/ | signalId/bucket/memoryId | Per-signal memory store |
| Recent | recent-items/ | symbol/strategy/exchange/frame/backtest | Last public signal per context |
| State | state-items/ | signalId/bucket | Per-signal state buckets |
| Session | session-items/ | strategy/exchange/frame/symbol/backtest | One session per running strategy |
⟲ts denotes an inverted timestamp (Number.MAX_SAFE_INTEGER − ms, zero-padded): plain lexicographic S3 listing yields newest-first order with no sorting overhead.
waitForInit(initial)
waitForInit is called by backtest-kit exactly once per context with initial = true. On subsequent calls (e.g., hot reloads or re-attaches) it receives false and returns immediately. The initial = true path calls waitForInfra(), which gates the adapter on infrastructure readiness.
waitForInfra is created with singleshot from functools-kit, which means Redis initialisation runs exactly once regardless of how many adapters call it concurrently. Subsequent calls resolve immediately from the cached promise.src/config/setup.ts
waitForInfra only needs to await Redis.
Redis as a Time-Ordered Index
S3 can list keys only in lexicographic order and cannot natively answer “what was created last” without a full bucket walk. For the three entities that require newest-first listings — Log, Notification, Storage — a*ConnectionService maintains a Redis index alongside every write:
- One Redis SET per minute:
<entity>-connection:<aligned-minute>→ object names.register()is a single pipeline (SADD+SETNXof the floor marker). Timestamps are minute-aligned so re-registering within a minute deduplicates by construction. listNewest(limit, prefix)walks backwards from the current minute — direct key lookups, noSCANover the full keyspace.- Cold-index fallback: if Redis was flushed, listings fall back to bucket LIST and re-warm the index. For Log and Notification, inverted-timestamp keys are already newest-first so the fallback read is ordered. For Storage, keys are
backtest/signalIdwith no timestamp — the cold-path walk is unordered.
Adapter Pages
Candle
Immutable OHLCV candlestick data — insert-only semantics, deterministic key.
Signal, Schedule, Strategy
Live signal state, pending scheduled signals, and deferred commit queue snapshots.
Risk, Partial, Breakeven
Active risk positions, partial profit/loss levels, and breakeven reached flags.
Storage, Notification, Log
Redis-indexed newest-first listings for closed signals, event notifications, and strategy logs.
Measure, Interval, Memory
LLM/API response cache, once-per-interval markers, and per-signal memory store.
Recent, State, Session
Last public signal per context, per-signal state buckets, and running strategy sessions.