Skip to main content

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:
FieldTypeDescription
symbolstringTrading pair (e.g., "TRXUSDT")
strategyNamestringRegistered strategy identifier
exchangeNamestringRegistered exchange identifier
frameNamestringFrame identifier for the backtest window
backtestbooleantrue 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

MethodSignatureDescription
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

FieldTypeDescription
signalIdstringUnique identifier of the open signal/position
bucketNamestringNamed 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

MethodSignatureDescription
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() → voidNo-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

FieldTypeDescription
strategyNamestringRegistered strategy identifier
exchangeNamestringRegistered exchange identifier
frameNamestringFrame identifier for the backtest window
symbolstringTrading pair (e.g., "TRXUSDT")
backtestbooleantrue 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

MethodSignatureDescription
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() → voidNo-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.

Build docs developers (and LLMs) love