Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-kit-minio-s3-docker/llms.txt

Use this file to discover all available pages before exploring further.

A frame defines the time window, candle interval, and date range that the backtest runner steps through. Frames are registered with addFrameSchema and referenced by name when launching a Backtest.background() run. Separating the frame from the strategy means you can combine any frame with any strategy without modifying either file — simply reference the right FrameName in your runner entry point.

addFrameSchema API

Frames are registered by calling addFrameSchema at module load time. The example frame in src/logic/frame/jan_2026.frame.ts covers January 2026 at 1-minute resolution:
import { addFrameSchema } from "backtest-kit";
import { FrameName } from "../../enum/FrameName";

addFrameSchema({
  frameName:  FrameName.Jan2026Frame,
  interval:   "1m",
  startDate:  new Date("2026-01-01T00:00:00Z"),
  endDate:    new Date("2026-01-31T23:59:59Z"),
  note:       "January 2026",
});
FieldTypeDescription
frameNamestringUnique identifier for the frame, typically sourced from the FrameName enum
intervalCandleIntervalCandle step size; determines how often getSignal is called and which candle series is iterated
startDateDateInclusive start of the backtest window
endDateDateInclusive end of the backtest window
notestringHuman-readable label shown in the backtest-kit UI and stored in session metadata

Available intervals

CandleInterval is a union of the string literals defined in the backtest-kit INTERVAL_MINUTES record. Every value maps to the number of minutes in that candle:
IntervalMinutes
"1m"1
"3m"3
"5m"5
"15m"15
"30m"30
"1h"60
"2h"120
"4h"240
"6h"360
"8h"480
"1d"1440
The interval you choose for a frame becomes the step size used in readCandlesData() — the runner advances the simulation clock by exactly one interval per tick.

FrameName enum

src/enum/FrameName.ts centralises all registered frame identifiers:
export enum FrameName {
  Jan2026Frame = "jan_2026_frame",
}
The string value ("jan_2026_frame") must match the frameName string passed to addFrameSchema in the corresponding frame module.

Adding a new frame

1

Create the frame file

Create a new file under src/logic/frame/. Name it to match the period you are testing:
// src/logic/frame/feb_2026.frame.ts
import { addFrameSchema } from "backtest-kit";
import { FrameName } from "../../enum/FrameName";

addFrameSchema({
  frameName:  FrameName.Feb2026Frame,
  interval:   "1m",
  startDate:  new Date("2026-02-01T00:00:00Z"),
  endDate:    new Date("2026-02-28T23:59:59Z"),
  note:       "February 2026",
});
2

Add the name to FrameName.ts

Open src/enum/FrameName.ts and append the new member:
export enum FrameName {
  Jan2026Frame = "jan_2026_frame",
  Feb2026Frame = "feb_2026_frame",   // ← add this
}
3

Import in src/logic/index.ts

Register the frame module by importing it in src/logic/index.ts:
import "./frame/jan_2026.frame";
import "./frame/feb_2026.frame";      // ← add this

import "./strategy/jan_2026.strategy";
The import is purely for its side-effect — calling addFrameSchema at module load registers the frame with the runtime.
4

Reference the frame in the runner

Update src/main/backtest.ts (or your own runner file) to use the new frame name, and make sure warmCandles covers the new date range:
await warmCandles({
  exchangeName: ExchangeName.CCXT,
  from:         new Date("2026-02-01T00:00:00Z"),
  to:           new Date("2026-02-28T23:59:59Z"),
  interval:     "1m",
  symbol:       "TRXUSDT",
});

Backtest.background("TRXUSDT", {
  exchangeName:  ExchangeName.CCXT,
  frameName:     FrameName.Feb2026Frame,   // ← updated
  strategyName:  StrategyName.Jan2026Strategy,
});

Candle warming

Before the backtest loop starts, backtest.ts calls warmCandles() to pre-fetch the full OHLCV dataset from the exchange and store it in the MinIO/Redis persistence layer. Subsequent reads during the simulation are served from the local cache — no live exchange calls during replay.
await warmCandles({
  exchangeName: ExchangeName.CCXT,
  from:         new Date("2026-01-01T00:00:00Z"),
  to:           new Date("2026-01-31T23:59:59Z"),
  interval:     "1m",
  symbol:       "TRXUSDT",
});
ParameterDescription
exchangeNameThe registered exchange adapter to fetch from (matches ExchangeName enum)
fromWarming start date — should match the frame’s startDate
toWarming end date — should match the frame’s endDate
intervalCandle granularity — should match the frame’s interval
symbolThe trading pair to pre-fetch
warmCandles is designed to be idempotent: candle objects in MinIO are immutable insert-only (stat + PUT) so re-running the same warm call never overwrites existing data.
Always use UTC dates for startDate, endDate, and the from/to arguments of warmCandles. The backtest-kit runtime stores and compares all timestamps in UTC. A local-timezone new Date("2026-01-01") may shift the boundary by hours and leave the first or last partial day uncached.
The interval you set on the frame controls the step size in readCandlesData(). A "1m" frame advances the simulation one minute at a time, calling getSignal at every bar. Choosing a coarser interval (e.g. "1h") dramatically reduces the number of getSignal calls and the volume of candle data that needs warming, at the cost of intra-hour precision. Match the frame interval to the finest resolution your strategy actually needs.

Build docs developers (and LLMs) love