backtest-kit 1.5.33 → 1.5.34

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$3 = {
1441
+ const INTERVAL_MINUTES$4 = {
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$3[interval];
1586
+ const step = INTERVAL_MINUTES$4[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$3[interval];
1624
+ const step = INTERVAL_MINUTES$4[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$2 = {
2848
+ const INTERVAL_MINUTES$3 = {
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$2[self.params.interval];
3066
+ const intervalMinutes = INTERVAL_MINUTES$3[self.params.interval];
3067
3067
  const intervalMs = intervalMinutes * 60 * 1000;
3068
3068
  // Проверяем что прошел нужный интервал с последнего getSignal
3069
3069
  if (self._lastSignalTimestamp !== null &&
@@ -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$1 = {
4814
+ const INTERVAL_MINUTES$2 = {
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$1[interval];
4843
+ const intervalMinutes = INTERVAL_MINUTES$2[interval];
4844
4844
  if (!intervalMinutes) {
4845
4845
  throw new Error(`ClientFrame unknown interval: ${interval}`);
4846
4846
  }
@@ -18142,7 +18142,7 @@ const EXCHANGE_METHOD_NAME_GET_CANDLES = "ExchangeUtils.getCandles";
18142
18142
  const EXCHANGE_METHOD_NAME_GET_AVERAGE_PRICE = "ExchangeUtils.getAveragePrice";
18143
18143
  const EXCHANGE_METHOD_NAME_FORMAT_QUANTITY = "ExchangeUtils.formatQuantity";
18144
18144
  const EXCHANGE_METHOD_NAME_FORMAT_PRICE = "ExchangeUtils.formatPrice";
18145
- const INTERVAL_MINUTES = {
18145
+ const INTERVAL_MINUTES$1 = {
18146
18146
  "1m": 1,
18147
18147
  "3m": 3,
18148
18148
  "5m": 5,
@@ -18203,7 +18203,7 @@ class ExchangeInstance {
18203
18203
  interval,
18204
18204
  limit,
18205
18205
  });
18206
- const step = INTERVAL_MINUTES[interval];
18206
+ const step = INTERVAL_MINUTES$1[interval];
18207
18207
  const adjust = step * limit - step;
18208
18208
  if (!adjust) {
18209
18209
  throw new Error(`ExchangeInstance unknown time adjust for interval=${interval}`);
@@ -18426,7 +18426,175 @@ class ExchangeUtils {
18426
18426
  */
18427
18427
  const Exchange = new ExchangeUtils();
18428
18428
 
18429
+ const CACHE_METHOD_NAME_RUN = "CacheInstance.run";
18430
+ const CACHE_METHOD_NAME_FN = "CacheUtils.fn";
18431
+ const INTERVAL_MINUTES = {
18432
+ "1m": 1,
18433
+ "3m": 3,
18434
+ "5m": 5,
18435
+ "15m": 15,
18436
+ "30m": 30,
18437
+ "1h": 60,
18438
+ "2h": 120,
18439
+ "4h": 240,
18440
+ "6h": 360,
18441
+ "8h": 480,
18442
+ };
18443
+ const createKey = (strategyName, exchangeName, backtest) => `${strategyName}:${exchangeName}:${backtest ? "backtest" : "live"}`;
18444
+ /**
18445
+ * Instance class for caching function results with timeframe-based invalidation.
18446
+ *
18447
+ * Provides automatic cache invalidation based on candle intervals.
18448
+ * Each instance maintains its own cache map keyed by strategy, exchange, and mode.
18449
+ * Cache is invalidated when the current time moves to a different interval.
18450
+ *
18451
+ * @template T - Function type to cache
18452
+ *
18453
+ * @example
18454
+ * ```typescript
18455
+ * const instance = new CacheInstance(myExpensiveFunction, "1h");
18456
+ * const result = instance.run(arg1, arg2); // Computed
18457
+ * const result2 = instance.run(arg1, arg2); // Cached (within same hour)
18458
+ * // After 1 hour passes
18459
+ * const result3 = instance.run(arg1, arg2); // Recomputed
18460
+ * ```
18461
+ */
18462
+ class CacheInstance {
18463
+ /**
18464
+ * Creates a new CacheInstance for a specific function and interval.
18465
+ *
18466
+ * @param fn - Function to cache
18467
+ * @param interval - Candle interval for cache invalidation (e.g., "1m", "1h")
18468
+ */
18469
+ constructor(fn, interval) {
18470
+ this.fn = fn;
18471
+ this.interval = interval;
18472
+ /** Cache map storing results per strategy/exchange/mode combination */
18473
+ this._cacheMap = new Map();
18474
+ /**
18475
+ * Execute function with caching based on timeframe intervals.
18476
+ *
18477
+ * Caches function results and invalidates when execution time moves to a different
18478
+ * interval boundary. Uses execution context (strategy, exchange, backtest mode) and
18479
+ * method context for cache key generation.
18480
+ *
18481
+ * @param args - Arguments to pass to the cached function
18482
+ * @returns Cached result containing value and timestamp
18483
+ * @throws Error if interval is unknown or required context is missing
18484
+ *
18485
+ * @example
18486
+ * ```typescript
18487
+ * const instance = new CacheInstance(calculateIndicator, "15m");
18488
+ * const result = instance.run("BTCUSDT", 100);
18489
+ * console.log(result.value); // Calculated value
18490
+ * console.log(result.when); // Cache timestamp
18491
+ * ```
18492
+ */
18493
+ this.run = (...args) => {
18494
+ backtest$1.loggerService.debug(CACHE_METHOD_NAME_RUN, { args });
18495
+ const step = INTERVAL_MINUTES[this.interval];
18496
+ if (!step) {
18497
+ throw new Error(`CacheInstance unknown cache ttl interval=${this.interval}`);
18498
+ }
18499
+ if (!MethodContextService.hasContext()) {
18500
+ throw new Error("CacheInstance run requires method context");
18501
+ }
18502
+ if (!ExecutionContextService.hasContext()) {
18503
+ throw new Error("CacheInstance run requires execution context");
18504
+ }
18505
+ const key = createKey(backtest$1.methodContextService.context.strategyName, backtest$1.methodContextService.context.exchangeName, backtest$1.executionContextService.context.backtest);
18506
+ const currentWhen = backtest$1.executionContextService.context.when;
18507
+ const cached = this._cacheMap.get(key);
18508
+ if (cached) {
18509
+ const stepMs = step * 60 * 1000;
18510
+ const elapsed = currentWhen.getTime() - cached.when.getTime();
18511
+ if (elapsed < stepMs) {
18512
+ return cached;
18513
+ }
18514
+ }
18515
+ const newCache = {
18516
+ when: currentWhen,
18517
+ value: this.fn(...args),
18518
+ };
18519
+ this._cacheMap.set(key, newCache);
18520
+ return newCache;
18521
+ };
18522
+ }
18523
+ }
18524
+ /**
18525
+ * Utility class for function caching with timeframe-based invalidation.
18526
+ *
18527
+ * Provides simplified API for wrapping functions with automatic caching.
18528
+ * Exported as singleton instance for convenient usage.
18529
+ *
18530
+ * @example
18531
+ * ```typescript
18532
+ * import { Cache } from "./classes/Cache";
18533
+ *
18534
+ * const cachedFn = Cache.fn(expensiveCalculation, "1h");
18535
+ * const result = cachedFn(arg1, arg2); // Computed on first call
18536
+ * const result2 = cachedFn(arg1, arg2); // Cached (within same hour)
18537
+ * ```
18538
+ */
18539
+ class CacheUtils {
18540
+ constructor() {
18541
+ /**
18542
+ * Memoized function to get or create CacheInstance for a function.
18543
+ * Each function gets its own isolated cache instance.
18544
+ */
18545
+ this._getInstance = functoolsKit.memoize(([run]) => run, (run, interval) => new CacheInstance(run, interval));
18546
+ /**
18547
+ * Wrap a function with caching based on timeframe intervals.
18548
+ *
18549
+ * Returns a wrapped version of the function that automatically caches results
18550
+ * and invalidates based on the specified candle interval.
18551
+ *
18552
+ * @template T - Function type to cache
18553
+ * @param run - Function to wrap with caching
18554
+ * @param interval - Candle interval for cache invalidation (e.g., "1m", "1h")
18555
+ * @returns Wrapped function with automatic caching
18556
+ *
18557
+ * @example
18558
+ * ```typescript
18559
+ * const calculateIndicator = (symbol: string, period: number) => {
18560
+ * // Expensive calculation
18561
+ * return result;
18562
+ * };
18563
+ *
18564
+ * const cachedCalculate = Cache.fn(calculateIndicator, "15m");
18565
+ * const result = cachedCalculate("BTCUSDT", 14); // Computed
18566
+ * const result2 = cachedCalculate("BTCUSDT", 14); // Cached (same 15m interval)
18567
+ * ```
18568
+ */
18569
+ this.fn = (run, context) => {
18570
+ backtest$1.loggerService.debug(CACHE_METHOD_NAME_FN, {
18571
+ context,
18572
+ });
18573
+ return (...args) => {
18574
+ const instance = this._getInstance(run, context.interval);
18575
+ return instance.run(...args).value;
18576
+ };
18577
+ };
18578
+ }
18579
+ }
18580
+ /**
18581
+ * Singleton instance of CacheUtils for convenient function caching.
18582
+ *
18583
+ * @example
18584
+ * ```typescript
18585
+ * import { Cache } from "./classes/Cache";
18586
+ *
18587
+ * // Wrap expensive function with 1-hour cache
18588
+ * const cachedFn = Cache.fn(myExpensiveFunction, "1h");
18589
+ * const result = cachedFn(arg1, arg2);
18590
+ *
18591
+ * // Cache is automatically invalidated when moving to next hour interval
18592
+ * ```
18593
+ */
18594
+ const Cache = new CacheUtils();
18595
+
18429
18596
  exports.Backtest = Backtest;
18597
+ exports.Cache = Cache;
18430
18598
  exports.Constant = Constant;
18431
18599
  exports.Exchange = Exchange;
18432
18600
  exports.ExecutionContextService = ExecutionContextService;
package/build/index.mjs CHANGED
@@ -1436,7 +1436,7 @@ class LoggerService {
1436
1436
  }
1437
1437
  }
1438
1438
 
1439
- const INTERVAL_MINUTES$3 = {
1439
+ const INTERVAL_MINUTES$4 = {
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$3[interval];
1584
+ const step = INTERVAL_MINUTES$4[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$3[interval];
1622
+ const step = INTERVAL_MINUTES$4[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$2 = {
2846
+ const INTERVAL_MINUTES$3 = {
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$2[self.params.interval];
3064
+ const intervalMinutes = INTERVAL_MINUTES$3[self.params.interval];
3065
3065
  const intervalMs = intervalMinutes * 60 * 1000;
3066
3066
  // Проверяем что прошел нужный интервал с последнего getSignal
3067
3067
  if (self._lastSignalTimestamp !== null &&
@@ -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$1 = {
4812
+ const INTERVAL_MINUTES$2 = {
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$1[interval];
4841
+ const intervalMinutes = INTERVAL_MINUTES$2[interval];
4842
4842
  if (!intervalMinutes) {
4843
4843
  throw new Error(`ClientFrame unknown interval: ${interval}`);
4844
4844
  }
@@ -18140,7 +18140,7 @@ const EXCHANGE_METHOD_NAME_GET_CANDLES = "ExchangeUtils.getCandles";
18140
18140
  const EXCHANGE_METHOD_NAME_GET_AVERAGE_PRICE = "ExchangeUtils.getAveragePrice";
18141
18141
  const EXCHANGE_METHOD_NAME_FORMAT_QUANTITY = "ExchangeUtils.formatQuantity";
18142
18142
  const EXCHANGE_METHOD_NAME_FORMAT_PRICE = "ExchangeUtils.formatPrice";
18143
- const INTERVAL_MINUTES = {
18143
+ const INTERVAL_MINUTES$1 = {
18144
18144
  "1m": 1,
18145
18145
  "3m": 3,
18146
18146
  "5m": 5,
@@ -18201,7 +18201,7 @@ class ExchangeInstance {
18201
18201
  interval,
18202
18202
  limit,
18203
18203
  });
18204
- const step = INTERVAL_MINUTES[interval];
18204
+ const step = INTERVAL_MINUTES$1[interval];
18205
18205
  const adjust = step * limit - step;
18206
18206
  if (!adjust) {
18207
18207
  throw new Error(`ExchangeInstance unknown time adjust for interval=${interval}`);
@@ -18424,4 +18424,171 @@ class ExchangeUtils {
18424
18424
  */
18425
18425
  const Exchange = new ExchangeUtils();
18426
18426
 
18427
- export { Backtest, Constant, Exchange, ExecutionContextService, Heat, Live, MethodContextService, Optimizer, Partial, Performance, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, Risk, Schedule, Walker, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setColumns, setConfig, setLogger };
18427
+ const CACHE_METHOD_NAME_RUN = "CacheInstance.run";
18428
+ const CACHE_METHOD_NAME_FN = "CacheUtils.fn";
18429
+ const INTERVAL_MINUTES = {
18430
+ "1m": 1,
18431
+ "3m": 3,
18432
+ "5m": 5,
18433
+ "15m": 15,
18434
+ "30m": 30,
18435
+ "1h": 60,
18436
+ "2h": 120,
18437
+ "4h": 240,
18438
+ "6h": 360,
18439
+ "8h": 480,
18440
+ };
18441
+ const createKey = (strategyName, exchangeName, backtest) => `${strategyName}:${exchangeName}:${backtest ? "backtest" : "live"}`;
18442
+ /**
18443
+ * Instance class for caching function results with timeframe-based invalidation.
18444
+ *
18445
+ * Provides automatic cache invalidation based on candle intervals.
18446
+ * Each instance maintains its own cache map keyed by strategy, exchange, and mode.
18447
+ * Cache is invalidated when the current time moves to a different interval.
18448
+ *
18449
+ * @template T - Function type to cache
18450
+ *
18451
+ * @example
18452
+ * ```typescript
18453
+ * const instance = new CacheInstance(myExpensiveFunction, "1h");
18454
+ * const result = instance.run(arg1, arg2); // Computed
18455
+ * const result2 = instance.run(arg1, arg2); // Cached (within same hour)
18456
+ * // After 1 hour passes
18457
+ * const result3 = instance.run(arg1, arg2); // Recomputed
18458
+ * ```
18459
+ */
18460
+ class CacheInstance {
18461
+ /**
18462
+ * Creates a new CacheInstance for a specific function and interval.
18463
+ *
18464
+ * @param fn - Function to cache
18465
+ * @param interval - Candle interval for cache invalidation (e.g., "1m", "1h")
18466
+ */
18467
+ constructor(fn, interval) {
18468
+ this.fn = fn;
18469
+ this.interval = interval;
18470
+ /** Cache map storing results per strategy/exchange/mode combination */
18471
+ this._cacheMap = new Map();
18472
+ /**
18473
+ * Execute function with caching based on timeframe intervals.
18474
+ *
18475
+ * Caches function results and invalidates when execution time moves to a different
18476
+ * interval boundary. Uses execution context (strategy, exchange, backtest mode) and
18477
+ * method context for cache key generation.
18478
+ *
18479
+ * @param args - Arguments to pass to the cached function
18480
+ * @returns Cached result containing value and timestamp
18481
+ * @throws Error if interval is unknown or required context is missing
18482
+ *
18483
+ * @example
18484
+ * ```typescript
18485
+ * const instance = new CacheInstance(calculateIndicator, "15m");
18486
+ * const result = instance.run("BTCUSDT", 100);
18487
+ * console.log(result.value); // Calculated value
18488
+ * console.log(result.when); // Cache timestamp
18489
+ * ```
18490
+ */
18491
+ this.run = (...args) => {
18492
+ backtest$1.loggerService.debug(CACHE_METHOD_NAME_RUN, { args });
18493
+ const step = INTERVAL_MINUTES[this.interval];
18494
+ if (!step) {
18495
+ throw new Error(`CacheInstance unknown cache ttl interval=${this.interval}`);
18496
+ }
18497
+ if (!MethodContextService.hasContext()) {
18498
+ throw new Error("CacheInstance run requires method context");
18499
+ }
18500
+ if (!ExecutionContextService.hasContext()) {
18501
+ throw new Error("CacheInstance run requires execution context");
18502
+ }
18503
+ const key = createKey(backtest$1.methodContextService.context.strategyName, backtest$1.methodContextService.context.exchangeName, backtest$1.executionContextService.context.backtest);
18504
+ const currentWhen = backtest$1.executionContextService.context.when;
18505
+ const cached = this._cacheMap.get(key);
18506
+ if (cached) {
18507
+ const stepMs = step * 60 * 1000;
18508
+ const elapsed = currentWhen.getTime() - cached.when.getTime();
18509
+ if (elapsed < stepMs) {
18510
+ return cached;
18511
+ }
18512
+ }
18513
+ const newCache = {
18514
+ when: currentWhen,
18515
+ value: this.fn(...args),
18516
+ };
18517
+ this._cacheMap.set(key, newCache);
18518
+ return newCache;
18519
+ };
18520
+ }
18521
+ }
18522
+ /**
18523
+ * Utility class for function caching with timeframe-based invalidation.
18524
+ *
18525
+ * Provides simplified API for wrapping functions with automatic caching.
18526
+ * Exported as singleton instance for convenient usage.
18527
+ *
18528
+ * @example
18529
+ * ```typescript
18530
+ * import { Cache } from "./classes/Cache";
18531
+ *
18532
+ * const cachedFn = Cache.fn(expensiveCalculation, "1h");
18533
+ * const result = cachedFn(arg1, arg2); // Computed on first call
18534
+ * const result2 = cachedFn(arg1, arg2); // Cached (within same hour)
18535
+ * ```
18536
+ */
18537
+ class CacheUtils {
18538
+ constructor() {
18539
+ /**
18540
+ * Memoized function to get or create CacheInstance for a function.
18541
+ * Each function gets its own isolated cache instance.
18542
+ */
18543
+ this._getInstance = memoize(([run]) => run, (run, interval) => new CacheInstance(run, interval));
18544
+ /**
18545
+ * Wrap a function with caching based on timeframe intervals.
18546
+ *
18547
+ * Returns a wrapped version of the function that automatically caches results
18548
+ * and invalidates based on the specified candle interval.
18549
+ *
18550
+ * @template T - Function type to cache
18551
+ * @param run - Function to wrap with caching
18552
+ * @param interval - Candle interval for cache invalidation (e.g., "1m", "1h")
18553
+ * @returns Wrapped function with automatic caching
18554
+ *
18555
+ * @example
18556
+ * ```typescript
18557
+ * const calculateIndicator = (symbol: string, period: number) => {
18558
+ * // Expensive calculation
18559
+ * return result;
18560
+ * };
18561
+ *
18562
+ * const cachedCalculate = Cache.fn(calculateIndicator, "15m");
18563
+ * const result = cachedCalculate("BTCUSDT", 14); // Computed
18564
+ * const result2 = cachedCalculate("BTCUSDT", 14); // Cached (same 15m interval)
18565
+ * ```
18566
+ */
18567
+ this.fn = (run, context) => {
18568
+ backtest$1.loggerService.debug(CACHE_METHOD_NAME_FN, {
18569
+ context,
18570
+ });
18571
+ return (...args) => {
18572
+ const instance = this._getInstance(run, context.interval);
18573
+ return instance.run(...args).value;
18574
+ };
18575
+ };
18576
+ }
18577
+ }
18578
+ /**
18579
+ * Singleton instance of CacheUtils for convenient function caching.
18580
+ *
18581
+ * @example
18582
+ * ```typescript
18583
+ * import { Cache } from "./classes/Cache";
18584
+ *
18585
+ * // Wrap expensive function with 1-hour cache
18586
+ * const cachedFn = Cache.fn(myExpensiveFunction, "1h");
18587
+ * const result = cachedFn(arg1, arg2);
18588
+ *
18589
+ * // Cache is automatically invalidated when moving to next hour interval
18590
+ * ```
18591
+ */
18592
+ const Cache = new CacheUtils();
18593
+
18594
+ export { Backtest, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, MethodContextService, Optimizer, Partial, Performance, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, Risk, Schedule, Walker, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setColumns, setConfig, setLogger };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "1.5.33",
3
+ "version": "1.5.34",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
package/types.d.ts CHANGED
@@ -7814,6 +7814,75 @@ declare class ExchangeUtils {
7814
7814
  */
7815
7815
  declare const Exchange: ExchangeUtils;
7816
7816
 
7817
+ /**
7818
+ * Generic function type that accepts any arguments and returns any value.
7819
+ * Used as a constraint for cached functions.
7820
+ */
7821
+ type Function = (...args: any[]) => any;
7822
+ /**
7823
+ * Utility class for function caching with timeframe-based invalidation.
7824
+ *
7825
+ * Provides simplified API for wrapping functions with automatic caching.
7826
+ * Exported as singleton instance for convenient usage.
7827
+ *
7828
+ * @example
7829
+ * ```typescript
7830
+ * import { Cache } from "./classes/Cache";
7831
+ *
7832
+ * const cachedFn = Cache.fn(expensiveCalculation, "1h");
7833
+ * const result = cachedFn(arg1, arg2); // Computed on first call
7834
+ * const result2 = cachedFn(arg1, arg2); // Cached (within same hour)
7835
+ * ```
7836
+ */
7837
+ declare class CacheUtils {
7838
+ /**
7839
+ * Memoized function to get or create CacheInstance for a function.
7840
+ * Each function gets its own isolated cache instance.
7841
+ */
7842
+ private _getInstance;
7843
+ /**
7844
+ * Wrap a function with caching based on timeframe intervals.
7845
+ *
7846
+ * Returns a wrapped version of the function that automatically caches results
7847
+ * and invalidates based on the specified candle interval.
7848
+ *
7849
+ * @template T - Function type to cache
7850
+ * @param run - Function to wrap with caching
7851
+ * @param interval - Candle interval for cache invalidation (e.g., "1m", "1h")
7852
+ * @returns Wrapped function with automatic caching
7853
+ *
7854
+ * @example
7855
+ * ```typescript
7856
+ * const calculateIndicator = (symbol: string, period: number) => {
7857
+ * // Expensive calculation
7858
+ * return result;
7859
+ * };
7860
+ *
7861
+ * const cachedCalculate = Cache.fn(calculateIndicator, "15m");
7862
+ * const result = cachedCalculate("BTCUSDT", 14); // Computed
7863
+ * const result2 = cachedCalculate("BTCUSDT", 14); // Cached (same 15m interval)
7864
+ * ```
7865
+ */
7866
+ fn: <T extends Function>(run: T, context: {
7867
+ interval: CandleInterval;
7868
+ }) => Function;
7869
+ }
7870
+ /**
7871
+ * Singleton instance of CacheUtils for convenient function caching.
7872
+ *
7873
+ * @example
7874
+ * ```typescript
7875
+ * import { Cache } from "./classes/Cache";
7876
+ *
7877
+ * // Wrap expensive function with 1-hour cache
7878
+ * const cachedFn = Cache.fn(myExpensiveFunction, "1h");
7879
+ * const result = cachedFn(arg1, arg2);
7880
+ *
7881
+ * // Cache is automatically invalidated when moving to next hour interval
7882
+ * ```
7883
+ */
7884
+ declare const Cache: CacheUtils;
7885
+
7817
7886
  /**
7818
7887
  * Contract for walker stop signal events.
7819
7888
  *
@@ -10649,4 +10718,4 @@ declare const backtest: {
10649
10718
  loggerService: LoggerService;
10650
10719
  };
10651
10720
 
10652
- export { Backtest, type BacktestStatisticsModel, type CandleInterval, type ColumnConfig, type ColumnModel, Constant, type DoneContract, type EntityId, Exchange, ExecutionContextService, type FrameInterval, type GlobalConfig, Heat, type HeatmapStatisticsModel, type ICandleData, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type IOptimizerCallbacks, type IOptimizerData, type IOptimizerFetchArgs, type IOptimizerFilterArgs, type IOptimizerRange, type IOptimizerSchema, type IOptimizerSource, type IOptimizerStrategy, type IOptimizerTemplate, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, type IScheduledSignalRow, type ISignalDto, type ISignalRow, type ISizingCalculateParams, type ISizingCalculateParamsATR, type ISizingCalculateParamsFixedPercentage, type ISizingCalculateParamsKelly, type ISizingSchema, type ISizingSchemaATR, type ISizingSchemaFixedPercentage, type ISizingSchemaKelly, type IStrategyPnL, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultCancelled, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IStrategyTickResultScheduled, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, Live, type LiveStatisticsModel, type MessageModel, type MessageRole, MethodContextService, Optimizer, Partial$1 as Partial, type PartialData, type PartialLossContract, type PartialProfitContract, type PartialStatisticsModel, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatisticsModel, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, type ProgressBacktestContract, type ProgressOptimizerContract, type ProgressWalkerContract, Risk, type RiskContract, type RiskData, type RiskStatisticsModel, Schedule, type ScheduleData, type ScheduleStatisticsModel, type SignalData, type SignalInterval, type TPersistBase, type TPersistBaseCtor, Walker, type WalkerCompleteContract, type WalkerContract, type WalkerMetric, type WalkerStatisticsModel, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setColumns, setConfig, setLogger };
10721
+ export { Backtest, type BacktestStatisticsModel, Cache, type CandleInterval, type ColumnConfig, type ColumnModel, Constant, type DoneContract, type EntityId, Exchange, ExecutionContextService, type FrameInterval, type GlobalConfig, Heat, type HeatmapStatisticsModel, type ICandleData, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type IOptimizerCallbacks, type IOptimizerData, type IOptimizerFetchArgs, type IOptimizerFilterArgs, type IOptimizerRange, type IOptimizerSchema, type IOptimizerSource, type IOptimizerStrategy, type IOptimizerTemplate, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, type IScheduledSignalRow, type ISignalDto, type ISignalRow, type ISizingCalculateParams, type ISizingCalculateParamsATR, type ISizingCalculateParamsFixedPercentage, type ISizingCalculateParamsKelly, type ISizingSchema, type ISizingSchemaATR, type ISizingSchemaFixedPercentage, type ISizingSchemaKelly, type IStrategyPnL, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultCancelled, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IStrategyTickResultScheduled, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, Live, type LiveStatisticsModel, type MessageModel, type MessageRole, MethodContextService, Optimizer, Partial$1 as Partial, type PartialData, type PartialLossContract, type PartialProfitContract, type PartialStatisticsModel, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatisticsModel, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, type ProgressBacktestContract, type ProgressOptimizerContract, type ProgressWalkerContract, Risk, type RiskContract, type RiskData, type RiskStatisticsModel, Schedule, type ScheduleData, type ScheduleStatisticsModel, type SignalData, type SignalInterval, type TPersistBase, type TPersistBaseCtor, Walker, type WalkerCompleteContract, type WalkerContract, type WalkerMetric, type WalkerStatisticsModel, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setColumns, setConfig, setLogger };