Skip to main content

Documentation Index

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

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

getAggregatedTrades retrieves recent trade-by-trade history for a symbol from the registered exchange adapter. Like all data-fetching functions in Backtest Kit, it uses AsyncLocalStorage to read the current execution context and aligns the to boundary strictly to the 1-minute mark, guaranteeing that no future trades can leak into the dataset. The function supports both single-window and paginated fetches depending on whether a limit is specified.

IAggregatedTradeData

interface IAggregatedTradeData {
  id: string;
  price: number;
  qty: number;
  timestamp: number;  // Unix ms
  isBuyerMaker: boolean; // true if buyer is the market maker (sell-initiated trade)
}
isBuyerMaker: true means the buyer placed a resting limit order that was filled by an aggressive sell — i.e., a sell-driven trade. false means a buy-initiated aggressive trade.

getAggregatedTrades

getAggregatedTrades(symbol: string, limit?: number): Promise<IAggregatedTradeData[]>
symbol
string
required
Trading pair symbol (e.g., "BTCUSDT").
limit
number
Optional maximum number of most-recent trades to return. When omitted, one full CC_AGGREGATED_TRADES_MAX_MINUTES window is returned. When provided, the function paginates backwards until at least limit trades are collected, then slices to the limit most recent trades.

Time Alignment

The to timestamp is always aligned down to the nearest 1-minute boundary to prevent look-ahead bias:
alignedTo = Math.floor(when / 60_000) * 60_000
windowMs  = (CC_AGGREGATED_TRADES_MAX_MINUTES * 60_000) - 60_000
to        = alignedTo
from      = alignedTo - windowMs
Example with CC_AGGREGATED_TRADES_MAX_MINUTES = 60 and when = 00:12:30.500 UTC:
FieldValue
alignedTo / to00:12:00 UTC
from23:13:00 UTC (previous hour)

Configuration

CC_AGGREGATED_TRADES_MAX_MINUTES
number
Maximum minutes of trade history to fetch per window. Used to compute the default from/to range and each pagination chunk size. Required by exchanges like Binance that limit the startTime/endTime window to a fixed duration.
import { setConfig } from 'backtest-kit';

setConfig({
  CC_AGGREGATED_TRADES_MAX_MINUTES: 60,  // 1-hour windows (Binance default)
});

Pagination Behavior

Without limit: One single [from, to] window is fetched and returned as-is. With limit: The function paginates backwards in CC_AGGREGATED_TRADES_MAX_MINUTES chunks until the collected array contains at least limit entries. It then slices to return only the limit most recent trades (closest to alignedTo).
Window 1: from = alignedTo - 59min,  to = alignedTo          → e.g. 120 trades
  total = 120  — not enough if limit = 200

Window 2: from = window1.from - 59min, to = window1.from      → e.g. 100 trades
  total = 220  — enough, slice to most recent 200

Exchange Adapter Contract

The adapter receives aligned from and to as Date objects. Live implementations may ignore these and return the current trade stream.
getAggregatedTrades(
  symbol: string,
  from: Date,
  to: Date,
  backtest: boolean
): Promise<IAggregatedTradeData[]>
If getAggregatedTrades is not provided in the exchange schema, calling the function from a strategy throws an error.

Compatible Packages

The [from, to] time range format produced by this function is directly compatible with:
  • garch — GARCH volatility modelling on trade-by-trade data
  • volume-anomaly — detecting abnormal trade volume bursts

Usage Example

import { addStrategySchema, getAggregatedTrades } from 'backtest-kit';

addStrategySchema({
  strategyName: 'volume-strategy',
  interval: '1m',
  getSignal: async (symbol) => {
    // Last 500 trades
    const trades = await getAggregatedTrades(symbol, 500);

    const buyVolume = trades
      .filter(t => !t.isBuyerMaker)
      .reduce((sum, t) => sum + t.qty, 0);

    const sellVolume = trades
      .filter(t => t.isBuyerMaker)
      .reduce((sum, t) => sum + t.qty, 0);

    const ratio = buyVolume / (buyVolume + sellVolume);

    if (ratio > 0.65) {
      // Strong buy-side dominance
      const lastPrice = trades[trades.length - 1].price;
      return {
        position: 'long',
        priceTakeProfit: lastPrice * 1.015,
        priceStopLoss: lastPrice * 0.99,
      };
    }

    return null;
  },
});

Build docs developers (and LLMs) love