backtest-kit 1.5.30 → 1.5.32

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
@@ -1438,7 +1438,7 @@ class LoggerService {
1438
1438
  }
1439
1439
  }
1440
1440
 
1441
- const INTERVAL_MINUTES$2 = {
1441
+ const INTERVAL_MINUTES$3 = {
1442
1442
  "1m": 1,
1443
1443
  "3m": 3,
1444
1444
  "5m": 5,
@@ -1583,7 +1583,7 @@ class ClientExchange {
1583
1583
  interval,
1584
1584
  limit,
1585
1585
  });
1586
- const step = INTERVAL_MINUTES$2[interval];
1586
+ const step = INTERVAL_MINUTES$3[interval];
1587
1587
  const adjust = step * limit - step;
1588
1588
  if (!adjust) {
1589
1589
  throw new Error(`ClientExchange unknown time adjust for interval=${interval}`);
@@ -1621,7 +1621,7 @@ class ClientExchange {
1621
1621
  const since = new Date(this.params.execution.context.when.getTime());
1622
1622
  const now = Date.now();
1623
1623
  // Вычисляем конечное время запроса
1624
- const step = INTERVAL_MINUTES$2[interval];
1624
+ const step = INTERVAL_MINUTES$3[interval];
1625
1625
  const endTime = since.getTime() + limit * step * 60 * 1000;
1626
1626
  // Проверяем что запрошенный период не заходит за Date.now()
1627
1627
  if (endTime > now) {
@@ -2845,7 +2845,7 @@ var emitters = /*#__PURE__*/Object.freeze({
2845
2845
  walkerStopSubject: walkerStopSubject
2846
2846
  });
2847
2847
 
2848
- const INTERVAL_MINUTES$1 = {
2848
+ const INTERVAL_MINUTES$2 = {
2849
2849
  "1m": 1,
2850
2850
  "3m": 3,
2851
2851
  "5m": 5,
@@ -3063,7 +3063,7 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
3063
3063
  }
3064
3064
  const currentTime = self.params.execution.context.when.getTime();
3065
3065
  {
3066
- const intervalMinutes = INTERVAL_MINUTES$1[self.params.interval];
3066
+ const intervalMinutes = INTERVAL_MINUTES$2[self.params.interval];
3067
3067
  const intervalMs = intervalMinutes * 60 * 1000;
3068
3068
  // Проверяем что прошел нужный интервал с последнего getSignal
3069
3069
  if (self._lastSignalTimestamp !== null &&
@@ -4451,7 +4451,7 @@ class RiskUtils {
4451
4451
  * }
4452
4452
  * ```
4453
4453
  */
4454
- this.getData = async (symbol, strategyName, backtest) => {
4454
+ this.getData = async (symbol, strategyName, backtest = false) => {
4455
4455
  backtest$1.loggerService.info(RISK_METHOD_NAME_GET_DATA, {
4456
4456
  symbol,
4457
4457
  strategyName,
@@ -4506,7 +4506,7 @@ class RiskUtils {
4506
4506
  * // - my-strategy: 1
4507
4507
  * ```
4508
4508
  */
4509
- this.getReport = async (symbol, strategyName, backtest, columns) => {
4509
+ this.getReport = async (symbol, strategyName, backtest = false, columns) => {
4510
4510
  backtest$1.loggerService.info(RISK_METHOD_NAME_GET_REPORT, {
4511
4511
  symbol,
4512
4512
  strategyName,
@@ -4552,7 +4552,7 @@ class RiskUtils {
4552
4552
  * }
4553
4553
  * ```
4554
4554
  */
4555
- this.dump = async (symbol, strategyName, backtest, path, columns) => {
4555
+ this.dump = async (symbol, strategyName, backtest = false, path, columns) => {
4556
4556
  backtest$1.loggerService.info(RISK_METHOD_NAME_DUMP, {
4557
4557
  symbol,
4558
4558
  strategyName,
@@ -4811,7 +4811,7 @@ class StrategyConnectionService {
4811
4811
  * Maps FrameInterval to minutes for timestamp calculation.
4812
4812
  * Used to generate timeframe arrays with proper spacing.
4813
4813
  */
4814
- const INTERVAL_MINUTES = {
4814
+ const INTERVAL_MINUTES$1 = {
4815
4815
  "1m": 1,
4816
4816
  "3m": 3,
4817
4817
  "5m": 5,
@@ -4840,7 +4840,7 @@ const GET_TIMEFRAME_FN = async (symbol, self) => {
4840
4840
  symbol,
4841
4841
  });
4842
4842
  const { interval, startDate, endDate } = self.params;
4843
- const intervalMinutes = INTERVAL_MINUTES[interval];
4843
+ const intervalMinutes = INTERVAL_MINUTES$1[interval];
4844
4844
  if (!intervalMinutes) {
4845
4845
  throw new Error(`ClientFrame unknown interval: ${interval}`);
4846
4846
  }
@@ -16692,7 +16692,7 @@ class ScheduleUtils {
16692
16692
  * console.log(stats.cancellationRate, stats.avgWaitTime);
16693
16693
  * ```
16694
16694
  */
16695
- this.getData = async (symbol, strategyName, backtest) => {
16695
+ this.getData = async (symbol, strategyName, backtest = false) => {
16696
16696
  backtest$1.loggerService.info(SCHEDULE_METHOD_NAME_GET_DATA, {
16697
16697
  symbol,
16698
16698
  strategyName,
@@ -16720,7 +16720,7 @@ class ScheduleUtils {
16720
16720
  * console.log(markdown);
16721
16721
  * ```
16722
16722
  */
16723
- this.getReport = async (symbol, strategyName, backtest, columns) => {
16723
+ this.getReport = async (symbol, strategyName, backtest = false, columns) => {
16724
16724
  backtest$1.loggerService.info(SCHEDULE_METHOD_NAME_GET_REPORT, {
16725
16725
  symbol,
16726
16726
  strategyName,
@@ -16751,7 +16751,7 @@ class ScheduleUtils {
16751
16751
  * await Schedule.dump("BTCUSDT", "my-strategy", "./custom/path");
16752
16752
  * ```
16753
16753
  */
16754
- this.dump = async (symbol, strategyName, backtest, path, columns) => {
16754
+ this.dump = async (symbol, strategyName, backtest = false, path, columns) => {
16755
16755
  backtest$1.loggerService.info(SCHEDULE_METHOD_NAME_DUMP, {
16756
16756
  symbol,
16757
16757
  strategyName,
@@ -16845,7 +16845,7 @@ class Performance {
16845
16845
  * }
16846
16846
  * ```
16847
16847
  */
16848
- static async getData(symbol, strategyName, backtest) {
16848
+ static async getData(symbol, strategyName, backtest = false) {
16849
16849
  backtest$1.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_DATA);
16850
16850
  {
16851
16851
  const { riskName, riskList } = backtest$1.strategySchemaService.get(strategyName);
@@ -16877,7 +16877,7 @@ class Performance {
16877
16877
  * await fs.writeFile("performance-report.md", markdown);
16878
16878
  * ```
16879
16879
  */
16880
- static async getReport(symbol, strategyName, backtest, columns) {
16880
+ static async getReport(symbol, strategyName, backtest = false, columns) {
16881
16881
  backtest$1.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_REPORT);
16882
16882
  {
16883
16883
  const { riskName, riskList } = backtest$1.strategySchemaService.get(strategyName);
@@ -16906,7 +16906,7 @@ class Performance {
16906
16906
  * await Performance.dump("BTCUSDT", "my-strategy", "./reports/perf");
16907
16907
  * ```
16908
16908
  */
16909
- static async dump(symbol, strategyName, backtest, path = "./dump/performance", columns) {
16909
+ static async dump(symbol, strategyName, backtest = false, path = "./dump/performance", columns) {
16910
16910
  backtest$1.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_DUMP);
16911
16911
  {
16912
16912
  const { riskName, riskList } = backtest$1.strategySchemaService.get(strategyName);
@@ -17544,7 +17544,7 @@ class HeatUtils {
17544
17544
  * });
17545
17545
  * ```
17546
17546
  */
17547
- this.getData = async (strategyName, backtest) => {
17547
+ this.getData = async (strategyName, backtest = false) => {
17548
17548
  backtest$1.loggerService.info(HEAT_METHOD_NAME_GET_DATA, { strategyName });
17549
17549
  backtest$1.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_DATA);
17550
17550
  {
@@ -17580,7 +17580,7 @@ class HeatUtils {
17580
17580
  * // ...
17581
17581
  * ```
17582
17582
  */
17583
- this.getReport = async (strategyName, backtest, columns) => {
17583
+ this.getReport = async (strategyName, backtest = false, columns) => {
17584
17584
  backtest$1.loggerService.info(HEAT_METHOD_NAME_GET_REPORT, { strategyName });
17585
17585
  backtest$1.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_REPORT);
17586
17586
  {
@@ -17609,7 +17609,7 @@ class HeatUtils {
17609
17609
  * await Heat.dump("my-strategy", "./reports");
17610
17610
  * ```
17611
17611
  */
17612
- this.dump = async (strategyName, backtest, path, columns) => {
17612
+ this.dump = async (strategyName, backtest = false, path, columns) => {
17613
17613
  backtest$1.loggerService.info(HEAT_METHOD_NAME_DUMP, { strategyName, path });
17614
17614
  backtest$1.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_DUMP);
17615
17615
  {
@@ -17933,7 +17933,7 @@ class PartialUtils {
17933
17933
  * }
17934
17934
  * ```
17935
17935
  */
17936
- this.getData = async (symbol, strategyName, backtest) => {
17936
+ this.getData = async (symbol, strategyName, backtest = false) => {
17937
17937
  backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol, strategyName });
17938
17938
  backtest$1.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_DATA);
17939
17939
  {
@@ -17982,7 +17982,7 @@ class PartialUtils {
17982
17982
  * // **Loss events:** 1
17983
17983
  * ```
17984
17984
  */
17985
- this.getReport = async (symbol, strategyName, backtest, columns) => {
17985
+ this.getReport = async (symbol, strategyName, backtest = false, columns) => {
17986
17986
  backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol, strategyName });
17987
17987
  backtest$1.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_REPORT);
17988
17988
  {
@@ -18024,7 +18024,7 @@ class PartialUtils {
18024
18024
  * }
18025
18025
  * ```
18026
18026
  */
18027
- this.dump = async (symbol, strategyName, backtest, path, columns) => {
18027
+ this.dump = async (symbol, strategyName, backtest = false, path, columns) => {
18028
18028
  backtest$1.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, strategyName, path });
18029
18029
  backtest$1.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_DUMP);
18030
18030
  {
@@ -18134,8 +18134,21 @@ class ConstantUtils {
18134
18134
  const Constant = new ConstantUtils();
18135
18135
 
18136
18136
  const EXCHANGE_METHOD_NAME_GET_CANDLES = "ExchangeUtils.getCandles";
18137
+ const EXCHANGE_METHOD_NAME_GET_AVERAGE_PRICE = "ExchangeUtils.getAveragePrice";
18137
18138
  const EXCHANGE_METHOD_NAME_FORMAT_QUANTITY = "ExchangeUtils.formatQuantity";
18138
18139
  const EXCHANGE_METHOD_NAME_FORMAT_PRICE = "ExchangeUtils.formatPrice";
18140
+ const INTERVAL_MINUTES = {
18141
+ "1m": 1,
18142
+ "3m": 3,
18143
+ "5m": 5,
18144
+ "15m": 15,
18145
+ "30m": 30,
18146
+ "1h": 60,
18147
+ "2h": 120,
18148
+ "4h": 240,
18149
+ "6h": 360,
18150
+ "8h": 480,
18151
+ };
18139
18152
  /**
18140
18153
  * Instance class for exchange operations on a specific exchange.
18141
18154
  *
@@ -18147,7 +18160,8 @@ const EXCHANGE_METHOD_NAME_FORMAT_PRICE = "ExchangeUtils.formatPrice";
18147
18160
  * ```typescript
18148
18161
  * const instance = new ExchangeInstance("binance");
18149
18162
  *
18150
- * const candles = await instance.getCandles("BTCUSDT", "1m", new Date(), 100);
18163
+ * const candles = await instance.getCandles("BTCUSDT", "1m", 100);
18164
+ * const vwap = await instance.getAveragePrice("BTCUSDT");
18151
18165
  * const formattedQty = await instance.formatQuantity("BTCUSDT", 0.001);
18152
18166
  * const formattedPrice = await instance.formatPrice("BTCUSDT", 50000.123);
18153
18167
  * ```
@@ -18163,27 +18177,88 @@ class ExchangeInstance {
18163
18177
  /**
18164
18178
  * Fetch candles from data source (API or database).
18165
18179
  *
18180
+ * Automatically calculates the start date based on Date.now() and the requested interval/limit.
18181
+ * Uses the same logic as ClientExchange to ensure backwards compatibility.
18182
+ *
18166
18183
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
18167
18184
  * @param interval - Candle time interval (e.g., "1m", "1h")
18168
- * @param since - Start date for candle fetching
18169
18185
  * @param limit - Maximum number of candles to fetch
18170
18186
  * @returns Promise resolving to array of OHLCV candle data
18171
18187
  *
18172
18188
  * @example
18173
18189
  * ```typescript
18174
18190
  * const instance = new ExchangeInstance("binance");
18175
- * const candles = await instance.getCandles("BTCUSDT", "1m", new Date(), 100);
18191
+ * const candles = await instance.getCandles("BTCUSDT", "1m", 100);
18176
18192
  * ```
18177
18193
  */
18178
- this.getCandles = async (symbol, interval, since, limit) => {
18194
+ this.getCandles = async (symbol, interval, limit) => {
18179
18195
  backtest$1.loggerService.info(EXCHANGE_METHOD_NAME_GET_CANDLES, {
18180
18196
  exchangeName: this.exchangeName,
18181
18197
  symbol,
18182
18198
  interval,
18183
- since,
18184
18199
  limit,
18185
18200
  });
18186
- return await this._schema.getCandles(symbol, interval, since, limit);
18201
+ const step = INTERVAL_MINUTES[interval];
18202
+ const adjust = step * limit - step;
18203
+ if (!adjust) {
18204
+ throw new Error(`ExchangeInstance unknown time adjust for interval=${interval}`);
18205
+ }
18206
+ const when = new Date(Date.now());
18207
+ const since = new Date(when.getTime() - adjust * 60 * 1000);
18208
+ const data = await this._schema.getCandles(symbol, interval, since, limit);
18209
+ // Filter candles to strictly match the requested range
18210
+ const whenTimestamp = when.getTime();
18211
+ const sinceTimestamp = since.getTime();
18212
+ const filteredData = data.filter((candle) => candle.timestamp >= sinceTimestamp && candle.timestamp <= whenTimestamp);
18213
+ if (filteredData.length < limit) {
18214
+ backtest$1.loggerService.warn(`ExchangeInstance Expected ${limit} candles, got ${filteredData.length}`);
18215
+ }
18216
+ return filteredData;
18217
+ };
18218
+ /**
18219
+ * Calculates VWAP (Volume Weighted Average Price) from last N 1m candles.
18220
+ * The number of candles is configurable via GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT.
18221
+ *
18222
+ * Formula:
18223
+ * - Typical Price = (high + low + close) / 3
18224
+ * - VWAP = sum(typical_price * volume) / sum(volume)
18225
+ *
18226
+ * If volume is zero, returns simple average of close prices.
18227
+ *
18228
+ * @param symbol - Trading pair symbol
18229
+ * @returns Promise resolving to VWAP price
18230
+ * @throws Error if no candles available
18231
+ *
18232
+ * @example
18233
+ * ```typescript
18234
+ * const instance = new ExchangeInstance("binance");
18235
+ * const vwap = await instance.getAveragePrice("BTCUSDT");
18236
+ * console.log(vwap); // 50125.43
18237
+ * ```
18238
+ */
18239
+ this.getAveragePrice = async (symbol) => {
18240
+ backtest$1.loggerService.debug(`ExchangeInstance getAveragePrice`, {
18241
+ exchangeName: this.exchangeName,
18242
+ symbol,
18243
+ });
18244
+ const candles = await this.getCandles(symbol, "1m", GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT);
18245
+ if (candles.length === 0) {
18246
+ throw new Error(`ExchangeInstance getAveragePrice: no candles data for symbol=${symbol}`);
18247
+ }
18248
+ // VWAP (Volume Weighted Average Price)
18249
+ // Используем типичную цену (typical price) = (high + low + close) / 3
18250
+ const sumPriceVolume = candles.reduce((acc, candle) => {
18251
+ const typicalPrice = (candle.high + candle.low + candle.close) / 3;
18252
+ return acc + typicalPrice * candle.volume;
18253
+ }, 0);
18254
+ const totalVolume = candles.reduce((acc, candle) => acc + candle.volume, 0);
18255
+ if (totalVolume === 0) {
18256
+ // Если объем нулевой, возвращаем простое среднее close цен
18257
+ const sum = candles.reduce((acc, candle) => acc + candle.close, 0);
18258
+ return sum / candles.length;
18259
+ }
18260
+ const vwap = sumPriceVolume / totalVolume;
18261
+ return vwap;
18187
18262
  };
18188
18263
  /**
18189
18264
  * Format quantity according to exchange precision rules.
@@ -18242,7 +18317,10 @@ class ExchangeInstance {
18242
18317
  * ```typescript
18243
18318
  * import { Exchange } from "./classes/Exchange";
18244
18319
  *
18245
- * const candles = await Exchange.getCandles("BTCUSDT", "1m", new Date(), 100, {
18320
+ * const candles = await Exchange.getCandles("BTCUSDT", "1m", 100, {
18321
+ * exchangeName: "binance"
18322
+ * });
18323
+ * const vwap = await Exchange.getAveragePrice("BTCUSDT", {
18246
18324
  * exchangeName: "binance"
18247
18325
  * });
18248
18326
  * const formatted = await Exchange.formatQuantity("BTCUSDT", 0.001, {
@@ -18260,17 +18338,31 @@ class ExchangeUtils {
18260
18338
  /**
18261
18339
  * Fetch candles from data source (API or database).
18262
18340
  *
18341
+ * Automatically calculates the start date based on Date.now() and the requested interval/limit.
18342
+ * Uses the same logic as ClientExchange to ensure backwards compatibility.
18343
+ *
18263
18344
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
18264
18345
  * @param interval - Candle time interval (e.g., "1m", "1h")
18265
- * @param since - Start date for candle fetching
18266
18346
  * @param limit - Maximum number of candles to fetch
18267
18347
  * @param context - Execution context with exchange name
18268
18348
  * @returns Promise resolving to array of OHLCV candle data
18269
18349
  */
18270
- this.getCandles = async (symbol, interval, since, limit, context) => {
18350
+ this.getCandles = async (symbol, interval, limit, context) => {
18271
18351
  backtest$1.exchangeValidationService.validate(context.exchangeName, EXCHANGE_METHOD_NAME_GET_CANDLES);
18272
18352
  const instance = this._getInstance(context.exchangeName);
18273
- return await instance.getCandles(symbol, interval, since, limit);
18353
+ return await instance.getCandles(symbol, interval, limit);
18354
+ };
18355
+ /**
18356
+ * Calculates VWAP (Volume Weighted Average Price) from last N 1m candles.
18357
+ *
18358
+ * @param symbol - Trading pair symbol
18359
+ * @param context - Execution context with exchange name
18360
+ * @returns Promise resolving to VWAP price
18361
+ */
18362
+ this.getAveragePrice = async (symbol, context) => {
18363
+ backtest$1.exchangeValidationService.validate(context.exchangeName, EXCHANGE_METHOD_NAME_GET_AVERAGE_PRICE);
18364
+ const instance = this._getInstance(context.exchangeName);
18365
+ return await instance.getAveragePrice(symbol);
18274
18366
  };
18275
18367
  /**
18276
18368
  * Format quantity according to exchange precision rules.
@@ -18308,7 +18400,10 @@ class ExchangeUtils {
18308
18400
  * import { Exchange } from "./classes/Exchange";
18309
18401
  *
18310
18402
  * // Using static-like API with context
18311
- * const candles = await Exchange.getCandles("BTCUSDT", "1m", new Date(), 100, {
18403
+ * const candles = await Exchange.getCandles("BTCUSDT", "1m", 100, {
18404
+ * exchangeName: "binance"
18405
+ * });
18406
+ * const vwap = await Exchange.getAveragePrice("BTCUSDT", {
18312
18407
  * exchangeName: "binance"
18313
18408
  * });
18314
18409
  * const qty = await Exchange.formatQuantity("BTCUSDT", 0.001, {
@@ -18320,7 +18415,8 @@ class ExchangeUtils {
18320
18415
  *
18321
18416
  * // Using instance API (no context needed, exchange set in constructor)
18322
18417
  * const binance = new ExchangeInstance("binance");
18323
- * const candles2 = await binance.getCandles("BTCUSDT", "1m", new Date(), 100);
18418
+ * const candles2 = await binance.getCandles("BTCUSDT", "1m", 100);
18419
+ * const vwap2 = await binance.getAveragePrice("BTCUSDT");
18324
18420
  * ```
18325
18421
  */
18326
18422
  const Exchange = new ExchangeUtils();
package/build/index.mjs CHANGED
@@ -1436,7 +1436,7 @@ class LoggerService {
1436
1436
  }
1437
1437
  }
1438
1438
 
1439
- const INTERVAL_MINUTES$2 = {
1439
+ const INTERVAL_MINUTES$3 = {
1440
1440
  "1m": 1,
1441
1441
  "3m": 3,
1442
1442
  "5m": 5,
@@ -1581,7 +1581,7 @@ class ClientExchange {
1581
1581
  interval,
1582
1582
  limit,
1583
1583
  });
1584
- const step = INTERVAL_MINUTES$2[interval];
1584
+ const step = INTERVAL_MINUTES$3[interval];
1585
1585
  const adjust = step * limit - step;
1586
1586
  if (!adjust) {
1587
1587
  throw new Error(`ClientExchange unknown time adjust for interval=${interval}`);
@@ -1619,7 +1619,7 @@ class ClientExchange {
1619
1619
  const since = new Date(this.params.execution.context.when.getTime());
1620
1620
  const now = Date.now();
1621
1621
  // Вычисляем конечное время запроса
1622
- const step = INTERVAL_MINUTES$2[interval];
1622
+ const step = INTERVAL_MINUTES$3[interval];
1623
1623
  const endTime = since.getTime() + limit * step * 60 * 1000;
1624
1624
  // Проверяем что запрошенный период не заходит за Date.now()
1625
1625
  if (endTime > now) {
@@ -2843,7 +2843,7 @@ var emitters = /*#__PURE__*/Object.freeze({
2843
2843
  walkerStopSubject: walkerStopSubject
2844
2844
  });
2845
2845
 
2846
- const INTERVAL_MINUTES$1 = {
2846
+ const INTERVAL_MINUTES$2 = {
2847
2847
  "1m": 1,
2848
2848
  "3m": 3,
2849
2849
  "5m": 5,
@@ -3061,7 +3061,7 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
3061
3061
  }
3062
3062
  const currentTime = self.params.execution.context.when.getTime();
3063
3063
  {
3064
- const intervalMinutes = INTERVAL_MINUTES$1[self.params.interval];
3064
+ const intervalMinutes = INTERVAL_MINUTES$2[self.params.interval];
3065
3065
  const intervalMs = intervalMinutes * 60 * 1000;
3066
3066
  // Проверяем что прошел нужный интервал с последнего getSignal
3067
3067
  if (self._lastSignalTimestamp !== null &&
@@ -4449,7 +4449,7 @@ class RiskUtils {
4449
4449
  * }
4450
4450
  * ```
4451
4451
  */
4452
- this.getData = async (symbol, strategyName, backtest) => {
4452
+ this.getData = async (symbol, strategyName, backtest = false) => {
4453
4453
  backtest$1.loggerService.info(RISK_METHOD_NAME_GET_DATA, {
4454
4454
  symbol,
4455
4455
  strategyName,
@@ -4504,7 +4504,7 @@ class RiskUtils {
4504
4504
  * // - my-strategy: 1
4505
4505
  * ```
4506
4506
  */
4507
- this.getReport = async (symbol, strategyName, backtest, columns) => {
4507
+ this.getReport = async (symbol, strategyName, backtest = false, columns) => {
4508
4508
  backtest$1.loggerService.info(RISK_METHOD_NAME_GET_REPORT, {
4509
4509
  symbol,
4510
4510
  strategyName,
@@ -4550,7 +4550,7 @@ class RiskUtils {
4550
4550
  * }
4551
4551
  * ```
4552
4552
  */
4553
- this.dump = async (symbol, strategyName, backtest, path, columns) => {
4553
+ this.dump = async (symbol, strategyName, backtest = false, path, columns) => {
4554
4554
  backtest$1.loggerService.info(RISK_METHOD_NAME_DUMP, {
4555
4555
  symbol,
4556
4556
  strategyName,
@@ -4809,7 +4809,7 @@ class StrategyConnectionService {
4809
4809
  * Maps FrameInterval to minutes for timestamp calculation.
4810
4810
  * Used to generate timeframe arrays with proper spacing.
4811
4811
  */
4812
- const INTERVAL_MINUTES = {
4812
+ const INTERVAL_MINUTES$1 = {
4813
4813
  "1m": 1,
4814
4814
  "3m": 3,
4815
4815
  "5m": 5,
@@ -4838,7 +4838,7 @@ const GET_TIMEFRAME_FN = async (symbol, self) => {
4838
4838
  symbol,
4839
4839
  });
4840
4840
  const { interval, startDate, endDate } = self.params;
4841
- const intervalMinutes = INTERVAL_MINUTES[interval];
4841
+ const intervalMinutes = INTERVAL_MINUTES$1[interval];
4842
4842
  if (!intervalMinutes) {
4843
4843
  throw new Error(`ClientFrame unknown interval: ${interval}`);
4844
4844
  }
@@ -16690,7 +16690,7 @@ class ScheduleUtils {
16690
16690
  * console.log(stats.cancellationRate, stats.avgWaitTime);
16691
16691
  * ```
16692
16692
  */
16693
- this.getData = async (symbol, strategyName, backtest) => {
16693
+ this.getData = async (symbol, strategyName, backtest = false) => {
16694
16694
  backtest$1.loggerService.info(SCHEDULE_METHOD_NAME_GET_DATA, {
16695
16695
  symbol,
16696
16696
  strategyName,
@@ -16718,7 +16718,7 @@ class ScheduleUtils {
16718
16718
  * console.log(markdown);
16719
16719
  * ```
16720
16720
  */
16721
- this.getReport = async (symbol, strategyName, backtest, columns) => {
16721
+ this.getReport = async (symbol, strategyName, backtest = false, columns) => {
16722
16722
  backtest$1.loggerService.info(SCHEDULE_METHOD_NAME_GET_REPORT, {
16723
16723
  symbol,
16724
16724
  strategyName,
@@ -16749,7 +16749,7 @@ class ScheduleUtils {
16749
16749
  * await Schedule.dump("BTCUSDT", "my-strategy", "./custom/path");
16750
16750
  * ```
16751
16751
  */
16752
- this.dump = async (symbol, strategyName, backtest, path, columns) => {
16752
+ this.dump = async (symbol, strategyName, backtest = false, path, columns) => {
16753
16753
  backtest$1.loggerService.info(SCHEDULE_METHOD_NAME_DUMP, {
16754
16754
  symbol,
16755
16755
  strategyName,
@@ -16843,7 +16843,7 @@ class Performance {
16843
16843
  * }
16844
16844
  * ```
16845
16845
  */
16846
- static async getData(symbol, strategyName, backtest) {
16846
+ static async getData(symbol, strategyName, backtest = false) {
16847
16847
  backtest$1.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_DATA);
16848
16848
  {
16849
16849
  const { riskName, riskList } = backtest$1.strategySchemaService.get(strategyName);
@@ -16875,7 +16875,7 @@ class Performance {
16875
16875
  * await fs.writeFile("performance-report.md", markdown);
16876
16876
  * ```
16877
16877
  */
16878
- static async getReport(symbol, strategyName, backtest, columns) {
16878
+ static async getReport(symbol, strategyName, backtest = false, columns) {
16879
16879
  backtest$1.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_REPORT);
16880
16880
  {
16881
16881
  const { riskName, riskList } = backtest$1.strategySchemaService.get(strategyName);
@@ -16904,7 +16904,7 @@ class Performance {
16904
16904
  * await Performance.dump("BTCUSDT", "my-strategy", "./reports/perf");
16905
16905
  * ```
16906
16906
  */
16907
- static async dump(symbol, strategyName, backtest, path = "./dump/performance", columns) {
16907
+ static async dump(symbol, strategyName, backtest = false, path = "./dump/performance", columns) {
16908
16908
  backtest$1.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_DUMP);
16909
16909
  {
16910
16910
  const { riskName, riskList } = backtest$1.strategySchemaService.get(strategyName);
@@ -17542,7 +17542,7 @@ class HeatUtils {
17542
17542
  * });
17543
17543
  * ```
17544
17544
  */
17545
- this.getData = async (strategyName, backtest) => {
17545
+ this.getData = async (strategyName, backtest = false) => {
17546
17546
  backtest$1.loggerService.info(HEAT_METHOD_NAME_GET_DATA, { strategyName });
17547
17547
  backtest$1.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_DATA);
17548
17548
  {
@@ -17578,7 +17578,7 @@ class HeatUtils {
17578
17578
  * // ...
17579
17579
  * ```
17580
17580
  */
17581
- this.getReport = async (strategyName, backtest, columns) => {
17581
+ this.getReport = async (strategyName, backtest = false, columns) => {
17582
17582
  backtest$1.loggerService.info(HEAT_METHOD_NAME_GET_REPORT, { strategyName });
17583
17583
  backtest$1.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_REPORT);
17584
17584
  {
@@ -17607,7 +17607,7 @@ class HeatUtils {
17607
17607
  * await Heat.dump("my-strategy", "./reports");
17608
17608
  * ```
17609
17609
  */
17610
- this.dump = async (strategyName, backtest, path, columns) => {
17610
+ this.dump = async (strategyName, backtest = false, path, columns) => {
17611
17611
  backtest$1.loggerService.info(HEAT_METHOD_NAME_DUMP, { strategyName, path });
17612
17612
  backtest$1.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_DUMP);
17613
17613
  {
@@ -17931,7 +17931,7 @@ class PartialUtils {
17931
17931
  * }
17932
17932
  * ```
17933
17933
  */
17934
- this.getData = async (symbol, strategyName, backtest) => {
17934
+ this.getData = async (symbol, strategyName, backtest = false) => {
17935
17935
  backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol, strategyName });
17936
17936
  backtest$1.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_DATA);
17937
17937
  {
@@ -17980,7 +17980,7 @@ class PartialUtils {
17980
17980
  * // **Loss events:** 1
17981
17981
  * ```
17982
17982
  */
17983
- this.getReport = async (symbol, strategyName, backtest, columns) => {
17983
+ this.getReport = async (symbol, strategyName, backtest = false, columns) => {
17984
17984
  backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol, strategyName });
17985
17985
  backtest$1.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_REPORT);
17986
17986
  {
@@ -18022,7 +18022,7 @@ class PartialUtils {
18022
18022
  * }
18023
18023
  * ```
18024
18024
  */
18025
- this.dump = async (symbol, strategyName, backtest, path, columns) => {
18025
+ this.dump = async (symbol, strategyName, backtest = false, path, columns) => {
18026
18026
  backtest$1.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, strategyName, path });
18027
18027
  backtest$1.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_DUMP);
18028
18028
  {
@@ -18132,8 +18132,21 @@ class ConstantUtils {
18132
18132
  const Constant = new ConstantUtils();
18133
18133
 
18134
18134
  const EXCHANGE_METHOD_NAME_GET_CANDLES = "ExchangeUtils.getCandles";
18135
+ const EXCHANGE_METHOD_NAME_GET_AVERAGE_PRICE = "ExchangeUtils.getAveragePrice";
18135
18136
  const EXCHANGE_METHOD_NAME_FORMAT_QUANTITY = "ExchangeUtils.formatQuantity";
18136
18137
  const EXCHANGE_METHOD_NAME_FORMAT_PRICE = "ExchangeUtils.formatPrice";
18138
+ const INTERVAL_MINUTES = {
18139
+ "1m": 1,
18140
+ "3m": 3,
18141
+ "5m": 5,
18142
+ "15m": 15,
18143
+ "30m": 30,
18144
+ "1h": 60,
18145
+ "2h": 120,
18146
+ "4h": 240,
18147
+ "6h": 360,
18148
+ "8h": 480,
18149
+ };
18137
18150
  /**
18138
18151
  * Instance class for exchange operations on a specific exchange.
18139
18152
  *
@@ -18145,7 +18158,8 @@ const EXCHANGE_METHOD_NAME_FORMAT_PRICE = "ExchangeUtils.formatPrice";
18145
18158
  * ```typescript
18146
18159
  * const instance = new ExchangeInstance("binance");
18147
18160
  *
18148
- * const candles = await instance.getCandles("BTCUSDT", "1m", new Date(), 100);
18161
+ * const candles = await instance.getCandles("BTCUSDT", "1m", 100);
18162
+ * const vwap = await instance.getAveragePrice("BTCUSDT");
18149
18163
  * const formattedQty = await instance.formatQuantity("BTCUSDT", 0.001);
18150
18164
  * const formattedPrice = await instance.formatPrice("BTCUSDT", 50000.123);
18151
18165
  * ```
@@ -18161,27 +18175,88 @@ class ExchangeInstance {
18161
18175
  /**
18162
18176
  * Fetch candles from data source (API or database).
18163
18177
  *
18178
+ * Automatically calculates the start date based on Date.now() and the requested interval/limit.
18179
+ * Uses the same logic as ClientExchange to ensure backwards compatibility.
18180
+ *
18164
18181
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
18165
18182
  * @param interval - Candle time interval (e.g., "1m", "1h")
18166
- * @param since - Start date for candle fetching
18167
18183
  * @param limit - Maximum number of candles to fetch
18168
18184
  * @returns Promise resolving to array of OHLCV candle data
18169
18185
  *
18170
18186
  * @example
18171
18187
  * ```typescript
18172
18188
  * const instance = new ExchangeInstance("binance");
18173
- * const candles = await instance.getCandles("BTCUSDT", "1m", new Date(), 100);
18189
+ * const candles = await instance.getCandles("BTCUSDT", "1m", 100);
18174
18190
  * ```
18175
18191
  */
18176
- this.getCandles = async (symbol, interval, since, limit) => {
18192
+ this.getCandles = async (symbol, interval, limit) => {
18177
18193
  backtest$1.loggerService.info(EXCHANGE_METHOD_NAME_GET_CANDLES, {
18178
18194
  exchangeName: this.exchangeName,
18179
18195
  symbol,
18180
18196
  interval,
18181
- since,
18182
18197
  limit,
18183
18198
  });
18184
- return await this._schema.getCandles(symbol, interval, since, limit);
18199
+ const step = INTERVAL_MINUTES[interval];
18200
+ const adjust = step * limit - step;
18201
+ if (!adjust) {
18202
+ throw new Error(`ExchangeInstance unknown time adjust for interval=${interval}`);
18203
+ }
18204
+ const when = new Date(Date.now());
18205
+ const since = new Date(when.getTime() - adjust * 60 * 1000);
18206
+ const data = await this._schema.getCandles(symbol, interval, since, limit);
18207
+ // Filter candles to strictly match the requested range
18208
+ const whenTimestamp = when.getTime();
18209
+ const sinceTimestamp = since.getTime();
18210
+ const filteredData = data.filter((candle) => candle.timestamp >= sinceTimestamp && candle.timestamp <= whenTimestamp);
18211
+ if (filteredData.length < limit) {
18212
+ backtest$1.loggerService.warn(`ExchangeInstance Expected ${limit} candles, got ${filteredData.length}`);
18213
+ }
18214
+ return filteredData;
18215
+ };
18216
+ /**
18217
+ * Calculates VWAP (Volume Weighted Average Price) from last N 1m candles.
18218
+ * The number of candles is configurable via GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT.
18219
+ *
18220
+ * Formula:
18221
+ * - Typical Price = (high + low + close) / 3
18222
+ * - VWAP = sum(typical_price * volume) / sum(volume)
18223
+ *
18224
+ * If volume is zero, returns simple average of close prices.
18225
+ *
18226
+ * @param symbol - Trading pair symbol
18227
+ * @returns Promise resolving to VWAP price
18228
+ * @throws Error if no candles available
18229
+ *
18230
+ * @example
18231
+ * ```typescript
18232
+ * const instance = new ExchangeInstance("binance");
18233
+ * const vwap = await instance.getAveragePrice("BTCUSDT");
18234
+ * console.log(vwap); // 50125.43
18235
+ * ```
18236
+ */
18237
+ this.getAveragePrice = async (symbol) => {
18238
+ backtest$1.loggerService.debug(`ExchangeInstance getAveragePrice`, {
18239
+ exchangeName: this.exchangeName,
18240
+ symbol,
18241
+ });
18242
+ const candles = await this.getCandles(symbol, "1m", GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT);
18243
+ if (candles.length === 0) {
18244
+ throw new Error(`ExchangeInstance getAveragePrice: no candles data for symbol=${symbol}`);
18245
+ }
18246
+ // VWAP (Volume Weighted Average Price)
18247
+ // Используем типичную цену (typical price) = (high + low + close) / 3
18248
+ const sumPriceVolume = candles.reduce((acc, candle) => {
18249
+ const typicalPrice = (candle.high + candle.low + candle.close) / 3;
18250
+ return acc + typicalPrice * candle.volume;
18251
+ }, 0);
18252
+ const totalVolume = candles.reduce((acc, candle) => acc + candle.volume, 0);
18253
+ if (totalVolume === 0) {
18254
+ // Если объем нулевой, возвращаем простое среднее close цен
18255
+ const sum = candles.reduce((acc, candle) => acc + candle.close, 0);
18256
+ return sum / candles.length;
18257
+ }
18258
+ const vwap = sumPriceVolume / totalVolume;
18259
+ return vwap;
18185
18260
  };
18186
18261
  /**
18187
18262
  * Format quantity according to exchange precision rules.
@@ -18240,7 +18315,10 @@ class ExchangeInstance {
18240
18315
  * ```typescript
18241
18316
  * import { Exchange } from "./classes/Exchange";
18242
18317
  *
18243
- * const candles = await Exchange.getCandles("BTCUSDT", "1m", new Date(), 100, {
18318
+ * const candles = await Exchange.getCandles("BTCUSDT", "1m", 100, {
18319
+ * exchangeName: "binance"
18320
+ * });
18321
+ * const vwap = await Exchange.getAveragePrice("BTCUSDT", {
18244
18322
  * exchangeName: "binance"
18245
18323
  * });
18246
18324
  * const formatted = await Exchange.formatQuantity("BTCUSDT", 0.001, {
@@ -18258,17 +18336,31 @@ class ExchangeUtils {
18258
18336
  /**
18259
18337
  * Fetch candles from data source (API or database).
18260
18338
  *
18339
+ * Automatically calculates the start date based on Date.now() and the requested interval/limit.
18340
+ * Uses the same logic as ClientExchange to ensure backwards compatibility.
18341
+ *
18261
18342
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
18262
18343
  * @param interval - Candle time interval (e.g., "1m", "1h")
18263
- * @param since - Start date for candle fetching
18264
18344
  * @param limit - Maximum number of candles to fetch
18265
18345
  * @param context - Execution context with exchange name
18266
18346
  * @returns Promise resolving to array of OHLCV candle data
18267
18347
  */
18268
- this.getCandles = async (symbol, interval, since, limit, context) => {
18348
+ this.getCandles = async (symbol, interval, limit, context) => {
18269
18349
  backtest$1.exchangeValidationService.validate(context.exchangeName, EXCHANGE_METHOD_NAME_GET_CANDLES);
18270
18350
  const instance = this._getInstance(context.exchangeName);
18271
- return await instance.getCandles(symbol, interval, since, limit);
18351
+ return await instance.getCandles(symbol, interval, limit);
18352
+ };
18353
+ /**
18354
+ * Calculates VWAP (Volume Weighted Average Price) from last N 1m candles.
18355
+ *
18356
+ * @param symbol - Trading pair symbol
18357
+ * @param context - Execution context with exchange name
18358
+ * @returns Promise resolving to VWAP price
18359
+ */
18360
+ this.getAveragePrice = async (symbol, context) => {
18361
+ backtest$1.exchangeValidationService.validate(context.exchangeName, EXCHANGE_METHOD_NAME_GET_AVERAGE_PRICE);
18362
+ const instance = this._getInstance(context.exchangeName);
18363
+ return await instance.getAveragePrice(symbol);
18272
18364
  };
18273
18365
  /**
18274
18366
  * Format quantity according to exchange precision rules.
@@ -18306,7 +18398,10 @@ class ExchangeUtils {
18306
18398
  * import { Exchange } from "./classes/Exchange";
18307
18399
  *
18308
18400
  * // Using static-like API with context
18309
- * const candles = await Exchange.getCandles("BTCUSDT", "1m", new Date(), 100, {
18401
+ * const candles = await Exchange.getCandles("BTCUSDT", "1m", 100, {
18402
+ * exchangeName: "binance"
18403
+ * });
18404
+ * const vwap = await Exchange.getAveragePrice("BTCUSDT", {
18310
18405
  * exchangeName: "binance"
18311
18406
  * });
18312
18407
  * const qty = await Exchange.formatQuantity("BTCUSDT", 0.001, {
@@ -18318,7 +18413,8 @@ class ExchangeUtils {
18318
18413
  *
18319
18414
  * // Using instance API (no context needed, exchange set in constructor)
18320
18415
  * const binance = new ExchangeInstance("binance");
18321
- * const candles2 = await binance.getCandles("BTCUSDT", "1m", new Date(), 100);
18416
+ * const candles2 = await binance.getCandles("BTCUSDT", "1m", 100);
18417
+ * const vwap2 = await binance.getAveragePrice("BTCUSDT");
18322
18418
  * ```
18323
18419
  */
18324
18420
  const Exchange = new ExchangeUtils();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "1.5.30",
3
+ "version": "1.5.32",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
package/types.d.ts CHANGED
@@ -5836,7 +5836,7 @@ declare class ScheduleUtils {
5836
5836
  * console.log(stats.cancellationRate, stats.avgWaitTime);
5837
5837
  * ```
5838
5838
  */
5839
- getData: (symbol: string, strategyName: StrategyName, backtest: boolean) => Promise<ScheduleStatisticsModel>;
5839
+ getData: (symbol: string, strategyName: StrategyName, backtest?: boolean) => Promise<ScheduleStatisticsModel>;
5840
5840
  /**
5841
5841
  * Generates markdown report with all scheduled events for a symbol-strategy pair.
5842
5842
  *
@@ -5851,7 +5851,7 @@ declare class ScheduleUtils {
5851
5851
  * console.log(markdown);
5852
5852
  * ```
5853
5853
  */
5854
- getReport: (symbol: string, strategyName: StrategyName, backtest: boolean, columns?: Columns$4[]) => Promise<string>;
5854
+ getReport: (symbol: string, strategyName: StrategyName, backtest?: boolean, columns?: Columns$4[]) => Promise<string>;
5855
5855
  /**
5856
5856
  * Saves strategy report to disk.
5857
5857
  *
@@ -5869,7 +5869,7 @@ declare class ScheduleUtils {
5869
5869
  * await Schedule.dump("BTCUSDT", "my-strategy", "./custom/path");
5870
5870
  * ```
5871
5871
  */
5872
- dump: (symbol: string, strategyName: StrategyName, backtest: boolean, path?: string, columns?: Columns$4[]) => Promise<void>;
5872
+ dump: (symbol: string, strategyName: StrategyName, backtest?: boolean, path?: string, columns?: Columns$4[]) => Promise<void>;
5873
5873
  }
5874
5874
  /**
5875
5875
  * Singleton instance of ScheduleUtils for convenient scheduled signals reporting.
@@ -6088,7 +6088,7 @@ declare class Performance {
6088
6088
  * }
6089
6089
  * ```
6090
6090
  */
6091
- static getData(symbol: string, strategyName: string, backtest: boolean): Promise<PerformanceStatisticsModel>;
6091
+ static getData(symbol: string, strategyName: string, backtest?: boolean): Promise<PerformanceStatisticsModel>;
6092
6092
  /**
6093
6093
  * Generates markdown report with performance analysis.
6094
6094
  *
@@ -6112,7 +6112,7 @@ declare class Performance {
6112
6112
  * await fs.writeFile("performance-report.md", markdown);
6113
6113
  * ```
6114
6114
  */
6115
- static getReport(symbol: string, strategyName: string, backtest: boolean, columns?: Columns$3[]): Promise<string>;
6115
+ static getReport(symbol: string, strategyName: string, backtest?: boolean, columns?: Columns$3[]): Promise<string>;
6116
6116
  /**
6117
6117
  * Saves performance report to disk.
6118
6118
  *
@@ -6133,7 +6133,7 @@ declare class Performance {
6133
6133
  * await Performance.dump("BTCUSDT", "my-strategy", "./reports/perf");
6134
6134
  * ```
6135
6135
  */
6136
- static dump(symbol: string, strategyName: string, backtest: boolean, path?: string, columns?: Columns$3[]): Promise<void>;
6136
+ static dump(symbol: string, strategyName: string, backtest?: boolean, path?: string, columns?: Columns$3[]): Promise<void>;
6137
6137
  }
6138
6138
 
6139
6139
  /**
@@ -6737,7 +6737,7 @@ declare class HeatUtils {
6737
6737
  * });
6738
6738
  * ```
6739
6739
  */
6740
- getData: (strategyName: StrategyName, backtest: boolean) => Promise<HeatmapStatisticsModel>;
6740
+ getData: (strategyName: StrategyName, backtest?: boolean) => Promise<HeatmapStatisticsModel>;
6741
6741
  /**
6742
6742
  * Generates markdown report with portfolio heatmap table for a strategy.
6743
6743
  *
@@ -6764,7 +6764,7 @@ declare class HeatUtils {
6764
6764
  * // ...
6765
6765
  * ```
6766
6766
  */
6767
- getReport: (strategyName: StrategyName, backtest: boolean, columns?: Columns$2[]) => Promise<string>;
6767
+ getReport: (strategyName: StrategyName, backtest?: boolean, columns?: Columns$2[]) => Promise<string>;
6768
6768
  /**
6769
6769
  * Saves heatmap report to disk for a strategy.
6770
6770
  *
@@ -6784,7 +6784,7 @@ declare class HeatUtils {
6784
6784
  * await Heat.dump("my-strategy", "./reports");
6785
6785
  * ```
6786
6786
  */
6787
- dump: (strategyName: StrategyName, backtest: boolean, path?: string, columns?: Columns$2[]) => Promise<void>;
6787
+ dump: (strategyName: StrategyName, backtest?: boolean, path?: string, columns?: Columns$2[]) => Promise<void>;
6788
6788
  }
6789
6789
  /**
6790
6790
  * Singleton instance of HeatUtils for convenient heatmap operations.
@@ -7218,7 +7218,7 @@ declare class PartialUtils {
7218
7218
  * }
7219
7219
  * ```
7220
7220
  */
7221
- getData: (symbol: string, strategyName: string, backtest: boolean) => Promise<PartialStatisticsModel>;
7221
+ getData: (symbol: string, strategyName: string, backtest?: boolean) => Promise<PartialStatisticsModel>;
7222
7222
  /**
7223
7223
  * Generates markdown report with all partial profit/loss events for a symbol-strategy pair.
7224
7224
  *
@@ -7258,7 +7258,7 @@ declare class PartialUtils {
7258
7258
  * // **Loss events:** 1
7259
7259
  * ```
7260
7260
  */
7261
- getReport: (symbol: string, strategyName: string, backtest: boolean, columns?: Columns$1[]) => Promise<string>;
7261
+ getReport: (symbol: string, strategyName: string, backtest?: boolean, columns?: Columns$1[]) => Promise<string>;
7262
7262
  /**
7263
7263
  * Generates and saves markdown report to file.
7264
7264
  *
@@ -7291,7 +7291,7 @@ declare class PartialUtils {
7291
7291
  * }
7292
7292
  * ```
7293
7293
  */
7294
- dump: (symbol: string, strategyName: string, backtest: boolean, path?: string, columns?: Columns$1[]) => Promise<void>;
7294
+ dump: (symbol: string, strategyName: string, backtest?: boolean, path?: string, columns?: Columns$1[]) => Promise<void>;
7295
7295
  }
7296
7296
  /**
7297
7297
  * Global singleton instance of PartialUtils.
@@ -7617,7 +7617,7 @@ declare class RiskUtils {
7617
7617
  * }
7618
7618
  * ```
7619
7619
  */
7620
- getData: (symbol: string, strategyName: string, backtest: boolean) => Promise<RiskStatisticsModel>;
7620
+ getData: (symbol: string, strategyName: string, backtest?: boolean) => Promise<RiskStatisticsModel>;
7621
7621
  /**
7622
7622
  * Generates markdown report with all risk rejection events for a symbol-strategy pair.
7623
7623
  *
@@ -7659,7 +7659,7 @@ declare class RiskUtils {
7659
7659
  * // - my-strategy: 1
7660
7660
  * ```
7661
7661
  */
7662
- getReport: (symbol: string, strategyName: string, backtest: boolean, columns?: Columns[]) => Promise<string>;
7662
+ getReport: (symbol: string, strategyName: string, backtest?: boolean, columns?: Columns[]) => Promise<string>;
7663
7663
  /**
7664
7664
  * Generates and saves markdown report to file.
7665
7665
  *
@@ -7692,7 +7692,7 @@ declare class RiskUtils {
7692
7692
  * }
7693
7693
  * ```
7694
7694
  */
7695
- dump: (symbol: string, strategyName: string, backtest: boolean, path?: string, columns?: Columns[]) => Promise<void>;
7695
+ dump: (symbol: string, strategyName: string, backtest?: boolean, path?: string, columns?: Columns[]) => Promise<void>;
7696
7696
  }
7697
7697
  /**
7698
7698
  * Global singleton instance of RiskUtils.
@@ -7720,7 +7720,10 @@ declare const Risk: RiskUtils;
7720
7720
  * ```typescript
7721
7721
  * import { Exchange } from "./classes/Exchange";
7722
7722
  *
7723
- * const candles = await Exchange.getCandles("BTCUSDT", "1m", new Date(), 100, {
7723
+ * const candles = await Exchange.getCandles("BTCUSDT", "1m", 100, {
7724
+ * exchangeName: "binance"
7725
+ * });
7726
+ * const vwap = await Exchange.getAveragePrice("BTCUSDT", {
7724
7727
  * exchangeName: "binance"
7725
7728
  * });
7726
7729
  * const formatted = await Exchange.formatQuantity("BTCUSDT", 0.001, {
@@ -7737,16 +7740,28 @@ declare class ExchangeUtils {
7737
7740
  /**
7738
7741
  * Fetch candles from data source (API or database).
7739
7742
  *
7743
+ * Automatically calculates the start date based on Date.now() and the requested interval/limit.
7744
+ * Uses the same logic as ClientExchange to ensure backwards compatibility.
7745
+ *
7740
7746
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
7741
7747
  * @param interval - Candle time interval (e.g., "1m", "1h")
7742
- * @param since - Start date for candle fetching
7743
7748
  * @param limit - Maximum number of candles to fetch
7744
7749
  * @param context - Execution context with exchange name
7745
7750
  * @returns Promise resolving to array of OHLCV candle data
7746
7751
  */
7747
- getCandles: (symbol: string, interval: CandleInterval, since: Date, limit: number, context: {
7752
+ getCandles: (symbol: string, interval: CandleInterval, limit: number, context: {
7748
7753
  exchangeName: ExchangeName;
7749
7754
  }) => Promise<ICandleData[]>;
7755
+ /**
7756
+ * Calculates VWAP (Volume Weighted Average Price) from last N 1m candles.
7757
+ *
7758
+ * @param symbol - Trading pair symbol
7759
+ * @param context - Execution context with exchange name
7760
+ * @returns Promise resolving to VWAP price
7761
+ */
7762
+ getAveragePrice: (symbol: string, context: {
7763
+ exchangeName: ExchangeName;
7764
+ }) => Promise<number>;
7750
7765
  /**
7751
7766
  * Format quantity according to exchange precision rules.
7752
7767
  *
@@ -7778,7 +7793,10 @@ declare class ExchangeUtils {
7778
7793
  * import { Exchange } from "./classes/Exchange";
7779
7794
  *
7780
7795
  * // Using static-like API with context
7781
- * const candles = await Exchange.getCandles("BTCUSDT", "1m", new Date(), 100, {
7796
+ * const candles = await Exchange.getCandles("BTCUSDT", "1m", 100, {
7797
+ * exchangeName: "binance"
7798
+ * });
7799
+ * const vwap = await Exchange.getAveragePrice("BTCUSDT", {
7782
7800
  * exchangeName: "binance"
7783
7801
  * });
7784
7802
  * const qty = await Exchange.formatQuantity("BTCUSDT", 0.001, {
@@ -7790,7 +7808,8 @@ declare class ExchangeUtils {
7790
7808
  *
7791
7809
  * // Using instance API (no context needed, exchange set in constructor)
7792
7810
  * const binance = new ExchangeInstance("binance");
7793
- * const candles2 = await binance.getCandles("BTCUSDT", "1m", new Date(), 100);
7811
+ * const candles2 = await binance.getCandles("BTCUSDT", "1m", 100);
7812
+ * const vwap2 = await binance.getAveragePrice("BTCUSDT");
7794
7813
  * ```
7795
7814
  */
7796
7815
  declare const Exchange: ExchangeUtils;