Documentation 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.
These three adapters track the longer-running state of each strategy execution. Recent stores the last publicly visible signal per (symbol, strategy, exchange, frame, mode) — a fast lookup for the most recent signal without scanning history. State stores arbitrary per-signal key-value buckets scoped to a (signalId, bucketName) pair, providing lightweight scratchpad storage for any signal-local computation. Session stores the running session record for each active strategy instance, keyed by the full five-part context (strategy, exchange, frame, symbol, mode).
All three adapters are implemented in src/config/setup.ts and backed by MinIO via the shared BaseStorage class. They gate their first waitForInit call on Redis being available, then perform purely synchronous key-value reads and writes against MinIO for all subsequent operations.
Recent adapter
Purpose
The Recent adapter persists the last publicly visible signal emitted by a strategy for a given (symbol, strategyName, exchangeName, frameName, backtest) context. It is used by the backtest-kit UI and downstream consumers to read the current market view without replaying the full signal history.
Constructor
The adapter is instantiated by backtest-kit with five constructor fields:
| Field | Type | Description |
|---|
symbol | string | Trading pair (e.g., "TRXUSDT") |
strategyName | string | Registered strategy identifier |
exchangeName | string | Registered exchange identifier |
frameName | string | Frame identifier for the backtest window |
backtest | boolean | true for backtest data, false for live/paper |
Object key pattern
Objects are stored under the backtest-kit/recent-items/ prefix in MinIO:
recent-items/{symbol}/{strategyName}/{exchangeName}/{frameName}/{backtest}
Example: recent-items/TRXUSDT/jan_2026_strategy/ccxt-exchange/jan_2026_frame/true
Interface methods
| Method | Signature | Description |
|---|
waitForInit | (initial: boolean) → Promise<void> | Gates on Redis ready if initial is true |
readRecentData | () → Promise<RecentData> | Returns the stored IPublicSignalRow or null |
writeRecentData | (signalRow, when) → Promise<void> | Upserts the latest public signal with timestamp |
Schema
// src/schema/Recent.schema.ts
import { IPublicSignalRow } from "backtest-kit";
interface IRecentDto {
symbol: string;
strategyName: string;
exchangeName: string;
frameName: string;
backtest: boolean;
payload: IPublicSignalRow;
when: number;
}
interface IRecentRow extends IRecentDto {
id: string;
createDate: Date;
updatedDate: Date;
}
The payload field holds the IPublicSignalRow object from backtest-kit — the full public representation of the signal as emitted by getSignal. The when field is a Unix millisecond timestamp of the last write.
Adapter registration
// src/config/setup.ts
PersistRecentAdapter.usePersistRecentAdapter(class implements IPersistRecentInstance {
constructor(
readonly symbol: string,
readonly strategyName: string,
readonly exchangeName: string,
readonly frameName: string,
readonly backtest: boolean,
) {}
async waitForInit(initial: boolean) {
if (!initial) {
return;
}
await waitForInfra();
}
async readRecentData(): Promise<RecentData> {
const row = await ioc.recentDataService.findByContext(
this.symbol,
this.strategyName,
this.exchangeName,
this.frameName,
this.backtest,
);
return row ? row.payload : null;
}
async writeRecentData(signalRow: NonNullable<RecentData>, when: Date): Promise<void> {
await ioc.recentDataService.upsert(
this.symbol,
this.strategyName,
this.exchangeName,
this.frameName,
this.backtest,
signalRow,
when,
);
}
});
State adapter
Purpose
The State adapter stores arbitrary per-signal key-value state scoped to a (signalId, bucketName) pair. It acts as a named scratchpad attached to a specific open position, allowing strategy logic to persist intermediate computation, counters, or flags across candle evaluations without polluting the main signal record.
Constructor
| Field | Type | Description |
|---|
signalId | string | Unique identifier of the open signal/position |
bucketName | string | Named bucket within the signal’s state space |
Object key pattern
Objects are stored under the backtest-kit/state-items/ prefix in MinIO:
state-items/{signalId}/{bucketName}
Example: state-items/abc123/trailing-take-state
Interface methods
| Method | Signature | Description |
|---|
waitForInit | (initial: boolean) → Promise<void> | Gates on Redis ready if initial is true |
readStateData | () → Promise<StateData | null> | Returns the stored state object or null |
writeStateData | (data, when) → Promise<void> | Upserts the state object with timestamp |
dispose | () → void | No-op in this implementation |
Schema
// src/schema/State.schema.ts
import { StateData } from "backtest-kit";
interface IStateDto {
signalId: string;
bucketName: string;
payload: StateData;
when: number;
}
interface IStateRow extends IStateDto {
id: string;
createDate: Date;
updatedDate: Date;
}
StateData is a backtest-kit opaque type — it can hold any JSON-serialisable object. The when field records the Unix millisecond timestamp of the last write.
Adapter registration
// src/config/setup.ts
PersistStateAdapter.usePersistStateAdapter(class implements IPersistStateInstance {
constructor(
readonly signalId: string,
readonly bucketName: string,
) {}
async waitForInit(initial: boolean) {
if (!initial) {
return;
}
await waitForInfra();
}
async readStateData(): Promise<StateData | null> {
const row = await ioc.stateDataService.findByContext(this.signalId, this.bucketName);
return row ? row.payload : null;
}
async writeStateData(data: StateData, when: Date): Promise<void> {
await ioc.stateDataService.upsert(this.signalId, this.bucketName, data, when);
}
dispose(): void { void 0; }
});
Session adapter
Purpose
The Session adapter stores the running session record for a single active strategy instance. Each unique combination of (strategyName, exchangeName, frameName, symbol, backtest) has exactly one session object in MinIO. Session data tracks the lifecycle state of the strategy run — start time, status, accumulated metrics — as maintained by backtest-kit internals.
Constructor
| Field | Type | Description |
|---|
strategyName | string | Registered strategy identifier |
exchangeName | string | Registered exchange identifier |
frameName | string | Frame identifier for the backtest window |
symbol | string | Trading pair (e.g., "TRXUSDT") |
backtest | boolean | true for backtest sessions, false for live/paper |
Object key pattern
Objects are stored under the backtest-kit/session-items/ prefix in MinIO:
session-items/{strategyName}/{exchangeName}/{frameName}/{symbol}/{backtest}
Example: session-items/jan_2026_strategy/ccxt-exchange/jan_2026_frame/TRXUSDT/false
Interface methods
| Method | Signature | Description |
|---|
waitForInit | (initial: boolean) → Promise<void> | Gates on Redis ready if initial is true |
readSessionData | () → Promise<SessionData | null> | Returns the stored session record or null |
writeSessionData | (data, when) → Promise<void> | Upserts the session record with timestamp |
dispose | () → void | No-op in this implementation |
Schema
// src/schema/Session.schema.ts
import { SessionData } from "backtest-kit";
interface ISessionDto {
strategyName: string;
exchangeName: string;
frameName: string;
symbol: string;
backtest: boolean;
payload: SessionData;
when: number;
}
interface ISessionRow extends ISessionDto {
id: string;
createDate: Date;
updatedDate: Date;
}
SessionData is a backtest-kit opaque type carrying internal lifecycle fields. The when field records the Unix millisecond timestamp of the last write.
Adapter registration
// src/config/setup.ts
PersistSessionAdapter.usePersistSessionAdapter(class implements IPersistSessionInstance {
constructor(
readonly strategyName: string,
readonly exchangeName: string,
readonly frameName: string,
readonly symbol: string,
readonly backtest: boolean,
) {}
async waitForInit(initial: boolean) {
if (!initial) {
return;
}
await waitForInfra();
}
async readSessionData(): Promise<SessionData | null> {
const row = await ioc.sessionDataService.findByContext(
this.strategyName,
this.exchangeName,
this.frameName,
this.symbol,
this.backtest,
);
return row ? row.payload : null;
}
async writeSessionData(data: SessionData, when: Date): Promise<void> {
await ioc.sessionDataService.upsert(
this.strategyName,
this.exchangeName,
this.frameName,
this.symbol,
this.backtest,
data,
when,
);
}
dispose(): void { void 0; }
});
The dispose() method on both the State and Session adapters is a deliberate no-op (void 0) in this MinIO implementation. backtest-kit calls dispose() at the end of a position or session lifecycle, but MinIO object storage has no open handles or connection state to release — cleanup happens naturally through the S3 object lifecycle.
The backtest: boolean constructor field on both the Recent and Session adapters is the key that separates backtest data from live and paper data in MinIO. Because the backtest flag is embedded in the object key, a backtest run and a live run for the same symbol and strategy will write to entirely different MinIO paths and can coexist in the same bucket without any collision. This means you can run a historical backtest and a live strategy simultaneously against the same infrastructure.