Public API Reference

This page provides a comprehensive reference for all public-facing functions and utilities exposed by the backtest-kit framework. These are the functions users directly interact with to configure strategies, execute backtests/live trading, and monitor results.

For detailed implementation details of the underlying service architecture, see Architecture. For specific execution patterns, see Backtest API and Live Trading API.

The public API is organized into six functional groups, all exported from the main entry point:

Mermaid Diagram

Public API Groups:

Group Purpose Key Functions
Configuration Register strategies, exchanges, and timeframes addStrategy(), addExchange(), addFrame()
Backtest Execution Run historical backtests and generate reports Backtest.run(), Backtest.background(), Backtest.getReport(), Backtest.dump()
Live Trading Execute live trading with crash recovery Live.run(), Live.background(), Live.getReport(), Live.dump()
Exchange Utilities Access market data and execution context getCandles(), getAveragePrice(), getDate(), getMode(), formatPrice(), formatQuantity()
Event Listeners Subscribe to signal lifecycle events listenSignal(), listenSignalBacktest(), listenSignalLive(), and Once variants
Setup Functions Configure framework behavior setLogger(), PersistSignalAdaper.usePersistSignalAdapter()

This diagram maps public API functions to their concrete implementations in the codebase:

Mermaid Diagram

Functions for registering strategies, exchanges, and timeframes. These must be called before execution begins. See Configuration Functions for detailed documentation.

Registers a trading strategy in the framework with signal generation logic, validation, and lifecycle callbacks.

function addStrategy(strategySchema: IStrategySchema): void

Parameters:

Parameter Type Description
strategySchema IStrategySchema Strategy configuration object
strategySchema.strategyName string Unique strategy identifier
strategySchema.interval SignalInterval Throttling interval: "1m" | "3m" | "5m" | "15m" | "30m" | "1h"
strategySchema.getSignal (symbol: string) => Promise<ISignalDto | null> Signal generation function
strategySchema.callbacks Partial<IStrategyCallbacks> Optional lifecycle callbacks (onTick, onOpen, onActive, onIdle, onClose)

Returns: void (throws error if validation fails)

Example:

addStrategy({
strategyName: "momentum-strategy",
interval: "5m",
getSignal: async (symbol) => {
// Signal generation logic
return {
position: "long",
priceOpen: 50000,
priceTakeProfit: 51000,
priceStopLoss: 49000,
minuteEstimatedTime: 60,
};
},
callbacks: {
onOpen: (symbol, signal, currentPrice, backtest) => {
console.log(`Signal opened: ${signal.id}`);
},
},
});

Registers an exchange data source with candle fetching and price formatting capabilities.

function addExchange(exchangeSchema: IExchangeSchema): void

Parameters:

Parameter Type Description
exchangeSchema IExchangeSchema Exchange configuration object
exchangeSchema.exchangeName string Unique exchange identifier
exchangeSchema.getCandles (symbol: string, interval: CandleInterval, since: Date, limit: number) => Promise<ICandleData[]> Historical candle fetching function
exchangeSchema.formatPrice (symbol: string, price: number) => Promise<string> Price formatting function
exchangeSchema.formatQuantity (symbol: string, quantity: number) => Promise<string> Quantity formatting function
exchangeSchema.callbacks Partial<IExchangeCallbacks> Optional callback for onCandleData events

Returns: void (throws error if validation fails)

Example:

addExchange({
exchangeName: "binance",
getCandles: async (symbol, interval, since, limit) => {
// Fetch from API or database
return [{
timestamp: Date.now(),
open: 50000,
high: 51000,
low: 49000,
close: 50500,
volume: 1000,
}];
},
formatPrice: async (symbol, price) => price.toFixed(2),
formatQuantity: async (symbol, quantity) => quantity.toFixed(8),
});

Registers a timeframe generator for backtest period definition with interval-based timestamp generation.

function addFrame(frameSchema: IFrameSchema): void

Parameters:

Parameter Type Description
frameSchema IFrameSchema Frame configuration object
frameSchema.frameName string Unique frame identifier
frameSchema.interval FrameInterval Timeframe interval: "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h" | "12h" | "1d" | "3d"
frameSchema.startDate Date Start of backtest period (inclusive)
frameSchema.endDate Date End of backtest period (inclusive)
frameSchema.callbacks Partial<IFrameCallbacks> Optional callback for onTimeframe events

Returns: void (throws error if validation fails)

Example:

addFrame({
frameName: "week-backtest",
interval: "1m",
startDate: new Date("2024-01-01T00:00:00Z"),
endDate: new Date("2024-01-07T23:59:59Z"),
callbacks: {
onTimeframe: (timeframe, startDate, endDate, interval) => {
console.log(`Generated ${timeframe.length} timestamps`);
},
},
});

The Backtest singleton provides methods for running backtests and generating reports. See Backtest API for detailed documentation.

Executes a backtest as an async generator, yielding closed signals as they complete. Memory-efficient streaming architecture.

Backtest.run(
symbol: string,
context: {
strategyName: string;
exchangeName: string;
frameName: string;
}
): AsyncGenerator<IStrategyTickResultClosed>

Parameters:

Parameter Type Description
symbol string Trading pair symbol (e.g., "BTCUSDT")
context.strategyName string Registered strategy name
context.exchangeName string Registered exchange name
context.frameName string Registered frame name

Returns: AsyncGenerator<IStrategyTickResultClosed> - Generator yielding closed signals with PNL

Example:

for await (const result of Backtest.run("BTCUSDT", {
strategyName: "momentum-strategy",
exchangeName: "binance",
frameName: "week-backtest"
})) {
console.log({
action: result.action, // "closed"
reason: result.closeReason, // "take_profit" | "stop_loss" | "time_expired"
pnl: result.pnl.pnlPercentage, // e.g., +2.5%
});

// Early termination
if (result.pnl.pnlPercentage < -5) break;
}

Runs a backtest in background without yielding results. Useful for executing backtests for side effects only (callbacks, logging). Returns a cancellation function.

Backtest.background(
symbol: string,
context: {
strategyName: string;
exchangeName: string;
frameName: string;
}
): Promise<() => void>

Parameters: Same as Backtest.run()

Returns: Promise<() => void> - Promise resolving to a cancellation function

Example:

const cancel = await Backtest.background("BTCUSDT", {
strategyName: "momentum-strategy",
exchangeName: "binance",
frameName: "week-backtest"
});

// Cancel execution if needed
setTimeout(() => cancel(), 10000);

Generates a markdown-formatted report with all closed signals and performance statistics.

Backtest.getReport(strategyName: string): Promise<string>

Parameters:

Parameter Type Description
strategyName string Strategy name to generate report for

Returns: Promise<string> - Markdown-formatted report

Example:

const markdown = await Backtest.getReport("momentum-strategy");
console.log(markdown);

Saves the strategy report to disk at the specified path (default: ./logs/backtest/).

Backtest.dump(strategyName: string, path?: string): Promise<void>

Parameters:

Parameter Type Description
strategyName string Strategy name to save report for
path string (optional) Directory path (default: "./logs/backtest")

Returns: Promise<void>

Example:

// Save to default path: ./logs/backtest/momentum-strategy.md
await Backtest.dump("momentum-strategy");

// Save to custom path
await Backtest.dump("momentum-strategy", "./reports");

The Live singleton provides methods for live trading execution with crash recovery. See Live Trading API for detailed documentation.

Executes live trading as an infinite async generator, yielding opened and closed signals. Process can crash and restart—state is recovered from disk.

Live.run(
symbol: string,
context: {
strategyName: string;
exchangeName: string;
}
): AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed>

Parameters:

Parameter Type Description
symbol string Trading pair symbol (e.g., "BTCUSDT")
context.strategyName string Registered strategy name
context.exchangeName string Registered exchange name

Returns: AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed> - Infinite generator yielding signal events

Example:

// Infinite loop - use Ctrl+C to stop
for await (const result of Live.run("BTCUSDT", {
strategyName: "momentum-strategy",
exchangeName: "binance"
})) {
if (result.action === "opened") {
console.log("Signal opened:", result.signal.id);
}
if (result.action === "closed") {
console.log("PNL:", result.pnl.pnlPercentage);
}
}

Runs live trading in background without yielding results. Infinite loop runs until process stops or crashes. Returns a cancellation function.

Live.background(
symbol: string,
context: {
strategyName: string;
exchangeName: string;
}
): Promise<() => void>

Parameters: Same as Live.run()

Returns: Promise<() => void> - Promise resolving to a cancellation function

Example:

const cancel = await Live.background("BTCUSDT", {
strategyName: "momentum-strategy",
exchangeName: "binance"
});

// Cancel when needed
process.on('SIGTERM', () => cancel());

Generates a markdown-formatted report with all live trading events and performance statistics (win rate, average PNL).

Live.getReport(strategyName: string): Promise<string>

Parameters:

Parameter Type Description
strategyName string Strategy name to generate report for

Returns: Promise<string> - Markdown-formatted report

Example:

const markdown = await Live.getReport("momentum-strategy");
console.log(markdown);

Saves the live trading report to disk at the specified path (default: ./logs/live/).

Live.dump(strategyName: string, path?: string): Promise<void>

Parameters:

Parameter Type Description
strategyName string Strategy name to save report for
path string (optional) Directory path (default: "./logs/live")

Returns: Promise<void>

Example:

// Save to default path: ./logs/live/momentum-strategy.md
await Live.dump("momentum-strategy");

// Save to custom path
await Live.dump("momentum-strategy", "./live-reports");

Utility functions for accessing market data and execution context. These functions use the current ExecutionContextService and MethodContextService for implicit context propagation. See Exchange Functions for detailed documentation.

Fetches historical candle data backwards from the current execution context time. Uses the registered exchange's getCandles implementation.

function getCandles(
symbol: string,
interval: CandleInterval,
limit: number
): Promise<ICandleData[]>

Parameters:

Parameter Type Description
symbol string Trading pair symbol (e.g., "BTCUSDT")
interval CandleInterval Candle interval: "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h"
limit number Number of candles to fetch

Returns: Promise<ICandleData[]> - Array of OHLCV candle data

Example:

const candles = await getCandles("BTCUSDT", "1h", 100);
candles.forEach(candle => {
console.log({
timestamp: candle.timestamp,
close: candle.close,
volume: candle.volume
});
});

Calculates VWAP (Volume Weighted Average Price) from the last 5 1-minute candles using the formula:

  • Typical Price = (high + low + close) / 3
  • VWAP = Σ(typical_price × volume) / Σ(volume)

If volume is zero, returns simple average of close prices.

function getAveragePrice(symbol: string): Promise<number>

Parameters:

Parameter Type Description
symbol string Trading pair symbol (e.g., "BTCUSDT")

Returns: Promise<number> - VWAP price

Example:

const vwap = await getAveragePrice("BTCUSDT");
console.log("Current VWAP:", vwap);

Formats a price value according to the exchange's precision rules. Uses the registered exchange's formatPrice implementation.

function formatPrice(symbol: string, price: number): Promise<string>

Parameters:

Parameter Type Description
symbol string Trading pair symbol (e.g., "BTCUSDT")
price number Raw price value

Returns: Promise<string> - Formatted price string

Example:

const formatted = await formatPrice("BTCUSDT", 50000.123456);
console.log(formatted); // "50000.12"

Formats a quantity value according to the exchange's precision rules. Uses the registered exchange's formatQuantity implementation.

function formatQuantity(symbol: string, quantity: number): Promise<string>

Parameters:

Parameter Type Description
symbol string Trading pair symbol (e.g., "BTCUSDT")
quantity number Raw quantity value

Returns: Promise<string> - Formatted quantity string

Example:

const formatted = await formatQuantity("BTCUSDT", 0.123456789);
console.log(formatted); // "0.12345678"

Gets the current date from the execution context. In backtest mode, returns the current timeframe date being processed. In live mode, returns the current real-time date.

function getDate(): Promise<Date>

Returns: Promise<Date> - Current execution context date

Example:

const date = await getDate();
console.log("Execution date:", date.toISOString());

Gets the current execution mode (backtest or live).

function getMode(): Promise<"backtest" | "live">

Returns: Promise<"backtest" | "live"> - Current execution mode

Example:

const mode = await getMode();
if (mode === "backtest") {
console.log("Running historical simulation");
} else {
console.log("Running live trading");
}

Functions for subscribing to signal lifecycle events. All callbacks are processed sequentially using queued async execution. See Event Listeners for detailed documentation.

Function Description Returns
listenSignal(fn) Subscribe to all signal events (backtest + live) () => void (unsubscribe function)
listenSignalOnce(filterFn, fn) Subscribe once with filter predicate () => void (unsubscribe function)
listenSignalBacktest(fn) Subscribe to backtest signals only () => void (unsubscribe function)
listenSignalBacktestOnce(filterFn, fn) Subscribe to backtest signals once () => void (unsubscribe function)
listenSignalLive(fn) Subscribe to live signals only () => void (unsubscribe function)
listenSignalLiveOnce(filterFn, fn) Subscribe to live signals once () => void (unsubscribe function)

Subscribes to all signal events with queued async processing. Receives events from both backtest and live execution.

function listenSignal(
fn: (event: IStrategyTickResult) => void
): () => void

Parameters:

Parameter Type Description
fn (event: IStrategyTickResult) => void Callback function to handle signal events

Returns: () => void - Unsubscribe function

Example:

const unsubscribe = listenSignal((event) => {
if (event.action === "opened") {
console.log("New signal:", event.signal.id);
}
if (event.action === "closed") {
console.log("PNL:", event.pnl.pnlPercentage);
}
});

// Stop listening later
unsubscribe();

Subscribes to filtered signal events with one-time execution. Executes callback once when filter predicate matches, then automatically unsubscribes.

function listenSignalOnce(
filterFn: (event: IStrategyTickResult) => boolean,
fn: (event: IStrategyTickResult) => void
): () => void

Parameters:

Parameter Type Description
filterFn (event: IStrategyTickResult) => boolean Predicate to filter which events trigger the callback
fn (event: IStrategyTickResult) => void Callback function (called only once)

Returns: () => void - Unsubscribe function (to cancel before event fires)

Example:

// Wait for first take profit hit
listenSignalOnce(
(event) => event.action === "closed" && event.closeReason === "take_profit",
(event) => {
console.log("Take profit hit! PNL:", event.pnl.pnlPercentage);
}
);

Subscribes to backtest signal events only. Only receives events from Backtest.run() execution.

function listenSignalBacktest(
fn: (event: IStrategyTickResult) => void
): () => void

Example:

const unsubscribe = listenSignalBacktest((event) => {
if (event.action === "closed") {
console.log("Backtest signal closed:", event.closeReason);
}
});

Subscribes to filtered backtest signal events with one-time execution.

function listenSignalBacktestOnce(
filterFn: (event: IStrategyTickResult) => boolean,
fn: (event: IStrategyTickResult) => void
): () => void

Example:

// Wait for first backtest stop loss
listenSignalBacktestOnce(
(event) => event.action === "closed" && event.closeReason === "stop_loss",
(event) => console.log("Stop loss:", event.pnl.pnlPercentage)
);

Subscribes to live trading signal events only. Only receives events from Live.run() execution.

function listenSignalLive(
fn: (event: IStrategyTickResult) => void
): () => void

Example:

const unsubscribe = listenSignalLive((event) => {
if (event.action === "closed") {
console.log("Live signal closed:", event.pnl.pnlPercentage);
}
});

Subscribes to filtered live signal events with one-time execution.

function listenSignalLiveOnce(
filterFn: (event: IStrategyTickResult) => boolean,
fn: (event: IStrategyTickResult) => void
): () => void

Example:

// Wait for first live take profit
listenSignalLiveOnce(
(event) => event.action === "closed" && event.closeReason === "take_profit",
(event) => console.log("Live take profit:", event.pnl.pnlPercentage)
);

Functions for configuring framework behavior and customizing implementations.

Sets a custom logger implementation for the framework. All log messages from internal services are forwarded to the provided logger with automatic context injection (strategyName, exchangeName, symbol, etc.).

function setLogger(logger: ILogger): Promise<void>

Parameters:

Parameter Type Description
logger ILogger Custom logger implementing ILogger interface

ILogger Interface:

interface ILogger {
log(topic: string, ...args: any[]): void;
debug(topic: string, ...args: any[]): void;
info(topic: string, ...args: any[]): void;
warn(topic: string, ...args: any[]): void;
}

Returns: Promise<void>

Example:

setLogger({
log: (topic, ...args) => console.log(`[LOG] ${topic}`, ...args),
debug: (topic, ...args) => console.debug(`[DEBUG] ${topic}`, ...args),
info: (topic, ...args) => console.info(`[INFO] ${topic}`, ...args),
warn: (topic, ...args) => console.warn(`[WARN] ${topic}`, ...args),
});

Registers a custom persistence adapter for signal state storage. Default implementation uses file-based atomic writes. Can be replaced with Redis, PostgreSQL, or any custom storage.

PersistSignalAdaper.usePersistSignalAdapter(
Ctor: TPersistBaseCtor<StrategyName, ISignalData>
): void

Parameters:

Parameter Type Description
Ctor TPersistBaseCtor<StrategyName, ISignalData> Custom PersistBase constructor

Example:

import { PersistSignalAdaper, PersistBase } from "backtest-kit";

class RedisPersist extends PersistBase {
async readValue(id) {
return JSON.parse(await redis.get(id));
}
async writeValue(id, entity) {
await redis.set(id, JSON.stringify(entity));
}
}

PersistSignalAdaper.usePersistSignalAdapter(RedisPersist);

All TypeScript interfaces and types are exported for type-safe usage. See individual interface documentation for details.

Interface Purpose Documentation
IStrategySchema Strategy configuration schema Configuration Functions
IExchangeSchema Exchange configuration schema Configuration Functions
IFrameSchema Frame configuration schema Configuration Functions
ISignalDto Signal data transfer object Signal Generation and Validation
ISignalRow Complete signal with auto-generated ID Signal States
IStrategyTickResult Discriminated union of all tick results Signal States
IStrategyPnL Profit/loss calculation with fees and slippage PnL Calculation
ICandleData OHLCV candle data point Exchange Functions
Type Values Purpose
CandleInterval "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h" Candle time intervals
SignalInterval "1m" | "3m" | "5m" | "15m" | "30m" | "1h" Signal generation throttling intervals
FrameInterval "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h" | "12h" | "1d" | "3d" Timeframe generation intervals
StrategyCloseReason "time_expired" | "take_profit" | "stop_loss" Signal close reasons

This example demonstrates the complete lifecycle of using the public API:

import {
addStrategy,
addExchange,
addFrame,
Backtest,
Live,
listenSignalBacktest,
setLogger,
} from "backtest-kit";

// 1. Setup custom logger
setLogger({
log: (topic, ...args) => console.log(topic, ...args),
debug: (topic, ...args) => {},
info: (topic, ...args) => console.info(topic, ...args),
warn: (topic, ...args) => console.warn(topic, ...args),
});

// 2. Register exchange
addExchange({
exchangeName: "binance",
getCandles: async (symbol, interval, since, limit) => {
// Fetch from Binance API
return [...];
},
formatPrice: async (symbol, price) => price.toFixed(2),
formatQuantity: async (symbol, quantity) => quantity.toFixed(8),
});

// 3. Register strategy
addStrategy({
strategyName: "momentum-strategy",
interval: "5m",
getSignal: async (symbol) => {
// Signal generation logic
return {
position: "long",
priceOpen: 50000,
priceTakeProfit: 51000,
priceStopLoss: 49000,
minuteEstimatedTime: 60,
};
},
});

// 4. Register frame
addFrame({
frameName: "week-backtest",
interval: "1m",
startDate: new Date("2024-01-01"),
endDate: new Date("2024-01-07"),
});

// 5. Listen to backtest events
listenSignalBacktest((event) => {
if (event.action === "closed") {
console.log("PNL:", event.pnl.pnlPercentage);
}
});

// 6. Run backtest
for await (const result of Backtest.run("BTCUSDT", {
strategyName: "momentum-strategy",
exchangeName: "binance",
frameName: "week-backtest",
})) {
console.log("Closed signal:", result.closeReason);
}

// 7. Generate report
const markdown = await Backtest.getReport("momentum-strategy");
await Backtest.dump("momentum-strategy");

// 8. Run live trading
for await (const result of Live.run("BTCUSDT", {
strategyName: "momentum-strategy",
exchangeName: "binance",
})) {
if (result.action === "opened") {
console.log("Signal opened:", result.signal.id);
}
if (result.action === "closed") {
await Live.dump("momentum-strategy");
}
}