backtest-kit 3.4.1 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.cjs CHANGED
@@ -428,6 +428,12 @@ const GLOBAL_CONFIG = {
428
428
  * Default: 20 levels
429
429
  */
430
430
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: 1000,
431
+ /**
432
+ * Maximum minutes of aggregated trades to fetch when no limit is provided.
433
+ * If limit is not specified, the system will fetch aggregated trades for this many minutes starting from the current time minus the offset.
434
+ * Binance requirement
435
+ */
436
+ CC_AGGREGATED_TRADES_MAX_MINUTES: 60,
431
437
  /**
432
438
  * Maximum number of notifications to keep in storage.
433
439
  * Older notifications are removed when this limit is exceeded.
@@ -2800,6 +2806,55 @@ class ClientExchange {
2800
2806
  GLOBAL_CONFIG.CC_ORDER_BOOK_TIME_OFFSET_MINUTES * MS_PER_MINUTE$5);
2801
2807
  return await this.params.getOrderBook(symbol, depth, from, to, this.params.execution.context.backtest);
2802
2808
  }
2809
+ /**
2810
+ * Fetches aggregated trades backwards from execution context time.
2811
+ *
2812
+ * Algorithm:
2813
+ * 1. Align when down to the nearest minute boundary (1-minute granularity)
2814
+ * 2. If limit is not specified: fetch one window of CC_AGGREGATED_TRADES_MAX_MINUTES
2815
+ * 3. If limit is specified: paginate backwards in CC_AGGREGATED_TRADES_MAX_MINUTES
2816
+ * chunks until at least limit trades are collected, then slice to limit
2817
+ *
2818
+ * Look-ahead bias prevention:
2819
+ * - `to` is always aligned down to the minute (never exceeds current when)
2820
+ * - Each pagination window goes strictly backwards from alignedWhen
2821
+ *
2822
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
2823
+ * @param limit - Optional maximum number of trades to return. If not specified,
2824
+ * returns all trades within the last CC_AGGREGATED_TRADES_MAX_MINUTES window.
2825
+ * @returns Promise resolving to array of aggregated trade data
2826
+ */
2827
+ async getAggregatedTrades(symbol, limit) {
2828
+ this.params.logger.debug("ClientExchange getAggregatedTrades", {
2829
+ symbol,
2830
+ limit,
2831
+ });
2832
+ const whenTimestamp = this.params.execution.context.when.getTime();
2833
+ // Align to 1-minute boundary to prevent look-ahead bias
2834
+ const alignedTo = ALIGN_TO_INTERVAL_FN$2(whenTimestamp, 1);
2835
+ const windowMs = GLOBAL_CONFIG.CC_AGGREGATED_TRADES_MAX_MINUTES * MS_PER_MINUTE$5 - MS_PER_MINUTE$5;
2836
+ // No limit: fetch a single window and return as-is
2837
+ if (limit === undefined) {
2838
+ const to = new Date(alignedTo);
2839
+ const from = new Date(alignedTo - windowMs);
2840
+ return await this.params.getAggregatedTrades(symbol, from, to, this.params.execution.context.backtest);
2841
+ }
2842
+ // With limit: paginate backwards until we have enough trades
2843
+ const result = [];
2844
+ let windowEnd = alignedTo;
2845
+ while (result.length < limit) {
2846
+ const windowStart = windowEnd - windowMs;
2847
+ const to = new Date(windowEnd);
2848
+ const from = new Date(windowStart);
2849
+ const chunk = await this.params.getAggregatedTrades(symbol, from, to, this.params.execution.context.backtest);
2850
+ // Prepend chunk (older data goes first)
2851
+ result.unshift(...chunk);
2852
+ // Move window backwards
2853
+ windowEnd = windowStart;
2854
+ }
2855
+ // Slice to requested limit (most recent trades)
2856
+ return result.slice(-limit);
2857
+ }
2803
2858
  }
2804
2859
 
2805
2860
  /**
@@ -2836,6 +2891,18 @@ const DEFAULT_FORMAT_PRICE_FN$1 = async (_symbol, price, _backtest) => {
2836
2891
  const DEFAULT_GET_ORDER_BOOK_FN$1 = async (_symbol, _depth, _from, _to, _backtest) => {
2837
2892
  throw new Error(`getOrderBook is not implemented for this exchange`);
2838
2893
  };
2894
+ /**
2895
+ * Default implementation for getAggregatedTrades.
2896
+ * Throws an error indicating the method is not implemented.
2897
+ *
2898
+ * @param _symbol - Trading pair symbol (unused)
2899
+ * @param _from - Start of time range (unused - can be ignored in live implementations)
2900
+ * @param _to - End of time range (unused - can be ignored in live implementations)
2901
+ * @param _backtest - Whether running in backtest mode (unused)
2902
+ */
2903
+ const DEFAULT_GET_AGGREGATED_TRADES_FN$1 = async (_symbol, _from, _to, _backtest) => {
2904
+ throw new Error(`getAggregatedTrades is not implemented for this exchange`);
2905
+ };
2839
2906
  /**
2840
2907
  * Connection service routing exchange operations to correct ClientExchange instance.
2841
2908
  *
@@ -2874,7 +2941,7 @@ class ExchangeConnectionService {
2874
2941
  * @returns Configured ClientExchange instance
2875
2942
  */
2876
2943
  this.getExchange = functoolsKit.memoize(([exchangeName]) => `${exchangeName}`, (exchangeName) => {
2877
- const { getCandles = DEFAULT_GET_CANDLES_FN$1, formatPrice = DEFAULT_FORMAT_PRICE_FN$1, formatQuantity = DEFAULT_FORMAT_QUANTITY_FN$1, getOrderBook = DEFAULT_GET_ORDER_BOOK_FN$1, callbacks } = this.exchangeSchemaService.get(exchangeName);
2944
+ const { getCandles = DEFAULT_GET_CANDLES_FN$1, formatPrice = DEFAULT_FORMAT_PRICE_FN$1, formatQuantity = DEFAULT_FORMAT_QUANTITY_FN$1, getOrderBook = DEFAULT_GET_ORDER_BOOK_FN$1, getAggregatedTrades = DEFAULT_GET_AGGREGATED_TRADES_FN$1, callbacks } = this.exchangeSchemaService.get(exchangeName);
2878
2945
  return new ClientExchange({
2879
2946
  execution: this.executionContextService,
2880
2947
  logger: this.loggerService,
@@ -2883,6 +2950,7 @@ class ExchangeConnectionService {
2883
2950
  formatPrice,
2884
2951
  formatQuantity,
2885
2952
  getOrderBook,
2953
+ getAggregatedTrades,
2886
2954
  callbacks,
2887
2955
  });
2888
2956
  });
@@ -2988,6 +3056,22 @@ class ExchangeConnectionService {
2988
3056
  });
2989
3057
  return await this.getExchange(this.methodContextService.context.exchangeName).getOrderBook(symbol, depth);
2990
3058
  };
3059
+ /**
3060
+ * Fetches aggregated trades for a trading pair using configured exchange.
3061
+ *
3062
+ * Routes to exchange determined by methodContextService.context.exchangeName.
3063
+ *
3064
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
3065
+ * @param limit - Optional maximum number of trades to fetch. If empty returns one window of data.
3066
+ * @returns Promise resolving to array of aggregated trade data
3067
+ */
3068
+ this.getAggregatedTrades = async (symbol, limit) => {
3069
+ this.loggerService.log("exchangeConnectionService getAggregatedTrades", {
3070
+ symbol,
3071
+ limit,
3072
+ });
3073
+ return await this.getExchange(this.methodContextService.context.exchangeName).getAggregatedTrades(symbol, limit);
3074
+ };
2991
3075
  /**
2992
3076
  * Fetches raw candles with flexible date/limit parameters.
2993
3077
  *
@@ -11361,6 +11445,34 @@ class ExchangeCoreService {
11361
11445
  backtest,
11362
11446
  });
11363
11447
  };
11448
+ /**
11449
+ * Fetches aggregated trades with execution context.
11450
+ *
11451
+ * @param symbol - Trading pair symbol
11452
+ * @param when - Timestamp for context (used in backtest mode)
11453
+ * @param backtest - Whether running in backtest mode
11454
+ * @param limit - Optional maximum number of trades to fetch
11455
+ * @returns Promise resolving to array of aggregated trade data
11456
+ */
11457
+ this.getAggregatedTrades = async (symbol, when, backtest, limit) => {
11458
+ this.loggerService.log("exchangeCoreService getAggregatedTrades", {
11459
+ symbol,
11460
+ when,
11461
+ backtest,
11462
+ limit,
11463
+ });
11464
+ if (!MethodContextService.hasContext()) {
11465
+ throw new Error("exchangeCoreService getAggregatedTrades requires a method context");
11466
+ }
11467
+ await this.validate(this.methodContextService.context.exchangeName);
11468
+ return await ExecutionContextService.runInContext(async () => {
11469
+ return await this.exchangeConnectionService.getAggregatedTrades(symbol, limit);
11470
+ }, {
11471
+ symbol,
11472
+ when,
11473
+ backtest,
11474
+ });
11475
+ };
11364
11476
  /**
11365
11477
  * Fetches raw candles with flexible date/limit parameters and execution context.
11366
11478
  *
@@ -26780,6 +26892,7 @@ const EXCHANGE_METHOD_NAME_FORMAT_QUANTITY = "ExchangeUtils.formatQuantity";
26780
26892
  const EXCHANGE_METHOD_NAME_FORMAT_PRICE = "ExchangeUtils.formatPrice";
26781
26893
  const EXCHANGE_METHOD_NAME_GET_ORDER_BOOK = "ExchangeUtils.getOrderBook";
26782
26894
  const EXCHANGE_METHOD_NAME_GET_RAW_CANDLES = "ExchangeUtils.getRawCandles";
26895
+ const EXCHANGE_METHOD_NAME_GET_AGGREGATED_TRADES = "ExchangeUtils.getAggregatedTrades";
26783
26896
  const MS_PER_MINUTE$3 = 60000;
26784
26897
  /**
26785
26898
  * Gets current timestamp from execution context if available.
@@ -26835,6 +26948,18 @@ const DEFAULT_FORMAT_PRICE_FN = async (_symbol, price, _backtest) => {
26835
26948
  const DEFAULT_GET_ORDER_BOOK_FN = async (_symbol, _depth, _from, _to, _backtest) => {
26836
26949
  throw new Error(`getOrderBook is not implemented for this exchange`);
26837
26950
  };
26951
+ /**
26952
+ * Default implementation for getAggregatedTrades.
26953
+ * Throws an error indicating the method is not implemented.
26954
+ *
26955
+ * @param _symbol - Trading pair symbol (unused)
26956
+ * @param _from - Start of time range (unused - can be ignored in live implementations)
26957
+ * @param _to - End of time range (unused - can be ignored in live implementations)
26958
+ * @param _backtest - Whether running in backtest mode (unused)
26959
+ */
26960
+ const DEFAULT_GET_AGGREGATED_TRADES_FN = async (_symbol, _from, _to, _backtest) => {
26961
+ throw new Error(`getAggregatedTrades is not implemented for this exchange`);
26962
+ };
26838
26963
  const INTERVAL_MINUTES$3 = {
26839
26964
  "1m": 1,
26840
26965
  "3m": 3,
@@ -26880,11 +27005,13 @@ const CREATE_EXCHANGE_INSTANCE_FN = (schema) => {
26880
27005
  const formatQuantity = schema.formatQuantity ?? DEFAULT_FORMAT_QUANTITY_FN;
26881
27006
  const formatPrice = schema.formatPrice ?? DEFAULT_FORMAT_PRICE_FN;
26882
27007
  const getOrderBook = schema.getOrderBook ?? DEFAULT_GET_ORDER_BOOK_FN;
27008
+ const getAggregatedTrades = schema.getAggregatedTrades ?? DEFAULT_GET_AGGREGATED_TRADES_FN;
26883
27009
  return {
26884
27010
  getCandles,
26885
27011
  formatQuantity,
26886
27012
  formatPrice,
26887
27013
  getOrderBook,
27014
+ getAggregatedTrades,
26888
27015
  };
26889
27016
  };
26890
27017
  /**
@@ -27196,6 +27323,58 @@ class ExchangeInstance {
27196
27323
  const isBacktest = await GET_BACKTEST_FN();
27197
27324
  return await this._methods.getOrderBook(symbol, depth, from, to, isBacktest);
27198
27325
  };
27326
+ /**
27327
+ * Fetch aggregated trades for a trading pair.
27328
+ *
27329
+ * Calculates time range backwards from current timestamp (or execution context when).
27330
+ * Aligns `to` to 1-minute boundary to prevent look-ahead bias.
27331
+ * If limit is not specified, returns all trades within one CC_AGGREGATED_TRADES_MAX_MINUTES window.
27332
+ * If limit is specified, paginates backwards until at least limit trades are collected.
27333
+ *
27334
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
27335
+ * @param limit - Optional maximum number of trades to return
27336
+ * @returns Promise resolving to array of aggregated trade data
27337
+ *
27338
+ * @example
27339
+ * ```typescript
27340
+ * const instance = new ExchangeInstance("binance");
27341
+ * const trades = await instance.getAggregatedTrades("BTCUSDT");
27342
+ * const lastN = await instance.getAggregatedTrades("BTCUSDT", 500);
27343
+ * ```
27344
+ */
27345
+ this.getAggregatedTrades = async (symbol, limit) => {
27346
+ bt.loggerService.info(EXCHANGE_METHOD_NAME_GET_AGGREGATED_TRADES, {
27347
+ exchangeName: this.exchangeName,
27348
+ symbol,
27349
+ limit,
27350
+ });
27351
+ const when = await GET_TIMESTAMP_FN();
27352
+ // Align to 1-minute boundary to prevent look-ahead bias
27353
+ const alignedTo = ALIGN_TO_INTERVAL_FN$1(when.getTime(), 1);
27354
+ const windowMs = GLOBAL_CONFIG.CC_AGGREGATED_TRADES_MAX_MINUTES * MS_PER_MINUTE$3 - MS_PER_MINUTE$3;
27355
+ const isBacktest = await GET_BACKTEST_FN();
27356
+ // No limit: fetch a single window and return as-is
27357
+ if (limit === undefined) {
27358
+ const to = new Date(alignedTo);
27359
+ const from = new Date(alignedTo - windowMs);
27360
+ return await this._methods.getAggregatedTrades(symbol, from, to, isBacktest);
27361
+ }
27362
+ // With limit: paginate backwards until we have enough trades
27363
+ const result = [];
27364
+ let windowEnd = alignedTo;
27365
+ while (result.length < limit) {
27366
+ const windowStart = windowEnd - windowMs;
27367
+ const to = new Date(windowEnd);
27368
+ const from = new Date(windowStart);
27369
+ const chunk = await this._methods.getAggregatedTrades(symbol, from, to, isBacktest);
27370
+ // Prepend chunk (older data goes first)
27371
+ result.unshift(...chunk);
27372
+ // Move window backwards
27373
+ windowEnd = windowStart;
27374
+ }
27375
+ // Slice to requested limit (most recent trades)
27376
+ return result.slice(-limit);
27377
+ };
27199
27378
  /**
27200
27379
  * Fetches raw candles with flexible date/limit parameters.
27201
27380
  *
@@ -27465,6 +27644,19 @@ class ExchangeUtils {
27465
27644
  const instance = this._getInstance(context.exchangeName);
27466
27645
  return await instance.getOrderBook(symbol, depth);
27467
27646
  };
27647
+ /**
27648
+ * Fetch aggregated trades for a trading pair.
27649
+ *
27650
+ * @param symbol - Trading pair symbol
27651
+ * @param context - Execution context with exchange name
27652
+ * @param limit - Optional maximum number of trades to return
27653
+ * @returns Promise resolving to array of aggregated trade data
27654
+ */
27655
+ this.getAggregatedTrades = async (symbol, context, limit) => {
27656
+ bt.exchangeValidationService.validate(context.exchangeName, EXCHANGE_METHOD_NAME_GET_AGGREGATED_TRADES);
27657
+ const instance = this._getInstance(context.exchangeName);
27658
+ return await instance.getAggregatedTrades(symbol, limit);
27659
+ };
27468
27660
  /**
27469
27661
  * Fetches raw candles with flexible date/limit parameters.
27470
27662
  *
@@ -28004,6 +28196,7 @@ const HAS_TRADE_CONTEXT_METHOD_NAME = "exchange.hasTradeContext";
28004
28196
  const GET_ORDER_BOOK_METHOD_NAME = "exchange.getOrderBook";
28005
28197
  const GET_RAW_CANDLES_METHOD_NAME = "exchange.getRawCandles";
28006
28198
  const GET_NEXT_CANDLES_METHOD_NAME = "exchange.getNextCandles";
28199
+ const GET_AGGREGATED_TRADES_METHOD_NAME = "exchange.getAggregatedTrades";
28007
28200
  /**
28008
28201
  * Checks if trade context is active (execution and method contexts).
28009
28202
  *
@@ -28332,6 +28525,41 @@ async function getNextCandles(symbol, interval, limit) {
28332
28525
  }
28333
28526
  return await bt.exchangeConnectionService.getNextCandles(symbol, interval, limit);
28334
28527
  }
28528
+ /**
28529
+ * Fetches aggregated trades for a trading pair from the registered exchange.
28530
+ *
28531
+ * Trades are fetched backwards from the current execution context time.
28532
+ * If limit is not specified, returns all trades within one CC_AGGREGATED_TRADES_MAX_MINUTES window.
28533
+ * If limit is specified, paginates backwards until at least limit trades are collected.
28534
+ *
28535
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
28536
+ * @param limit - Optional maximum number of trades to fetch
28537
+ * @returns Promise resolving to array of aggregated trade data
28538
+ * @throws Error if execution or method context is missing
28539
+ *
28540
+ * @example
28541
+ * ```typescript
28542
+ * // Fetch last hour of trades
28543
+ * const trades = await getAggregatedTrades("BTCUSDT");
28544
+ *
28545
+ * // Fetch last 500 trades
28546
+ * const lastTrades = await getAggregatedTrades("BTCUSDT", 500);
28547
+ * console.log(lastTrades[0]); // { id, price, qty, timestamp, isBuyerMaker }
28548
+ * ```
28549
+ */
28550
+ async function getAggregatedTrades(symbol, limit) {
28551
+ bt.loggerService.info(GET_AGGREGATED_TRADES_METHOD_NAME, {
28552
+ symbol,
28553
+ limit,
28554
+ });
28555
+ if (!ExecutionContextService.hasContext()) {
28556
+ throw new Error("getAggregatedTrades requires an execution context");
28557
+ }
28558
+ if (!MethodContextService.hasContext()) {
28559
+ throw new Error("getAggregatedTrades requires a method context");
28560
+ }
28561
+ return await bt.exchangeConnectionService.getAggregatedTrades(symbol, limit);
28562
+ }
28335
28563
 
28336
28564
  const CANCEL_SCHEDULED_METHOD_NAME = "strategy.commitCancelScheduled";
28337
28565
  const CLOSE_PENDING_METHOD_NAME = "strategy.commitClosePending";
@@ -38866,6 +39094,7 @@ exports.formatPrice = formatPrice;
38866
39094
  exports.formatQuantity = formatQuantity;
38867
39095
  exports.get = get;
38868
39096
  exports.getActionSchema = getActionSchema;
39097
+ exports.getAggregatedTrades = getAggregatedTrades;
38869
39098
  exports.getAveragePrice = getAveragePrice;
38870
39099
  exports.getBacktestTimeframe = getBacktestTimeframe;
38871
39100
  exports.getCandles = getCandles;
package/build/index.mjs CHANGED
@@ -408,6 +408,12 @@ const GLOBAL_CONFIG = {
408
408
  * Default: 20 levels
409
409
  */
410
410
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: 1000,
411
+ /**
412
+ * Maximum minutes of aggregated trades to fetch when no limit is provided.
413
+ * If limit is not specified, the system will fetch aggregated trades for this many minutes starting from the current time minus the offset.
414
+ * Binance requirement
415
+ */
416
+ CC_AGGREGATED_TRADES_MAX_MINUTES: 60,
411
417
  /**
412
418
  * Maximum number of notifications to keep in storage.
413
419
  * Older notifications are removed when this limit is exceeded.
@@ -2780,6 +2786,55 @@ class ClientExchange {
2780
2786
  GLOBAL_CONFIG.CC_ORDER_BOOK_TIME_OFFSET_MINUTES * MS_PER_MINUTE$5);
2781
2787
  return await this.params.getOrderBook(symbol, depth, from, to, this.params.execution.context.backtest);
2782
2788
  }
2789
+ /**
2790
+ * Fetches aggregated trades backwards from execution context time.
2791
+ *
2792
+ * Algorithm:
2793
+ * 1. Align when down to the nearest minute boundary (1-minute granularity)
2794
+ * 2. If limit is not specified: fetch one window of CC_AGGREGATED_TRADES_MAX_MINUTES
2795
+ * 3. If limit is specified: paginate backwards in CC_AGGREGATED_TRADES_MAX_MINUTES
2796
+ * chunks until at least limit trades are collected, then slice to limit
2797
+ *
2798
+ * Look-ahead bias prevention:
2799
+ * - `to` is always aligned down to the minute (never exceeds current when)
2800
+ * - Each pagination window goes strictly backwards from alignedWhen
2801
+ *
2802
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
2803
+ * @param limit - Optional maximum number of trades to return. If not specified,
2804
+ * returns all trades within the last CC_AGGREGATED_TRADES_MAX_MINUTES window.
2805
+ * @returns Promise resolving to array of aggregated trade data
2806
+ */
2807
+ async getAggregatedTrades(symbol, limit) {
2808
+ this.params.logger.debug("ClientExchange getAggregatedTrades", {
2809
+ symbol,
2810
+ limit,
2811
+ });
2812
+ const whenTimestamp = this.params.execution.context.when.getTime();
2813
+ // Align to 1-minute boundary to prevent look-ahead bias
2814
+ const alignedTo = ALIGN_TO_INTERVAL_FN$2(whenTimestamp, 1);
2815
+ const windowMs = GLOBAL_CONFIG.CC_AGGREGATED_TRADES_MAX_MINUTES * MS_PER_MINUTE$5 - MS_PER_MINUTE$5;
2816
+ // No limit: fetch a single window and return as-is
2817
+ if (limit === undefined) {
2818
+ const to = new Date(alignedTo);
2819
+ const from = new Date(alignedTo - windowMs);
2820
+ return await this.params.getAggregatedTrades(symbol, from, to, this.params.execution.context.backtest);
2821
+ }
2822
+ // With limit: paginate backwards until we have enough trades
2823
+ const result = [];
2824
+ let windowEnd = alignedTo;
2825
+ while (result.length < limit) {
2826
+ const windowStart = windowEnd - windowMs;
2827
+ const to = new Date(windowEnd);
2828
+ const from = new Date(windowStart);
2829
+ const chunk = await this.params.getAggregatedTrades(symbol, from, to, this.params.execution.context.backtest);
2830
+ // Prepend chunk (older data goes first)
2831
+ result.unshift(...chunk);
2832
+ // Move window backwards
2833
+ windowEnd = windowStart;
2834
+ }
2835
+ // Slice to requested limit (most recent trades)
2836
+ return result.slice(-limit);
2837
+ }
2783
2838
  }
2784
2839
 
2785
2840
  /**
@@ -2816,6 +2871,18 @@ const DEFAULT_FORMAT_PRICE_FN$1 = async (_symbol, price, _backtest) => {
2816
2871
  const DEFAULT_GET_ORDER_BOOK_FN$1 = async (_symbol, _depth, _from, _to, _backtest) => {
2817
2872
  throw new Error(`getOrderBook is not implemented for this exchange`);
2818
2873
  };
2874
+ /**
2875
+ * Default implementation for getAggregatedTrades.
2876
+ * Throws an error indicating the method is not implemented.
2877
+ *
2878
+ * @param _symbol - Trading pair symbol (unused)
2879
+ * @param _from - Start of time range (unused - can be ignored in live implementations)
2880
+ * @param _to - End of time range (unused - can be ignored in live implementations)
2881
+ * @param _backtest - Whether running in backtest mode (unused)
2882
+ */
2883
+ const DEFAULT_GET_AGGREGATED_TRADES_FN$1 = async (_symbol, _from, _to, _backtest) => {
2884
+ throw new Error(`getAggregatedTrades is not implemented for this exchange`);
2885
+ };
2819
2886
  /**
2820
2887
  * Connection service routing exchange operations to correct ClientExchange instance.
2821
2888
  *
@@ -2854,7 +2921,7 @@ class ExchangeConnectionService {
2854
2921
  * @returns Configured ClientExchange instance
2855
2922
  */
2856
2923
  this.getExchange = memoize(([exchangeName]) => `${exchangeName}`, (exchangeName) => {
2857
- const { getCandles = DEFAULT_GET_CANDLES_FN$1, formatPrice = DEFAULT_FORMAT_PRICE_FN$1, formatQuantity = DEFAULT_FORMAT_QUANTITY_FN$1, getOrderBook = DEFAULT_GET_ORDER_BOOK_FN$1, callbacks } = this.exchangeSchemaService.get(exchangeName);
2924
+ const { getCandles = DEFAULT_GET_CANDLES_FN$1, formatPrice = DEFAULT_FORMAT_PRICE_FN$1, formatQuantity = DEFAULT_FORMAT_QUANTITY_FN$1, getOrderBook = DEFAULT_GET_ORDER_BOOK_FN$1, getAggregatedTrades = DEFAULT_GET_AGGREGATED_TRADES_FN$1, callbacks } = this.exchangeSchemaService.get(exchangeName);
2858
2925
  return new ClientExchange({
2859
2926
  execution: this.executionContextService,
2860
2927
  logger: this.loggerService,
@@ -2863,6 +2930,7 @@ class ExchangeConnectionService {
2863
2930
  formatPrice,
2864
2931
  formatQuantity,
2865
2932
  getOrderBook,
2933
+ getAggregatedTrades,
2866
2934
  callbacks,
2867
2935
  });
2868
2936
  });
@@ -2968,6 +3036,22 @@ class ExchangeConnectionService {
2968
3036
  });
2969
3037
  return await this.getExchange(this.methodContextService.context.exchangeName).getOrderBook(symbol, depth);
2970
3038
  };
3039
+ /**
3040
+ * Fetches aggregated trades for a trading pair using configured exchange.
3041
+ *
3042
+ * Routes to exchange determined by methodContextService.context.exchangeName.
3043
+ *
3044
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
3045
+ * @param limit - Optional maximum number of trades to fetch. If empty returns one window of data.
3046
+ * @returns Promise resolving to array of aggregated trade data
3047
+ */
3048
+ this.getAggregatedTrades = async (symbol, limit) => {
3049
+ this.loggerService.log("exchangeConnectionService getAggregatedTrades", {
3050
+ symbol,
3051
+ limit,
3052
+ });
3053
+ return await this.getExchange(this.methodContextService.context.exchangeName).getAggregatedTrades(symbol, limit);
3054
+ };
2971
3055
  /**
2972
3056
  * Fetches raw candles with flexible date/limit parameters.
2973
3057
  *
@@ -11341,6 +11425,34 @@ class ExchangeCoreService {
11341
11425
  backtest,
11342
11426
  });
11343
11427
  };
11428
+ /**
11429
+ * Fetches aggregated trades with execution context.
11430
+ *
11431
+ * @param symbol - Trading pair symbol
11432
+ * @param when - Timestamp for context (used in backtest mode)
11433
+ * @param backtest - Whether running in backtest mode
11434
+ * @param limit - Optional maximum number of trades to fetch
11435
+ * @returns Promise resolving to array of aggregated trade data
11436
+ */
11437
+ this.getAggregatedTrades = async (symbol, when, backtest, limit) => {
11438
+ this.loggerService.log("exchangeCoreService getAggregatedTrades", {
11439
+ symbol,
11440
+ when,
11441
+ backtest,
11442
+ limit,
11443
+ });
11444
+ if (!MethodContextService.hasContext()) {
11445
+ throw new Error("exchangeCoreService getAggregatedTrades requires a method context");
11446
+ }
11447
+ await this.validate(this.methodContextService.context.exchangeName);
11448
+ return await ExecutionContextService.runInContext(async () => {
11449
+ return await this.exchangeConnectionService.getAggregatedTrades(symbol, limit);
11450
+ }, {
11451
+ symbol,
11452
+ when,
11453
+ backtest,
11454
+ });
11455
+ };
11344
11456
  /**
11345
11457
  * Fetches raw candles with flexible date/limit parameters and execution context.
11346
11458
  *
@@ -26760,6 +26872,7 @@ const EXCHANGE_METHOD_NAME_FORMAT_QUANTITY = "ExchangeUtils.formatQuantity";
26760
26872
  const EXCHANGE_METHOD_NAME_FORMAT_PRICE = "ExchangeUtils.formatPrice";
26761
26873
  const EXCHANGE_METHOD_NAME_GET_ORDER_BOOK = "ExchangeUtils.getOrderBook";
26762
26874
  const EXCHANGE_METHOD_NAME_GET_RAW_CANDLES = "ExchangeUtils.getRawCandles";
26875
+ const EXCHANGE_METHOD_NAME_GET_AGGREGATED_TRADES = "ExchangeUtils.getAggregatedTrades";
26763
26876
  const MS_PER_MINUTE$3 = 60000;
26764
26877
  /**
26765
26878
  * Gets current timestamp from execution context if available.
@@ -26815,6 +26928,18 @@ const DEFAULT_FORMAT_PRICE_FN = async (_symbol, price, _backtest) => {
26815
26928
  const DEFAULT_GET_ORDER_BOOK_FN = async (_symbol, _depth, _from, _to, _backtest) => {
26816
26929
  throw new Error(`getOrderBook is not implemented for this exchange`);
26817
26930
  };
26931
+ /**
26932
+ * Default implementation for getAggregatedTrades.
26933
+ * Throws an error indicating the method is not implemented.
26934
+ *
26935
+ * @param _symbol - Trading pair symbol (unused)
26936
+ * @param _from - Start of time range (unused - can be ignored in live implementations)
26937
+ * @param _to - End of time range (unused - can be ignored in live implementations)
26938
+ * @param _backtest - Whether running in backtest mode (unused)
26939
+ */
26940
+ const DEFAULT_GET_AGGREGATED_TRADES_FN = async (_symbol, _from, _to, _backtest) => {
26941
+ throw new Error(`getAggregatedTrades is not implemented for this exchange`);
26942
+ };
26818
26943
  const INTERVAL_MINUTES$3 = {
26819
26944
  "1m": 1,
26820
26945
  "3m": 3,
@@ -26860,11 +26985,13 @@ const CREATE_EXCHANGE_INSTANCE_FN = (schema) => {
26860
26985
  const formatQuantity = schema.formatQuantity ?? DEFAULT_FORMAT_QUANTITY_FN;
26861
26986
  const formatPrice = schema.formatPrice ?? DEFAULT_FORMAT_PRICE_FN;
26862
26987
  const getOrderBook = schema.getOrderBook ?? DEFAULT_GET_ORDER_BOOK_FN;
26988
+ const getAggregatedTrades = schema.getAggregatedTrades ?? DEFAULT_GET_AGGREGATED_TRADES_FN;
26863
26989
  return {
26864
26990
  getCandles,
26865
26991
  formatQuantity,
26866
26992
  formatPrice,
26867
26993
  getOrderBook,
26994
+ getAggregatedTrades,
26868
26995
  };
26869
26996
  };
26870
26997
  /**
@@ -27176,6 +27303,58 @@ class ExchangeInstance {
27176
27303
  const isBacktest = await GET_BACKTEST_FN();
27177
27304
  return await this._methods.getOrderBook(symbol, depth, from, to, isBacktest);
27178
27305
  };
27306
+ /**
27307
+ * Fetch aggregated trades for a trading pair.
27308
+ *
27309
+ * Calculates time range backwards from current timestamp (or execution context when).
27310
+ * Aligns `to` to 1-minute boundary to prevent look-ahead bias.
27311
+ * If limit is not specified, returns all trades within one CC_AGGREGATED_TRADES_MAX_MINUTES window.
27312
+ * If limit is specified, paginates backwards until at least limit trades are collected.
27313
+ *
27314
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
27315
+ * @param limit - Optional maximum number of trades to return
27316
+ * @returns Promise resolving to array of aggregated trade data
27317
+ *
27318
+ * @example
27319
+ * ```typescript
27320
+ * const instance = new ExchangeInstance("binance");
27321
+ * const trades = await instance.getAggregatedTrades("BTCUSDT");
27322
+ * const lastN = await instance.getAggregatedTrades("BTCUSDT", 500);
27323
+ * ```
27324
+ */
27325
+ this.getAggregatedTrades = async (symbol, limit) => {
27326
+ bt.loggerService.info(EXCHANGE_METHOD_NAME_GET_AGGREGATED_TRADES, {
27327
+ exchangeName: this.exchangeName,
27328
+ symbol,
27329
+ limit,
27330
+ });
27331
+ const when = await GET_TIMESTAMP_FN();
27332
+ // Align to 1-minute boundary to prevent look-ahead bias
27333
+ const alignedTo = ALIGN_TO_INTERVAL_FN$1(when.getTime(), 1);
27334
+ const windowMs = GLOBAL_CONFIG.CC_AGGREGATED_TRADES_MAX_MINUTES * MS_PER_MINUTE$3 - MS_PER_MINUTE$3;
27335
+ const isBacktest = await GET_BACKTEST_FN();
27336
+ // No limit: fetch a single window and return as-is
27337
+ if (limit === undefined) {
27338
+ const to = new Date(alignedTo);
27339
+ const from = new Date(alignedTo - windowMs);
27340
+ return await this._methods.getAggregatedTrades(symbol, from, to, isBacktest);
27341
+ }
27342
+ // With limit: paginate backwards until we have enough trades
27343
+ const result = [];
27344
+ let windowEnd = alignedTo;
27345
+ while (result.length < limit) {
27346
+ const windowStart = windowEnd - windowMs;
27347
+ const to = new Date(windowEnd);
27348
+ const from = new Date(windowStart);
27349
+ const chunk = await this._methods.getAggregatedTrades(symbol, from, to, isBacktest);
27350
+ // Prepend chunk (older data goes first)
27351
+ result.unshift(...chunk);
27352
+ // Move window backwards
27353
+ windowEnd = windowStart;
27354
+ }
27355
+ // Slice to requested limit (most recent trades)
27356
+ return result.slice(-limit);
27357
+ };
27179
27358
  /**
27180
27359
  * Fetches raw candles with flexible date/limit parameters.
27181
27360
  *
@@ -27445,6 +27624,19 @@ class ExchangeUtils {
27445
27624
  const instance = this._getInstance(context.exchangeName);
27446
27625
  return await instance.getOrderBook(symbol, depth);
27447
27626
  };
27627
+ /**
27628
+ * Fetch aggregated trades for a trading pair.
27629
+ *
27630
+ * @param symbol - Trading pair symbol
27631
+ * @param context - Execution context with exchange name
27632
+ * @param limit - Optional maximum number of trades to return
27633
+ * @returns Promise resolving to array of aggregated trade data
27634
+ */
27635
+ this.getAggregatedTrades = async (symbol, context, limit) => {
27636
+ bt.exchangeValidationService.validate(context.exchangeName, EXCHANGE_METHOD_NAME_GET_AGGREGATED_TRADES);
27637
+ const instance = this._getInstance(context.exchangeName);
27638
+ return await instance.getAggregatedTrades(symbol, limit);
27639
+ };
27448
27640
  /**
27449
27641
  * Fetches raw candles with flexible date/limit parameters.
27450
27642
  *
@@ -27984,6 +28176,7 @@ const HAS_TRADE_CONTEXT_METHOD_NAME = "exchange.hasTradeContext";
27984
28176
  const GET_ORDER_BOOK_METHOD_NAME = "exchange.getOrderBook";
27985
28177
  const GET_RAW_CANDLES_METHOD_NAME = "exchange.getRawCandles";
27986
28178
  const GET_NEXT_CANDLES_METHOD_NAME = "exchange.getNextCandles";
28179
+ const GET_AGGREGATED_TRADES_METHOD_NAME = "exchange.getAggregatedTrades";
27987
28180
  /**
27988
28181
  * Checks if trade context is active (execution and method contexts).
27989
28182
  *
@@ -28312,6 +28505,41 @@ async function getNextCandles(symbol, interval, limit) {
28312
28505
  }
28313
28506
  return await bt.exchangeConnectionService.getNextCandles(symbol, interval, limit);
28314
28507
  }
28508
+ /**
28509
+ * Fetches aggregated trades for a trading pair from the registered exchange.
28510
+ *
28511
+ * Trades are fetched backwards from the current execution context time.
28512
+ * If limit is not specified, returns all trades within one CC_AGGREGATED_TRADES_MAX_MINUTES window.
28513
+ * If limit is specified, paginates backwards until at least limit trades are collected.
28514
+ *
28515
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
28516
+ * @param limit - Optional maximum number of trades to fetch
28517
+ * @returns Promise resolving to array of aggregated trade data
28518
+ * @throws Error if execution or method context is missing
28519
+ *
28520
+ * @example
28521
+ * ```typescript
28522
+ * // Fetch last hour of trades
28523
+ * const trades = await getAggregatedTrades("BTCUSDT");
28524
+ *
28525
+ * // Fetch last 500 trades
28526
+ * const lastTrades = await getAggregatedTrades("BTCUSDT", 500);
28527
+ * console.log(lastTrades[0]); // { id, price, qty, timestamp, isBuyerMaker }
28528
+ * ```
28529
+ */
28530
+ async function getAggregatedTrades(symbol, limit) {
28531
+ bt.loggerService.info(GET_AGGREGATED_TRADES_METHOD_NAME, {
28532
+ symbol,
28533
+ limit,
28534
+ });
28535
+ if (!ExecutionContextService.hasContext()) {
28536
+ throw new Error("getAggregatedTrades requires an execution context");
28537
+ }
28538
+ if (!MethodContextService.hasContext()) {
28539
+ throw new Error("getAggregatedTrades requires a method context");
28540
+ }
28541
+ return await bt.exchangeConnectionService.getAggregatedTrades(symbol, limit);
28542
+ }
28315
28543
 
28316
28544
  const CANCEL_SCHEDULED_METHOD_NAME = "strategy.commitCancelScheduled";
28317
28545
  const CLOSE_PENDING_METHOD_NAME = "strategy.commitClosePending";
@@ -38783,4 +39011,4 @@ const set = (object, path, value) => {
38783
39011
  }
38784
39012
  };
38785
39013
 
38786
- export { ActionBase, Backtest, Breakeven, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, Log, Markdown, MarkdownFileBase, MarkdownFolderBase, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistLogAdapter, PersistNotificationAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, PositionSize, Report, ReportBase, Risk, Schedule, Storage, StorageBacktest, StorageLive, Strategy, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialProfit, commitTrailingStop, commitTrailingTake, dumpMessages, emitters, formatPrice, formatQuantity, get, getActionSchema, getAveragePrice, getBacktestTimeframe, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getExchangeSchema, getFrameSchema, getMode, getNextCandles, getOrderBook, getRawCandles, getRiskSchema, getSizingSchema, getStrategySchema, getSymbol, getWalkerSchema, hasTradeContext, backtest as lib, listExchangeSchema, listFrameSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, roundTicks, set, setColumns, setConfig, setLogger, stopStrategy, validate, waitForCandle, warmCandles };
39014
+ export { ActionBase, Backtest, Breakeven, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, Log, Markdown, MarkdownFileBase, MarkdownFolderBase, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistLogAdapter, PersistNotificationAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, PositionSize, Report, ReportBase, Risk, Schedule, Storage, StorageBacktest, StorageLive, Strategy, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialProfit, commitTrailingStop, commitTrailingTake, dumpMessages, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getExchangeSchema, getFrameSchema, getMode, getNextCandles, getOrderBook, getRawCandles, getRiskSchema, getSizingSchema, getStrategySchema, getSymbol, getWalkerSchema, hasTradeContext, backtest as lib, listExchangeSchema, listFrameSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, roundTicks, set, setColumns, setConfig, setLogger, stopStrategy, validate, waitForCandle, warmCandles };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "3.4.1",
3
+ "version": "3.5.0",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
package/types.d.ts CHANGED
@@ -160,6 +160,24 @@ interface IOrderBookData {
160
160
  /** Array of ask orders (sell orders) */
161
161
  asks: IBidData[];
162
162
  }
163
+ /**
164
+ * Aggregated trade data point.
165
+ * Represents a single trade that has occurred, used for detailed analysis and backtesting.
166
+ * Includes price, quantity, timestamp, and whether the buyer is the market maker (which can indicate trade direction).
167
+ *
168
+ */
169
+ interface IAggregatedTradeData {
170
+ /** Unique identifier for the aggregated trade */
171
+ id: string;
172
+ /** Price at which the trade occurred */
173
+ price: number;
174
+ /** Quantity traded */
175
+ qty: number;
176
+ /** Unix timestamp in milliseconds when the trade occurred */
177
+ timestamp: number;
178
+ /** Whether the buyer is the market maker (true if buyer is maker, false if seller is maker) */
179
+ isBuyerMaker: boolean;
180
+ }
163
181
  /**
164
182
  * Exchange parameters passed to ClientExchange constructor.
165
183
  * Combines schema with runtime dependencies.
@@ -178,6 +196,8 @@ interface IExchangeParams extends IExchangeSchema {
178
196
  formatPrice: (symbol: string, price: number, backtest: boolean) => Promise<string>;
179
197
  /** Fetch order book for a trading pair (required, defaults applied) */
180
198
  getOrderBook: (symbol: string, depth: number, from: Date, to: Date, backtest: boolean) => Promise<IOrderBookData>;
199
+ /** Fetch aggregated trades for a trading pair (required, defaults applied) */
200
+ getAggregatedTrades: (symbol: string, from: Date, to: Date, backtest: boolean) => Promise<IAggregatedTradeData[]>;
181
201
  }
182
202
  /**
183
203
  * Optional callbacks for exchange data events.
@@ -257,6 +277,31 @@ interface IExchangeSchema {
257
277
  * ```
258
278
  */
259
279
  getOrderBook?: (symbol: string, depth: number, from: Date, to: Date, backtest: boolean) => Promise<IOrderBookData>;
280
+ /**
281
+ * Fetch aggregated trades for a trading pair.
282
+ * Optional. If not provided, throws an error when called.
283
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
284
+ * @param from - Start of time range (used in backtest for historical data, can be ignored in live)
285
+ * @param to - End of time range (used in backtest for historical data, can be ignored in live)
286
+ * @param backtest - Whether running in backtest mode
287
+ * @return Promise resolving to array of aggregated trade data
288
+ * @example
289
+ * ```typescript
290
+ * // Backtest implementation: returns historical aggregated trades for the time range
291
+ * const backtestAggregatedTrades = async (symbol: string, from: Date, to: Date, backtest: boolean) => {
292
+ * if (backtest) {
293
+ * return await database.getAggregatedTrades(symbol, from, to);
294
+ * }
295
+ * return await exchange.fetchAggregatedTrades(symbol);
296
+ * };
297
+ *
298
+ * // Live implementation: ignores from/to when not in backtest mode
299
+ * const liveAggregatedTrades = async (symbol: string, _from: Date, _to: Date, backtest: boolean) => {
300
+ * return await exchange.fetchAggregatedTrades(symbol);
301
+ * };
302
+ * ```
303
+ */
304
+ getAggregatedTrades?: (symbol: string, from: Date, to: Date, backtest: boolean) => Promise<IAggregatedTradeData[]>;
260
305
  /** Optional lifecycle event callbacks (onCandleData) */
261
306
  callbacks?: Partial<IExchangeCallbacks>;
262
307
  }
@@ -317,6 +362,14 @@ interface IExchange {
317
362
  * @returns Promise resolving to order book data
318
363
  */
319
364
  getOrderBook: (symbol: string, depth?: number) => Promise<IOrderBookData>;
365
+ /**
366
+ * Fetch aggregated trades for a trading pair.
367
+ *
368
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
369
+ * @param limit - Optional maximum number of aggregated trades to fetch. If empty returns one hour of data.
370
+ * @returns Promise resolving to array of aggregated trade data
371
+ */
372
+ getAggregatedTrades: (symbol: string, limit?: number) => Promise<IAggregatedTradeData[]>;
320
373
  /**
321
374
  * Fetch raw candles with flexible date/limit parameters.
322
375
  *
@@ -4382,6 +4435,12 @@ declare const GLOBAL_CONFIG: {
4382
4435
  * Default: 20 levels
4383
4436
  */
4384
4437
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: number;
4438
+ /**
4439
+ * Maximum minutes of aggregated trades to fetch when no limit is provided.
4440
+ * If limit is not specified, the system will fetch aggregated trades for this many minutes starting from the current time minus the offset.
4441
+ * Binance requirement
4442
+ */
4443
+ CC_AGGREGATED_TRADES_MAX_MINUTES: number;
4385
4444
  /**
4386
4445
  * Maximum number of notifications to keep in storage.
4387
4446
  * Older notifications are removed when this limit is exceeded.
@@ -4517,6 +4576,7 @@ declare function getConfig(): {
4517
4576
  CC_BREAKEVEN_THRESHOLD: number;
4518
4577
  CC_ORDER_BOOK_TIME_OFFSET_MINUTES: number;
4519
4578
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: number;
4579
+ CC_AGGREGATED_TRADES_MAX_MINUTES: number;
4520
4580
  CC_MAX_NOTIFICATIONS: number;
4521
4581
  CC_MAX_SIGNALS: number;
4522
4582
  CC_MAX_LOG_LINES: number;
@@ -4555,6 +4615,7 @@ declare function getDefaultConfig(): Readonly<{
4555
4615
  CC_BREAKEVEN_THRESHOLD: number;
4556
4616
  CC_ORDER_BOOK_TIME_OFFSET_MINUTES: number;
4557
4617
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: number;
4618
+ CC_AGGREGATED_TRADES_MAX_MINUTES: number;
4558
4619
  CC_MAX_NOTIFICATIONS: number;
4559
4620
  CC_MAX_SIGNALS: number;
4560
4621
  CC_MAX_LOG_LINES: number;
@@ -6898,6 +6959,29 @@ declare function getRawCandles(symbol: string, interval: CandleInterval, limit?:
6898
6959
  * @returns Promise resolving to array of candle data
6899
6960
  */
6900
6961
  declare function getNextCandles(symbol: string, interval: CandleInterval, limit: number): Promise<ICandleData[]>;
6962
+ /**
6963
+ * Fetches aggregated trades for a trading pair from the registered exchange.
6964
+ *
6965
+ * Trades are fetched backwards from the current execution context time.
6966
+ * If limit is not specified, returns all trades within one CC_AGGREGATED_TRADES_MAX_MINUTES window.
6967
+ * If limit is specified, paginates backwards until at least limit trades are collected.
6968
+ *
6969
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
6970
+ * @param limit - Optional maximum number of trades to fetch
6971
+ * @returns Promise resolving to array of aggregated trade data
6972
+ * @throws Error if execution or method context is missing
6973
+ *
6974
+ * @example
6975
+ * ```typescript
6976
+ * // Fetch last hour of trades
6977
+ * const trades = await getAggregatedTrades("BTCUSDT");
6978
+ *
6979
+ * // Fetch last 500 trades
6980
+ * const lastTrades = await getAggregatedTrades("BTCUSDT", 500);
6981
+ * console.log(lastTrades[0]); // { id, price, qty, timestamp, isBuyerMaker }
6982
+ * ```
6983
+ */
6984
+ declare function getAggregatedTrades(symbol: string, limit?: number): Promise<IAggregatedTradeData[]>;
6901
6985
 
6902
6986
  /** Unique identifier for a dump result. Can be a string or numeric ID. */
6903
6987
  type ResultId = string | number;
@@ -14393,6 +14477,17 @@ declare class ExchangeUtils {
14393
14477
  getOrderBook: (symbol: string, context: {
14394
14478
  exchangeName: ExchangeName;
14395
14479
  }, depth?: number) => Promise<IOrderBookData>;
14480
+ /**
14481
+ * Fetch aggregated trades for a trading pair.
14482
+ *
14483
+ * @param symbol - Trading pair symbol
14484
+ * @param context - Execution context with exchange name
14485
+ * @param limit - Optional maximum number of trades to return
14486
+ * @returns Promise resolving to array of aggregated trade data
14487
+ */
14488
+ getAggregatedTrades: (symbol: string, context: {
14489
+ exchangeName: ExchangeName;
14490
+ }, limit?: number) => Promise<IAggregatedTradeData[]>;
14396
14491
  /**
14397
14492
  * Fetches raw candles with flexible date/limit parameters.
14398
14493
  *
@@ -17010,6 +17105,25 @@ declare class ClientExchange implements IExchange {
17010
17105
  * @throws Error if getOrderBook is not implemented
17011
17106
  */
17012
17107
  getOrderBook(symbol: string, depth?: number): Promise<IOrderBookData>;
17108
+ /**
17109
+ * Fetches aggregated trades backwards from execution context time.
17110
+ *
17111
+ * Algorithm:
17112
+ * 1. Align when down to the nearest minute boundary (1-minute granularity)
17113
+ * 2. If limit is not specified: fetch one window of CC_AGGREGATED_TRADES_MAX_MINUTES
17114
+ * 3. If limit is specified: paginate backwards in CC_AGGREGATED_TRADES_MAX_MINUTES
17115
+ * chunks until at least limit trades are collected, then slice to limit
17116
+ *
17117
+ * Look-ahead bias prevention:
17118
+ * - `to` is always aligned down to the minute (never exceeds current when)
17119
+ * - Each pagination window goes strictly backwards from alignedWhen
17120
+ *
17121
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
17122
+ * @param limit - Optional maximum number of trades to return. If not specified,
17123
+ * returns all trades within the last CC_AGGREGATED_TRADES_MAX_MINUTES window.
17124
+ * @returns Promise resolving to array of aggregated trade data
17125
+ */
17126
+ getAggregatedTrades(symbol: string, limit?: number): Promise<IAggregatedTradeData[]>;
17013
17127
  }
17014
17128
 
17015
17129
  /**
@@ -17114,6 +17228,16 @@ declare class ExchangeConnectionService implements IExchange {
17114
17228
  * @returns Promise resolving to order book data
17115
17229
  */
17116
17230
  getOrderBook: (symbol: string, depth?: number) => Promise<IOrderBookData>;
17231
+ /**
17232
+ * Fetches aggregated trades for a trading pair using configured exchange.
17233
+ *
17234
+ * Routes to exchange determined by methodContextService.context.exchangeName.
17235
+ *
17236
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
17237
+ * @param limit - Optional maximum number of trades to fetch. If empty returns one window of data.
17238
+ * @returns Promise resolving to array of aggregated trade data
17239
+ */
17240
+ getAggregatedTrades: (symbol: string, limit?: number) => Promise<IAggregatedTradeData[]>;
17117
17241
  /**
17118
17242
  * Fetches raw candles with flexible date/limit parameters.
17119
17243
  *
@@ -18850,6 +18974,16 @@ declare class ExchangeCoreService implements TExchange {
18850
18974
  * @returns Promise resolving to order book data
18851
18975
  */
18852
18976
  getOrderBook: (symbol: string, when: Date, backtest: boolean, depth?: number) => Promise<IOrderBookData>;
18977
+ /**
18978
+ * Fetches aggregated trades with execution context.
18979
+ *
18980
+ * @param symbol - Trading pair symbol
18981
+ * @param when - Timestamp for context (used in backtest mode)
18982
+ * @param backtest - Whether running in backtest mode
18983
+ * @param limit - Optional maximum number of trades to fetch
18984
+ * @returns Promise resolving to array of aggregated trade data
18985
+ */
18986
+ getAggregatedTrades: (symbol: string, when: Date, backtest: boolean, limit?: number) => Promise<IAggregatedTradeData[]>;
18853
18987
  /**
18854
18988
  * Fetches raw candles with flexible date/limit parameters and execution context.
18855
18989
  *
@@ -21452,4 +21586,4 @@ declare const backtest: {
21452
21586
  loggerService: LoggerService;
21453
21587
  };
21454
21588
 
21455
- export { ActionBase, type ActivateScheduledCommit, type ActivateScheduledCommitNotification, type ActivePingContract, type AverageBuyCommit, Backtest, type BacktestStatisticsModel, Breakeven, type BreakevenAvailableNotification, type BreakevenCommit, type BreakevenCommitNotification, type BreakevenContract, type BreakevenData, Cache, type CancelScheduledCommit, type CandleData, type CandleInterval, type ClosePendingCommit, type ColumnConfig, type ColumnModel, Constant, type CriticalErrorNotification, type DoneContract, type EntityId, Exchange, ExecutionContextService, type FrameInterval, type GlobalConfig, Heat, type HeatmapStatisticsModel, type IActionSchema, type IActivateScheduledCommitRow, type IBidData, type IBreakevenCommitRow, type ICandleData, type ICommitRow, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type ILog, type ILogEntry, type ILogger, type IMarkdownDumpOptions, type INotificationUtils, type IOrderBookData, type IPartialLossCommitRow, type IPartialProfitCommitRow, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IPublicAction, type IPublicCandleData, type IPublicSignalRow, type IReportDumpOptions, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskSignalRow, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, type IScheduledSignalCancelRow, type IScheduledSignalRow, type ISignalDto, type ISignalRow, type ISizingCalculateParams, type ISizingCalculateParamsATR, type ISizingCalculateParamsFixedPercentage, type ISizingCalculateParamsKelly, type ISizingParams, type ISizingParamsATR, type ISizingParamsFixedPercentage, type ISizingParamsKelly, type ISizingSchema, type ISizingSchemaATR, type ISizingSchemaFixedPercentage, type ISizingSchemaKelly, type IStorageSignalRow, type IStorageUtils, type IStrategyPnL, type IStrategyResult, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultCancelled, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IStrategyTickResultScheduled, type IStrategyTickResultWaiting, type ITrailingStopCommitRow, type ITrailingTakeCommitRow, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, type InfoErrorNotification, Live, type LiveStatisticsModel, Log, type LogData, Markdown, MarkdownFileBase, MarkdownFolderBase, type MarkdownName, MethodContextService, type MetricStats, Notification, NotificationBacktest, type NotificationData, NotificationLive, type NotificationModel, Partial$1 as Partial, type PartialData, type PartialEvent, type PartialLossAvailableNotification, type PartialLossCommit, type PartialLossCommitNotification, type PartialLossContract, type PartialProfitAvailableNotification, type PartialProfitCommit, type PartialProfitCommitNotification, type PartialProfitContract, type PartialStatisticsModel, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatisticsModel, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistLogAdapter, PersistNotificationAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, PositionSize, type ProgressBacktestContract, type ProgressWalkerContract, Report, ReportBase, type ReportName, Risk, type RiskContract, type RiskData, type RiskEvent, type RiskRejectionNotification, type RiskStatisticsModel, Schedule, type ScheduleData, type SchedulePingContract, type ScheduleStatisticsModel, type ScheduledEvent, type SignalCancelledNotification, type SignalClosedNotification, type SignalData, type SignalInterval, type SignalOpenedNotification, type SignalScheduledNotification, Storage, StorageBacktest, type StorageData, StorageLive, Strategy, type StrategyActionType, type StrategyCancelReason, type StrategyCloseReason, type StrategyCommitContract, type StrategyEvent, type StrategyStatisticsModel, type TLogCtor, type TMarkdownBase, type TNotificationUtilsCtor, type TPersistBase, type TPersistBaseCtor, type TReportBase, type TStorageUtilsCtor, type TickEvent, type TrailingStopCommit, type TrailingStopCommitNotification, type TrailingTakeCommit, type TrailingTakeCommitNotification, type ValidationErrorNotification, Walker, type WalkerCompleteContract, type WalkerContract, type WalkerMetric, type SignalData$1 as WalkerSignalData, type WalkerStatisticsModel, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialProfit, commitTrailingStop, commitTrailingTake, dumpMessages, emitters, formatPrice, formatQuantity, get, getActionSchema, getAveragePrice, getBacktestTimeframe, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getExchangeSchema, getFrameSchema, getMode, getNextCandles, getOrderBook, getRawCandles, getRiskSchema, getSizingSchema, getStrategySchema, getSymbol, getWalkerSchema, hasTradeContext, backtest as lib, listExchangeSchema, listFrameSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, roundTicks, set, setColumns, setConfig, setLogger, stopStrategy, validate, waitForCandle, warmCandles };
21589
+ export { ActionBase, type ActivateScheduledCommit, type ActivateScheduledCommitNotification, type ActivePingContract, type AverageBuyCommit, Backtest, type BacktestStatisticsModel, Breakeven, type BreakevenAvailableNotification, type BreakevenCommit, type BreakevenCommitNotification, type BreakevenContract, type BreakevenData, Cache, type CancelScheduledCommit, type CandleData, type CandleInterval, type ClosePendingCommit, type ColumnConfig, type ColumnModel, Constant, type CriticalErrorNotification, type DoneContract, type EntityId, Exchange, ExecutionContextService, type FrameInterval, type GlobalConfig, Heat, type HeatmapStatisticsModel, type IActionSchema, type IActivateScheduledCommitRow, type IAggregatedTradeData, type IBidData, type IBreakevenCommitRow, type ICandleData, type ICommitRow, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type ILog, type ILogEntry, type ILogger, type IMarkdownDumpOptions, type INotificationUtils, type IOrderBookData, type IPartialLossCommitRow, type IPartialProfitCommitRow, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IPublicAction, type IPublicCandleData, type IPublicSignalRow, type IReportDumpOptions, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskSignalRow, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, type IScheduledSignalCancelRow, type IScheduledSignalRow, type ISignalDto, type ISignalRow, type ISizingCalculateParams, type ISizingCalculateParamsATR, type ISizingCalculateParamsFixedPercentage, type ISizingCalculateParamsKelly, type ISizingParams, type ISizingParamsATR, type ISizingParamsFixedPercentage, type ISizingParamsKelly, type ISizingSchema, type ISizingSchemaATR, type ISizingSchemaFixedPercentage, type ISizingSchemaKelly, type IStorageSignalRow, type IStorageUtils, type IStrategyPnL, type IStrategyResult, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultCancelled, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IStrategyTickResultScheduled, type IStrategyTickResultWaiting, type ITrailingStopCommitRow, type ITrailingTakeCommitRow, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, type InfoErrorNotification, Live, type LiveStatisticsModel, Log, type LogData, Markdown, MarkdownFileBase, MarkdownFolderBase, type MarkdownName, MethodContextService, type MetricStats, Notification, NotificationBacktest, type NotificationData, NotificationLive, type NotificationModel, Partial$1 as Partial, type PartialData, type PartialEvent, type PartialLossAvailableNotification, type PartialLossCommit, type PartialLossCommitNotification, type PartialLossContract, type PartialProfitAvailableNotification, type PartialProfitCommit, type PartialProfitCommitNotification, type PartialProfitContract, type PartialStatisticsModel, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatisticsModel, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistLogAdapter, PersistNotificationAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, PositionSize, type ProgressBacktestContract, type ProgressWalkerContract, Report, ReportBase, type ReportName, Risk, type RiskContract, type RiskData, type RiskEvent, type RiskRejectionNotification, type RiskStatisticsModel, Schedule, type ScheduleData, type SchedulePingContract, type ScheduleStatisticsModel, type ScheduledEvent, type SignalCancelledNotification, type SignalClosedNotification, type SignalData, type SignalInterval, type SignalOpenedNotification, type SignalScheduledNotification, Storage, StorageBacktest, type StorageData, StorageLive, Strategy, type StrategyActionType, type StrategyCancelReason, type StrategyCloseReason, type StrategyCommitContract, type StrategyEvent, type StrategyStatisticsModel, type TLogCtor, type TMarkdownBase, type TNotificationUtilsCtor, type TPersistBase, type TPersistBaseCtor, type TReportBase, type TStorageUtilsCtor, type TickEvent, type TrailingStopCommit, type TrailingStopCommitNotification, type TrailingTakeCommit, type TrailingTakeCommitNotification, type ValidationErrorNotification, Walker, type WalkerCompleteContract, type WalkerContract, type WalkerMetric, type SignalData$1 as WalkerSignalData, type WalkerStatisticsModel, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialProfit, commitTrailingStop, commitTrailingTake, dumpMessages, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getExchangeSchema, getFrameSchema, getMode, getNextCandles, getOrderBook, getRawCandles, getRiskSchema, getSizingSchema, getStrategySchema, getSymbol, getWalkerSchema, hasTradeContext, backtest as lib, listExchangeSchema, listFrameSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, roundTicks, set, setColumns, setConfig, setLogger, stopStrategy, validate, waitForCandle, warmCandles };