backtest-kit 3.0.7 → 3.0.9

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
@@ -36250,6 +36250,7 @@ const Exchange = new ExchangeUtils();
36250
36250
  const CACHE_METHOD_NAME_FLUSH = "CacheUtils.flush";
36251
36251
  const CACHE_METHOD_NAME_CLEAR = "CacheInstance.clear";
36252
36252
  const CACHE_METHOD_NAME_RUN = "CacheInstance.run";
36253
+ const CACHE_METHOD_NAME_GC = "CacheInstance.gc";
36253
36254
  const CACHE_METHOD_NAME_FN = "CacheUtils.fn";
36254
36255
  const MS_PER_MINUTE = 60000;
36255
36256
  const INTERVAL_MINUTES = {
@@ -36438,6 +36439,38 @@ class CacheInstance {
36438
36439
  }
36439
36440
  }
36440
36441
  };
36442
+ /**
36443
+ * Garbage collect expired cache entries.
36444
+ *
36445
+ * Removes all cached entries whose interval has expired (not aligned with current time).
36446
+ * Call this periodically to free memory from stale cache entries.
36447
+ *
36448
+ * Requires active execution context to get current time.
36449
+ *
36450
+ * @returns Number of entries removed
36451
+ *
36452
+ * @example
36453
+ * ```typescript
36454
+ * const instance = new CacheInstance(calculateIndicator, "1h");
36455
+ * instance.run("BTCUSDT", 14); // Cached at 10:00
36456
+ * instance.run("ETHUSDT", 14); // Cached at 10:00
36457
+ * // Time passes to 11:00
36458
+ * const removed = instance.gc(); // Returns 2, removes both expired entries
36459
+ * ```
36460
+ */
36461
+ this.gc = () => {
36462
+ const currentWhen = bt.executionContextService.context.when;
36463
+ const currentAligned = align(currentWhen.getTime(), this.interval);
36464
+ let removed = 0;
36465
+ for (const [key, cached] of this._cacheMap.entries()) {
36466
+ const cachedAligned = align(cached.when.getTime(), this.interval);
36467
+ if (currentAligned !== cachedAligned) {
36468
+ this._cacheMap.delete(key);
36469
+ removed++;
36470
+ }
36471
+ }
36472
+ return removed;
36473
+ };
36441
36474
  }
36442
36475
  }
36443
36476
  /**
@@ -36573,8 +36606,48 @@ class CacheUtils {
36573
36606
  bt.loggerService.info(CACHE_METHOD_NAME_CLEAR, {
36574
36607
  run,
36575
36608
  });
36609
+ if (!MethodContextService.hasContext()) {
36610
+ console.warn(`${CACHE_METHOD_NAME_CLEAR} called without method context, skipping clear`);
36611
+ return;
36612
+ }
36613
+ if (!ExecutionContextService.hasContext()) {
36614
+ console.warn(`${CACHE_METHOD_NAME_CLEAR} called without execution context, skipping clear`);
36615
+ return;
36616
+ }
36576
36617
  this._getInstance.get(run).clear();
36577
36618
  };
36619
+ /**
36620
+ * Garbage collect expired cache entries for a specific function.
36621
+ *
36622
+ * Removes all cached entries whose interval has expired (not aligned with current time).
36623
+ * Call this periodically to free memory from stale cache entries.
36624
+ *
36625
+ * Requires active execution context to get current time.
36626
+ *
36627
+ * @template T - Function type
36628
+ * @param run - Function whose expired cache entries should be removed
36629
+ * @returns Number of entries removed
36630
+ *
36631
+ * @example
36632
+ * ```typescript
36633
+ * const cachedFn = Cache.fn(calculateIndicator, { interval: "1h" });
36634
+ *
36635
+ * cachedFn("BTCUSDT", 14); // Cached at 10:00
36636
+ * cachedFn("ETHUSDT", 14); // Cached at 10:00
36637
+ * // Time passes to 11:00
36638
+ * const removed = Cache.gc(calculateIndicator); // Returns 2
36639
+ * ```
36640
+ */
36641
+ this.gc = (run) => {
36642
+ bt.loggerService.info(CACHE_METHOD_NAME_GC, {
36643
+ run,
36644
+ });
36645
+ if (!ExecutionContextService.hasContext()) {
36646
+ console.warn(`${CACHE_METHOD_NAME_GC} called without execution context, skipping garbage collection`);
36647
+ return;
36648
+ }
36649
+ return this._getInstance.get(run).gc();
36650
+ };
36578
36651
  }
36579
36652
  }
36580
36653
  /**
package/build/index.mjs CHANGED
@@ -36230,6 +36230,7 @@ const Exchange = new ExchangeUtils();
36230
36230
  const CACHE_METHOD_NAME_FLUSH = "CacheUtils.flush";
36231
36231
  const CACHE_METHOD_NAME_CLEAR = "CacheInstance.clear";
36232
36232
  const CACHE_METHOD_NAME_RUN = "CacheInstance.run";
36233
+ const CACHE_METHOD_NAME_GC = "CacheInstance.gc";
36233
36234
  const CACHE_METHOD_NAME_FN = "CacheUtils.fn";
36234
36235
  const MS_PER_MINUTE = 60000;
36235
36236
  const INTERVAL_MINUTES = {
@@ -36418,6 +36419,38 @@ class CacheInstance {
36418
36419
  }
36419
36420
  }
36420
36421
  };
36422
+ /**
36423
+ * Garbage collect expired cache entries.
36424
+ *
36425
+ * Removes all cached entries whose interval has expired (not aligned with current time).
36426
+ * Call this periodically to free memory from stale cache entries.
36427
+ *
36428
+ * Requires active execution context to get current time.
36429
+ *
36430
+ * @returns Number of entries removed
36431
+ *
36432
+ * @example
36433
+ * ```typescript
36434
+ * const instance = new CacheInstance(calculateIndicator, "1h");
36435
+ * instance.run("BTCUSDT", 14); // Cached at 10:00
36436
+ * instance.run("ETHUSDT", 14); // Cached at 10:00
36437
+ * // Time passes to 11:00
36438
+ * const removed = instance.gc(); // Returns 2, removes both expired entries
36439
+ * ```
36440
+ */
36441
+ this.gc = () => {
36442
+ const currentWhen = bt.executionContextService.context.when;
36443
+ const currentAligned = align(currentWhen.getTime(), this.interval);
36444
+ let removed = 0;
36445
+ for (const [key, cached] of this._cacheMap.entries()) {
36446
+ const cachedAligned = align(cached.when.getTime(), this.interval);
36447
+ if (currentAligned !== cachedAligned) {
36448
+ this._cacheMap.delete(key);
36449
+ removed++;
36450
+ }
36451
+ }
36452
+ return removed;
36453
+ };
36421
36454
  }
36422
36455
  }
36423
36456
  /**
@@ -36553,8 +36586,48 @@ class CacheUtils {
36553
36586
  bt.loggerService.info(CACHE_METHOD_NAME_CLEAR, {
36554
36587
  run,
36555
36588
  });
36589
+ if (!MethodContextService.hasContext()) {
36590
+ console.warn(`${CACHE_METHOD_NAME_CLEAR} called without method context, skipping clear`);
36591
+ return;
36592
+ }
36593
+ if (!ExecutionContextService.hasContext()) {
36594
+ console.warn(`${CACHE_METHOD_NAME_CLEAR} called without execution context, skipping clear`);
36595
+ return;
36596
+ }
36556
36597
  this._getInstance.get(run).clear();
36557
36598
  };
36599
+ /**
36600
+ * Garbage collect expired cache entries for a specific function.
36601
+ *
36602
+ * Removes all cached entries whose interval has expired (not aligned with current time).
36603
+ * Call this periodically to free memory from stale cache entries.
36604
+ *
36605
+ * Requires active execution context to get current time.
36606
+ *
36607
+ * @template T - Function type
36608
+ * @param run - Function whose expired cache entries should be removed
36609
+ * @returns Number of entries removed
36610
+ *
36611
+ * @example
36612
+ * ```typescript
36613
+ * const cachedFn = Cache.fn(calculateIndicator, { interval: "1h" });
36614
+ *
36615
+ * cachedFn("BTCUSDT", 14); // Cached at 10:00
36616
+ * cachedFn("ETHUSDT", 14); // Cached at 10:00
36617
+ * // Time passes to 11:00
36618
+ * const removed = Cache.gc(calculateIndicator); // Returns 2
36619
+ * ```
36620
+ */
36621
+ this.gc = (run) => {
36622
+ bt.loggerService.info(CACHE_METHOD_NAME_GC, {
36623
+ run,
36624
+ });
36625
+ if (!ExecutionContextService.hasContext()) {
36626
+ console.warn(`${CACHE_METHOD_NAME_GC} called without execution context, skipping garbage collection`);
36627
+ return;
36628
+ }
36629
+ return this._getInstance.get(run).gc();
36630
+ };
36558
36631
  }
36559
36632
  }
36560
36633
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "3.0.7",
3
+ "version": "3.0.9",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
@@ -43,7 +43,7 @@
43
43
  "build:docs": "rimraf docs && mkdir docs && node ./scripts/dts-docs.cjs ./types.d.ts ./docs",
44
44
  "docs:gpt": "npm run build && node ./tools/gpt-docs/index.mjs",
45
45
  "docs:uml": "npm run build && node ./scripts/uml.mjs",
46
- "docs:www": "rimraf docs/wwwroot && typedoc && node ./tools/typedoc-yandex-metrica/index.mjs",
46
+ "docs:www": "rimraf docs/wwwroot && node ./tools/typedoc-packages-docs/index.mjs && typedoc && node ./tools/typedoc-yandex-metrica/index.mjs",
47
47
  "repl": "dotenv -e .env -- npm run build && node -e \"import('./scripts/repl.mjs')\" --interactive"
48
48
  },
49
49
  "main": "build/index.cjs",
@@ -75,7 +75,7 @@
75
75
  },
76
76
  "dependencies": {
77
77
  "di-kit": "^1.0.18",
78
- "di-scoped": "^1.0.20",
78
+ "di-scoped": "^1.0.21",
79
79
  "functools-kit": "^1.0.95",
80
80
  "get-moment-stamp": "^1.1.1"
81
81
  },
package/types.d.ts CHANGED
@@ -13991,6 +13991,29 @@ declare class CacheUtils {
13991
13991
  * ```
13992
13992
  */
13993
13993
  clear: <T extends Function>(run: T) => void;
13994
+ /**
13995
+ * Garbage collect expired cache entries for a specific function.
13996
+ *
13997
+ * Removes all cached entries whose interval has expired (not aligned with current time).
13998
+ * Call this periodically to free memory from stale cache entries.
13999
+ *
14000
+ * Requires active execution context to get current time.
14001
+ *
14002
+ * @template T - Function type
14003
+ * @param run - Function whose expired cache entries should be removed
14004
+ * @returns Number of entries removed
14005
+ *
14006
+ * @example
14007
+ * ```typescript
14008
+ * const cachedFn = Cache.fn(calculateIndicator, { interval: "1h" });
14009
+ *
14010
+ * cachedFn("BTCUSDT", 14); // Cached at 10:00
14011
+ * cachedFn("ETHUSDT", 14); // Cached at 10:00
14012
+ * // Time passes to 11:00
14013
+ * const removed = Cache.gc(calculateIndicator); // Returns 2
14014
+ * ```
14015
+ */
14016
+ gc: <T extends Function>(run: T) => number;
13994
14017
  }
13995
14018
  /**
13996
14019
  * Singleton instance of CacheUtils for convenient function caching.