backtest-kit 1.6.3 → 1.6.5

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # 🧿 Backtest Kit
4
4
 
5
- > A TypeScript framework for backtesting and live trading strategies on multi-asset, crypto or forex, with crash-safe persistence, signal validation, and AI optimization.
5
+ > A TypeScript framework for backtesting and live trading strategies on multi-asset, crypto, forex or [DEX (peer-to-peer marketplace)](https://en.wikipedia.org/wiki/Decentralized_finance#Decentralized_exchanges) with crash-safe persistence, signal validation, and AI optimization.
6
6
 
7
7
  ![future](./assets/prophet.png)
8
8
 
package/build/index.cjs CHANGED
@@ -3734,11 +3734,22 @@ class RiskUtils {
3734
3734
  */
3735
3735
  const Risk = new RiskUtils();
3736
3736
 
3737
+ /**
3738
+ * No-operation IRisk implementation.
3739
+ * Always allows signals and performs no actions.
3740
+ */
3737
3741
  const NOOP_RISK = {
3738
3742
  checkSignal: () => Promise.resolve(true),
3739
3743
  addSignal: () => Promise.resolve(),
3740
3744
  removeSignal: () => Promise.resolve(),
3741
3745
  };
3746
+ /**
3747
+ * Determines the appropriate IRisk instance based on provided riskName and riskList.
3748
+ * @param dto - Object containing riskName and riskList
3749
+ * @param backtest - Whether running in backtest mode
3750
+ * @param self - Reference to StrategyConnectionService instance
3751
+ * @returns Configured IRisk instance (single or merged)
3752
+ */
3742
3753
  const GET_RISK_FN = (dto, backtest, self) => {
3743
3754
  const hasRiskName = !!dto.riskName;
3744
3755
  const hasRiskList = !!dto.riskList?.length;
@@ -3760,6 +3771,15 @@ const GET_RISK_FN = (dto, backtest, self) => {
3760
3771
  ...dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName, backtest)),
3761
3772
  ]);
3762
3773
  };
3774
+ /**
3775
+ * Creates a unique key for memoizing ClientStrategy instances.
3776
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
3777
+ * @param symbol - Trading pair symbol
3778
+ * @param strategyName - Name of the strategy
3779
+ * @param backtest - Whether running in backtest mode
3780
+ * @returns Unique string key for memoization
3781
+ */
3782
+ const CREATE_KEY_FN$9 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
3763
3783
  /**
3764
3784
  * Callback function for emitting ping events to pingSubject.
3765
3785
  *
@@ -3820,7 +3840,7 @@ class StrategyConnectionService {
3820
3840
  * @param strategyName - Name of registered strategy schema
3821
3841
  * @returns Configured ClientStrategy instance
3822
3842
  */
3823
- this.getStrategy = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, (symbol, strategyName, backtest) => {
3843
+ this.getStrategy = functoolsKit.memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$9(symbol, strategyName, backtest), (symbol, strategyName, backtest) => {
3824
3844
  const { riskName = "", riskList = [], getSignal, interval, callbacks, } = this.strategySchemaService.get(strategyName);
3825
3845
  return new ClientStrategy({
3826
3846
  symbol,
@@ -3987,7 +4007,7 @@ class StrategyConnectionService {
3987
4007
  ctx,
3988
4008
  });
3989
4009
  if (ctx) {
3990
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
4010
+ const key = CREATE_KEY_FN$9(ctx.symbol, ctx.strategyName, backtest);
3991
4011
  this.getStrategy.clear(key);
3992
4012
  }
3993
4013
  else {
@@ -4590,6 +4610,14 @@ class ClientRisk {
4590
4610
  }
4591
4611
  }
4592
4612
 
4613
+ /**
4614
+ * Creates a unique key for memoizing ClientRisk instances.
4615
+ * Key format: "riskName:backtest" or "riskName:live"
4616
+ * @param riskName - Name of the risk schema
4617
+ * @param backtest - Whether running in backtest mode
4618
+ * @returns Unique string key for memoization
4619
+ */
4620
+ const CREATE_KEY_FN$8 = (riskName, backtest) => `${riskName}:${backtest ? "backtest" : "live"}`;
4593
4621
  /**
4594
4622
  * Callback function for emitting risk rejection events to riskSubject.
4595
4623
  *
@@ -4661,7 +4689,7 @@ class RiskConnectionService {
4661
4689
  * @param backtest - True if backtest mode, false if live mode
4662
4690
  * @returns Configured ClientRisk instance
4663
4691
  */
4664
- this.getRisk = functoolsKit.memoize(([riskName, backtest]) => `${riskName}:${backtest ? "backtest" : "live"}`, (riskName, backtest) => {
4692
+ this.getRisk = functoolsKit.memoize(([riskName, backtest]) => CREATE_KEY_FN$8(riskName, backtest), (riskName, backtest) => {
4665
4693
  const schema = this.riskSchemaService.get(riskName);
4666
4694
  return new ClientRisk({
4667
4695
  ...schema,
@@ -4719,15 +4747,21 @@ class RiskConnectionService {
4719
4747
  /**
4720
4748
  * Clears the cached ClientRisk instance for the given risk name.
4721
4749
  *
4722
- * @param riskName - Name of the risk schema to clear from cache
4750
+ * @param backtest - Whether running in backtest mode
4751
+ * @param ctx - Optional context with riskName (clears all if not provided)
4723
4752
  */
4724
- this.clear = async (backtest, riskName) => {
4753
+ this.clear = async (backtest, ctx) => {
4725
4754
  this.loggerService.log("riskConnectionService clear", {
4726
- riskName,
4755
+ ctx,
4727
4756
  backtest,
4728
4757
  });
4729
- const key = `${riskName}:${backtest ? "backtest" : "live"}`;
4730
- this.getRisk.clear(key);
4758
+ if (ctx) {
4759
+ const key = CREATE_KEY_FN$8(ctx.riskName, backtest);
4760
+ this.getRisk.clear(key);
4761
+ }
4762
+ else {
4763
+ this.getRisk.clear();
4764
+ }
4731
4765
  };
4732
4766
  }
4733
4767
  }
@@ -4955,9 +4989,6 @@ class StrategyCoreService {
4955
4989
  symbol,
4956
4990
  strategyName,
4957
4991
  });
4958
- if (!MethodContextService.hasContext()) {
4959
- throw new Error("strategyCoreService getPendingSignal requires a method context");
4960
- }
4961
4992
  await this.validate(symbol, strategyName);
4962
4993
  return await this.strategyConnectionService.getPendingSignal(backtest, symbol, strategyName);
4963
4994
  };
@@ -4975,9 +5006,6 @@ class StrategyCoreService {
4975
5006
  symbol,
4976
5007
  strategyName,
4977
5008
  });
4978
- if (!MethodContextService.hasContext()) {
4979
- throw new Error("strategyCoreService getScheduledSignal requires a method context");
4980
- }
4981
5009
  await this.validate(symbol, strategyName);
4982
5010
  return await this.strategyConnectionService.getScheduledSignal(backtest, symbol, strategyName);
4983
5011
  };
@@ -4997,9 +5025,6 @@ class StrategyCoreService {
4997
5025
  strategyName,
4998
5026
  backtest,
4999
5027
  });
5000
- if (!MethodContextService.hasContext()) {
5001
- throw new Error("strategyCoreService getStopped requires a method context");
5002
- }
5003
5028
  await this.validate(symbol, strategyName);
5004
5029
  return await this.strategyConnectionService.getStopped(backtest, symbol, strategyName);
5005
5030
  };
@@ -5256,19 +5281,20 @@ class RiskGlobalService {
5256
5281
  };
5257
5282
  /**
5258
5283
  * Clears risk data.
5259
- * If riskName is provided, clears data for that specific risk instance.
5260
- * If no riskName is provided, clears all risk data.
5261
- * @param riskName - Optional name of the risk instance to clear
5284
+ * If ctx is provided, clears data for that specific risk instance.
5285
+ * If no ctx is provided, clears all risk data.
5286
+ * @param backtest - Whether running in backtest mode
5287
+ * @param ctx - Optional context with riskName (clears all if not provided)
5262
5288
  */
5263
- this.clear = async (backtest, riskName) => {
5289
+ this.clear = async (backtest, ctx) => {
5264
5290
  this.loggerService.log("riskGlobalService clear", {
5265
- riskName,
5291
+ ctx,
5266
5292
  backtest,
5267
5293
  });
5268
- if (riskName) {
5269
- await this.validate(riskName);
5294
+ if (ctx) {
5295
+ await this.validate(ctx.riskName);
5270
5296
  }
5271
- return await this.riskConnectionService.clear(backtest, riskName);
5297
+ return await this.riskConnectionService.clear(backtest, ctx);
5272
5298
  };
5273
5299
  }
5274
5300
  }
@@ -7761,6 +7787,15 @@ const COLUMN_CONFIG = {
7761
7787
  */
7762
7788
  const DEFAULT_COLUMNS = Object.freeze({ ...COLUMN_CONFIG });
7763
7789
 
7790
+ /**
7791
+ * Creates a unique key for memoizing ReportStorage instances.
7792
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
7793
+ * @param symbol - Trading pair symbol
7794
+ * @param strategyName - Name of the strategy
7795
+ * @param backtest - Whether running in backtest mode
7796
+ * @returns Unique string key for memoization
7797
+ */
7798
+ const CREATE_KEY_FN$7 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
7764
7799
  /**
7765
7800
  * Checks if a value is unsafe for display (not a number, NaN, or Infinity).
7766
7801
  *
@@ -7969,7 +8004,7 @@ class BacktestMarkdownService {
7969
8004
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
7970
8005
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
7971
8006
  */
7972
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$5());
8007
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$7(symbol, strategyName, backtest), () => new ReportStorage$5());
7973
8008
  /**
7974
8009
  * Processes tick events and accumulates closed signals.
7975
8010
  * Should be called from IStrategyCallbacks.onTick.
@@ -8107,7 +8142,7 @@ class BacktestMarkdownService {
8107
8142
  ctx,
8108
8143
  });
8109
8144
  if (ctx) {
8110
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
8145
+ const key = CREATE_KEY_FN$7(ctx.symbol, ctx.strategyName, backtest);
8111
8146
  this.getStorage.clear(key);
8112
8147
  }
8113
8148
  else {
@@ -8132,6 +8167,15 @@ class BacktestMarkdownService {
8132
8167
  }
8133
8168
  }
8134
8169
 
8170
+ /**
8171
+ * Creates a unique key for memoizing ReportStorage instances.
8172
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
8173
+ * @param symbol - Trading pair symbol
8174
+ * @param strategyName - Name of the strategy
8175
+ * @param backtest - Whether running in backtest mode
8176
+ * @returns Unique string key for memoization
8177
+ */
8178
+ const CREATE_KEY_FN$6 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
8135
8179
  /**
8136
8180
  * Checks if a value is unsafe for display (not a number, NaN, or Infinity).
8137
8181
  *
@@ -8461,7 +8505,7 @@ class LiveMarkdownService {
8461
8505
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
8462
8506
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
8463
8507
  */
8464
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$4());
8508
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$6(symbol, strategyName, backtest), () => new ReportStorage$4());
8465
8509
  /**
8466
8510
  * Processes tick events and accumulates all event types.
8467
8511
  * Should be called from IStrategyCallbacks.onTick.
@@ -8609,7 +8653,7 @@ class LiveMarkdownService {
8609
8653
  ctx,
8610
8654
  });
8611
8655
  if (ctx) {
8612
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
8656
+ const key = CREATE_KEY_FN$6(ctx.symbol, ctx.strategyName, backtest);
8613
8657
  this.getStorage.clear(key);
8614
8658
  }
8615
8659
  else {
@@ -8634,6 +8678,15 @@ class LiveMarkdownService {
8634
8678
  }
8635
8679
  }
8636
8680
 
8681
+ /**
8682
+ * Creates a unique key for memoizing ReportStorage instances.
8683
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
8684
+ * @param symbol - Trading pair symbol
8685
+ * @param strategyName - Name of the strategy
8686
+ * @param backtest - Whether running in backtest mode
8687
+ * @returns Unique string key for memoization
8688
+ */
8689
+ const CREATE_KEY_FN$5 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
8637
8690
  /** Maximum number of events to store in schedule reports */
8638
8691
  const MAX_EVENTS$4 = 250;
8639
8692
  /**
@@ -8869,7 +8922,7 @@ class ScheduleMarkdownService {
8869
8922
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
8870
8923
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
8871
8924
  */
8872
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$3());
8925
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$5(symbol, strategyName, backtest), () => new ReportStorage$3());
8873
8926
  /**
8874
8927
  * Processes tick events and accumulates scheduled/opened/cancelled events.
8875
8928
  * Should be called from signalEmitter subscription.
@@ -9011,7 +9064,7 @@ class ScheduleMarkdownService {
9011
9064
  ctx,
9012
9065
  });
9013
9066
  if (ctx) {
9014
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
9067
+ const key = CREATE_KEY_FN$5(ctx.symbol, ctx.strategyName, backtest);
9015
9068
  this.getStorage.clear(key);
9016
9069
  }
9017
9070
  else {
@@ -9036,6 +9089,15 @@ class ScheduleMarkdownService {
9036
9089
  }
9037
9090
  }
9038
9091
 
9092
+ /**
9093
+ * Creates a unique key for memoizing PerformanceStorage instances.
9094
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
9095
+ * @param symbol - Trading pair symbol
9096
+ * @param strategyName - Name of the strategy
9097
+ * @param backtest - Whether running in backtest mode
9098
+ * @returns Unique string key for memoization
9099
+ */
9100
+ const CREATE_KEY_FN$4 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
9039
9101
  /**
9040
9102
  * Calculates percentile value from sorted array.
9041
9103
  */
@@ -9253,7 +9315,7 @@ class PerformanceMarkdownService {
9253
9315
  * Memoized function to get or create PerformanceStorage for a symbol-strategy-backtest triple.
9254
9316
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
9255
9317
  */
9256
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new PerformanceStorage());
9318
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$4(symbol, strategyName, backtest), () => new PerformanceStorage());
9257
9319
  /**
9258
9320
  * Processes performance events and accumulates metrics.
9259
9321
  * Should be called from performance tracking code.
@@ -9358,7 +9420,7 @@ class PerformanceMarkdownService {
9358
9420
  ctx,
9359
9421
  });
9360
9422
  if (ctx) {
9361
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
9423
+ const key = CREATE_KEY_FN$4(ctx.symbol, ctx.strategyName, backtest);
9362
9424
  this.getStorage.clear(key);
9363
9425
  }
9364
9426
  else {
@@ -9785,6 +9847,14 @@ class WalkerMarkdownService {
9785
9847
  }
9786
9848
  }
9787
9849
 
9850
+ /**
9851
+ * Creates a unique key for memoizing HeatmapStorage instances.
9852
+ * Key format: "strategyName:backtest" or "strategyName:live"
9853
+ * @param strategyName - Name of the strategy
9854
+ * @param backtest - Whether running in backtest mode
9855
+ * @returns Unique string key for memoization
9856
+ */
9857
+ const CREATE_KEY_FN$3 = (strategyName, backtest) => `${strategyName}:${backtest ? "backtest" : "live"}`;
9788
9858
  const HEATMAP_METHOD_NAME_GET_DATA = "HeatMarkdownService.getData";
9789
9859
  const HEATMAP_METHOD_NAME_GET_REPORT = "HeatMarkdownService.getReport";
9790
9860
  const HEATMAP_METHOD_NAME_DUMP = "HeatMarkdownService.dump";
@@ -10128,7 +10198,7 @@ class HeatMarkdownService {
10128
10198
  * Memoized function to get or create HeatmapStorage for a strategy and backtest mode.
10129
10199
  * Each strategy + backtest mode combination gets its own isolated heatmap storage instance.
10130
10200
  */
10131
- this.getStorage = functoolsKit.memoize(([strategyName, backtest]) => `${strategyName}:${backtest ? "backtest" : "live"}`, () => new HeatmapStorage());
10201
+ this.getStorage = functoolsKit.memoize(([strategyName, backtest]) => CREATE_KEY_FN$3(strategyName, backtest), () => new HeatmapStorage());
10132
10202
  /**
10133
10203
  * Processes tick events and accumulates closed signals.
10134
10204
  * Should be called from signal emitter subscription.
@@ -10264,7 +10334,7 @@ class HeatMarkdownService {
10264
10334
  ctx,
10265
10335
  });
10266
10336
  if (ctx) {
10267
- const key = `${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
10337
+ const key = CREATE_KEY_FN$3(ctx.strategyName, backtest);
10268
10338
  this.getStorage.clear(key);
10269
10339
  }
10270
10340
  else {
@@ -12474,6 +12544,15 @@ class ClientPartial {
12474
12544
  }
12475
12545
  }
12476
12546
 
12547
+ /**
12548
+ * Creates a unique key for memoizing ClientPartial instances.
12549
+ * Key format: "signalId:backtest" or "signalId:live"
12550
+ *
12551
+ * @param signalId - Signal ID
12552
+ * @param backtest - Whether running in backtest mode
12553
+ * @returns Unique string key for memoization
12554
+ */
12555
+ const CREATE_KEY_FN$2 = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
12477
12556
  /**
12478
12557
  * Callback function for emitting profit events to partialProfitSubject.
12479
12558
  *
@@ -12571,7 +12650,7 @@ class PartialConnectionService {
12571
12650
  * Key format: "signalId:backtest" or "signalId:live"
12572
12651
  * Value: ClientPartial instance with logger and event emitters
12573
12652
  */
12574
- this.getPartial = functoolsKit.memoize(([signalId, backtest]) => `${signalId}:${backtest ? "backtest" : "live"}`, (signalId, backtest) => {
12653
+ this.getPartial = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$2(signalId, backtest), (signalId, backtest) => {
12575
12654
  return new ClientPartial({
12576
12655
  signalId,
12577
12656
  logger: this.loggerService,
@@ -12661,12 +12740,19 @@ class PartialConnectionService {
12661
12740
  const partial = this.getPartial(data.id, backtest);
12662
12741
  await partial.waitForInit(symbol, data.strategyName);
12663
12742
  await partial.clear(symbol, data, priceClose, backtest);
12664
- const key = `${data.id}:${backtest ? "backtest" : "live"}`;
12743
+ const key = CREATE_KEY_FN$2(data.id, backtest);
12665
12744
  this.getPartial.clear(key);
12666
12745
  };
12667
12746
  }
12668
12747
  }
12669
12748
 
12749
+ /**
12750
+ * Creates a unique key for memoizing ReportStorage instances.
12751
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
12752
+ * @param param0 - Tuple of symbol, strategyName and backtest boolean
12753
+ * @returns Unique string key for memoization
12754
+ */
12755
+ const CREATE_KEY_FN$1 = ([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
12670
12756
  /** Maximum number of events to store in partial reports */
12671
12757
  const MAX_EVENTS$1 = 250;
12672
12758
  /**
@@ -12841,7 +12927,7 @@ class PartialMarkdownService {
12841
12927
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
12842
12928
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
12843
12929
  */
12844
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$1());
12930
+ this.getStorage = functoolsKit.memoize(CREATE_KEY_FN$1, () => new ReportStorage$1());
12845
12931
  /**
12846
12932
  * Processes profit events and accumulates them.
12847
12933
  * Should be called from partialProfitSubject subscription.
@@ -12988,7 +13074,7 @@ class PartialMarkdownService {
12988
13074
  ctx,
12989
13075
  });
12990
13076
  if (ctx) {
12991
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
13077
+ const key = CREATE_KEY_FN$1([ctx.symbol, ctx.strategyName, backtest]);
12992
13078
  this.getStorage.clear(key);
12993
13079
  }
12994
13080
  else {
@@ -13423,6 +13509,15 @@ class ConfigValidationService {
13423
13509
  }
13424
13510
  }
13425
13511
 
13512
+ /**
13513
+ * Creates a unique key for memoizing ReportStorage instances.
13514
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
13515
+ * @param symbol - Trading pair symbol
13516
+ * @param strategyName - Name of the strategy
13517
+ * @param backtest - Whether running in backtest mode
13518
+ * @returns Unique string key for memoization
13519
+ */
13520
+ const CREATE_KEY_FN = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
13426
13521
  /** Maximum number of events to store in risk reports */
13427
13522
  const MAX_EVENTS = 250;
13428
13523
  /**
@@ -13567,7 +13662,7 @@ class RiskMarkdownService {
13567
13662
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
13568
13663
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
13569
13664
  */
13570
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage());
13665
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN(symbol, strategyName, backtest), () => new ReportStorage());
13571
13666
  /**
13572
13667
  * Processes risk rejection events and accumulates them.
13573
13668
  * Should be called from riskSubject subscription.
@@ -13695,7 +13790,7 @@ class RiskMarkdownService {
13695
13790
  ctx,
13696
13791
  });
13697
13792
  if (ctx) {
13698
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
13793
+ const key = CREATE_KEY_FN(ctx.symbol, ctx.strategyName, backtest);
13699
13794
  this.getStorage.clear(key);
13700
13795
  }
13701
13796
  else {
@@ -16407,8 +16502,8 @@ class BacktestInstance {
16407
16502
  }
16408
16503
  {
16409
16504
  const { riskName, riskList } = backtest$1.strategySchemaService.get(context.strategyName);
16410
- riskName && backtest$1.riskGlobalService.clear(true, riskName);
16411
- riskList && riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(true, riskName));
16505
+ riskName && backtest$1.riskGlobalService.clear(true, { riskName });
16506
+ riskList && riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(true, { riskName }));
16412
16507
  }
16413
16508
  return backtest$1.backtestCommandService.run(symbol, context);
16414
16509
  };
@@ -17081,8 +17176,8 @@ class LiveInstance {
17081
17176
  }
17082
17177
  {
17083
17178
  const { riskName, riskList } = backtest$1.strategySchemaService.get(context.strategyName);
17084
- riskName && backtest$1.riskGlobalService.clear(false, riskName);
17085
- riskList && riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(false, riskName));
17179
+ riskName && backtest$1.riskGlobalService.clear(false, { riskName });
17180
+ riskList && riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(false, { riskName }));
17086
17181
  }
17087
17182
  return backtest$1.liveCommandService.run(symbol, context);
17088
17183
  };
@@ -18033,9 +18128,9 @@ class WalkerInstance {
18033
18128
  }
18034
18129
  {
18035
18130
  const { riskName, riskList } = backtest$1.strategySchemaService.get(strategyName);
18036
- riskName && backtest$1.riskGlobalService.clear(true, riskName);
18131
+ riskName && backtest$1.riskGlobalService.clear(true, { riskName });
18037
18132
  riskList &&
18038
- riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(true, riskName));
18133
+ riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(true, { riskName }));
18039
18134
  }
18040
18135
  }
18041
18136
  return backtest$1.walkerCommandService.run(symbol, {
package/build/index.mjs CHANGED
@@ -3732,11 +3732,22 @@ class RiskUtils {
3732
3732
  */
3733
3733
  const Risk = new RiskUtils();
3734
3734
 
3735
+ /**
3736
+ * No-operation IRisk implementation.
3737
+ * Always allows signals and performs no actions.
3738
+ */
3735
3739
  const NOOP_RISK = {
3736
3740
  checkSignal: () => Promise.resolve(true),
3737
3741
  addSignal: () => Promise.resolve(),
3738
3742
  removeSignal: () => Promise.resolve(),
3739
3743
  };
3744
+ /**
3745
+ * Determines the appropriate IRisk instance based on provided riskName and riskList.
3746
+ * @param dto - Object containing riskName and riskList
3747
+ * @param backtest - Whether running in backtest mode
3748
+ * @param self - Reference to StrategyConnectionService instance
3749
+ * @returns Configured IRisk instance (single or merged)
3750
+ */
3740
3751
  const GET_RISK_FN = (dto, backtest, self) => {
3741
3752
  const hasRiskName = !!dto.riskName;
3742
3753
  const hasRiskList = !!dto.riskList?.length;
@@ -3758,6 +3769,15 @@ const GET_RISK_FN = (dto, backtest, self) => {
3758
3769
  ...dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName, backtest)),
3759
3770
  ]);
3760
3771
  };
3772
+ /**
3773
+ * Creates a unique key for memoizing ClientStrategy instances.
3774
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
3775
+ * @param symbol - Trading pair symbol
3776
+ * @param strategyName - Name of the strategy
3777
+ * @param backtest - Whether running in backtest mode
3778
+ * @returns Unique string key for memoization
3779
+ */
3780
+ const CREATE_KEY_FN$9 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
3761
3781
  /**
3762
3782
  * Callback function for emitting ping events to pingSubject.
3763
3783
  *
@@ -3818,7 +3838,7 @@ class StrategyConnectionService {
3818
3838
  * @param strategyName - Name of registered strategy schema
3819
3839
  * @returns Configured ClientStrategy instance
3820
3840
  */
3821
- this.getStrategy = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, (symbol, strategyName, backtest) => {
3841
+ this.getStrategy = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$9(symbol, strategyName, backtest), (symbol, strategyName, backtest) => {
3822
3842
  const { riskName = "", riskList = [], getSignal, interval, callbacks, } = this.strategySchemaService.get(strategyName);
3823
3843
  return new ClientStrategy({
3824
3844
  symbol,
@@ -3985,7 +4005,7 @@ class StrategyConnectionService {
3985
4005
  ctx,
3986
4006
  });
3987
4007
  if (ctx) {
3988
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
4008
+ const key = CREATE_KEY_FN$9(ctx.symbol, ctx.strategyName, backtest);
3989
4009
  this.getStrategy.clear(key);
3990
4010
  }
3991
4011
  else {
@@ -4588,6 +4608,14 @@ class ClientRisk {
4588
4608
  }
4589
4609
  }
4590
4610
 
4611
+ /**
4612
+ * Creates a unique key for memoizing ClientRisk instances.
4613
+ * Key format: "riskName:backtest" or "riskName:live"
4614
+ * @param riskName - Name of the risk schema
4615
+ * @param backtest - Whether running in backtest mode
4616
+ * @returns Unique string key for memoization
4617
+ */
4618
+ const CREATE_KEY_FN$8 = (riskName, backtest) => `${riskName}:${backtest ? "backtest" : "live"}`;
4591
4619
  /**
4592
4620
  * Callback function for emitting risk rejection events to riskSubject.
4593
4621
  *
@@ -4659,7 +4687,7 @@ class RiskConnectionService {
4659
4687
  * @param backtest - True if backtest mode, false if live mode
4660
4688
  * @returns Configured ClientRisk instance
4661
4689
  */
4662
- this.getRisk = memoize(([riskName, backtest]) => `${riskName}:${backtest ? "backtest" : "live"}`, (riskName, backtest) => {
4690
+ this.getRisk = memoize(([riskName, backtest]) => CREATE_KEY_FN$8(riskName, backtest), (riskName, backtest) => {
4663
4691
  const schema = this.riskSchemaService.get(riskName);
4664
4692
  return new ClientRisk({
4665
4693
  ...schema,
@@ -4717,15 +4745,21 @@ class RiskConnectionService {
4717
4745
  /**
4718
4746
  * Clears the cached ClientRisk instance for the given risk name.
4719
4747
  *
4720
- * @param riskName - Name of the risk schema to clear from cache
4748
+ * @param backtest - Whether running in backtest mode
4749
+ * @param ctx - Optional context with riskName (clears all if not provided)
4721
4750
  */
4722
- this.clear = async (backtest, riskName) => {
4751
+ this.clear = async (backtest, ctx) => {
4723
4752
  this.loggerService.log("riskConnectionService clear", {
4724
- riskName,
4753
+ ctx,
4725
4754
  backtest,
4726
4755
  });
4727
- const key = `${riskName}:${backtest ? "backtest" : "live"}`;
4728
- this.getRisk.clear(key);
4756
+ if (ctx) {
4757
+ const key = CREATE_KEY_FN$8(ctx.riskName, backtest);
4758
+ this.getRisk.clear(key);
4759
+ }
4760
+ else {
4761
+ this.getRisk.clear();
4762
+ }
4729
4763
  };
4730
4764
  }
4731
4765
  }
@@ -4953,9 +4987,6 @@ class StrategyCoreService {
4953
4987
  symbol,
4954
4988
  strategyName,
4955
4989
  });
4956
- if (!MethodContextService.hasContext()) {
4957
- throw new Error("strategyCoreService getPendingSignal requires a method context");
4958
- }
4959
4990
  await this.validate(symbol, strategyName);
4960
4991
  return await this.strategyConnectionService.getPendingSignal(backtest, symbol, strategyName);
4961
4992
  };
@@ -4973,9 +5004,6 @@ class StrategyCoreService {
4973
5004
  symbol,
4974
5005
  strategyName,
4975
5006
  });
4976
- if (!MethodContextService.hasContext()) {
4977
- throw new Error("strategyCoreService getScheduledSignal requires a method context");
4978
- }
4979
5007
  await this.validate(symbol, strategyName);
4980
5008
  return await this.strategyConnectionService.getScheduledSignal(backtest, symbol, strategyName);
4981
5009
  };
@@ -4995,9 +5023,6 @@ class StrategyCoreService {
4995
5023
  strategyName,
4996
5024
  backtest,
4997
5025
  });
4998
- if (!MethodContextService.hasContext()) {
4999
- throw new Error("strategyCoreService getStopped requires a method context");
5000
- }
5001
5026
  await this.validate(symbol, strategyName);
5002
5027
  return await this.strategyConnectionService.getStopped(backtest, symbol, strategyName);
5003
5028
  };
@@ -5254,19 +5279,20 @@ class RiskGlobalService {
5254
5279
  };
5255
5280
  /**
5256
5281
  * Clears risk data.
5257
- * If riskName is provided, clears data for that specific risk instance.
5258
- * If no riskName is provided, clears all risk data.
5259
- * @param riskName - Optional name of the risk instance to clear
5282
+ * If ctx is provided, clears data for that specific risk instance.
5283
+ * If no ctx is provided, clears all risk data.
5284
+ * @param backtest - Whether running in backtest mode
5285
+ * @param ctx - Optional context with riskName (clears all if not provided)
5260
5286
  */
5261
- this.clear = async (backtest, riskName) => {
5287
+ this.clear = async (backtest, ctx) => {
5262
5288
  this.loggerService.log("riskGlobalService clear", {
5263
- riskName,
5289
+ ctx,
5264
5290
  backtest,
5265
5291
  });
5266
- if (riskName) {
5267
- await this.validate(riskName);
5292
+ if (ctx) {
5293
+ await this.validate(ctx.riskName);
5268
5294
  }
5269
- return await this.riskConnectionService.clear(backtest, riskName);
5295
+ return await this.riskConnectionService.clear(backtest, ctx);
5270
5296
  };
5271
5297
  }
5272
5298
  }
@@ -7759,6 +7785,15 @@ const COLUMN_CONFIG = {
7759
7785
  */
7760
7786
  const DEFAULT_COLUMNS = Object.freeze({ ...COLUMN_CONFIG });
7761
7787
 
7788
+ /**
7789
+ * Creates a unique key for memoizing ReportStorage instances.
7790
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
7791
+ * @param symbol - Trading pair symbol
7792
+ * @param strategyName - Name of the strategy
7793
+ * @param backtest - Whether running in backtest mode
7794
+ * @returns Unique string key for memoization
7795
+ */
7796
+ const CREATE_KEY_FN$7 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
7762
7797
  /**
7763
7798
  * Checks if a value is unsafe for display (not a number, NaN, or Infinity).
7764
7799
  *
@@ -7967,7 +8002,7 @@ class BacktestMarkdownService {
7967
8002
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
7968
8003
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
7969
8004
  */
7970
- this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$5());
8005
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$7(symbol, strategyName, backtest), () => new ReportStorage$5());
7971
8006
  /**
7972
8007
  * Processes tick events and accumulates closed signals.
7973
8008
  * Should be called from IStrategyCallbacks.onTick.
@@ -8105,7 +8140,7 @@ class BacktestMarkdownService {
8105
8140
  ctx,
8106
8141
  });
8107
8142
  if (ctx) {
8108
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
8143
+ const key = CREATE_KEY_FN$7(ctx.symbol, ctx.strategyName, backtest);
8109
8144
  this.getStorage.clear(key);
8110
8145
  }
8111
8146
  else {
@@ -8130,6 +8165,15 @@ class BacktestMarkdownService {
8130
8165
  }
8131
8166
  }
8132
8167
 
8168
+ /**
8169
+ * Creates a unique key for memoizing ReportStorage instances.
8170
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
8171
+ * @param symbol - Trading pair symbol
8172
+ * @param strategyName - Name of the strategy
8173
+ * @param backtest - Whether running in backtest mode
8174
+ * @returns Unique string key for memoization
8175
+ */
8176
+ const CREATE_KEY_FN$6 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
8133
8177
  /**
8134
8178
  * Checks if a value is unsafe for display (not a number, NaN, or Infinity).
8135
8179
  *
@@ -8459,7 +8503,7 @@ class LiveMarkdownService {
8459
8503
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
8460
8504
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
8461
8505
  */
8462
- this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$4());
8506
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$6(symbol, strategyName, backtest), () => new ReportStorage$4());
8463
8507
  /**
8464
8508
  * Processes tick events and accumulates all event types.
8465
8509
  * Should be called from IStrategyCallbacks.onTick.
@@ -8607,7 +8651,7 @@ class LiveMarkdownService {
8607
8651
  ctx,
8608
8652
  });
8609
8653
  if (ctx) {
8610
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
8654
+ const key = CREATE_KEY_FN$6(ctx.symbol, ctx.strategyName, backtest);
8611
8655
  this.getStorage.clear(key);
8612
8656
  }
8613
8657
  else {
@@ -8632,6 +8676,15 @@ class LiveMarkdownService {
8632
8676
  }
8633
8677
  }
8634
8678
 
8679
+ /**
8680
+ * Creates a unique key for memoizing ReportStorage instances.
8681
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
8682
+ * @param symbol - Trading pair symbol
8683
+ * @param strategyName - Name of the strategy
8684
+ * @param backtest - Whether running in backtest mode
8685
+ * @returns Unique string key for memoization
8686
+ */
8687
+ const CREATE_KEY_FN$5 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
8635
8688
  /** Maximum number of events to store in schedule reports */
8636
8689
  const MAX_EVENTS$4 = 250;
8637
8690
  /**
@@ -8867,7 +8920,7 @@ class ScheduleMarkdownService {
8867
8920
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
8868
8921
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
8869
8922
  */
8870
- this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$3());
8923
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$5(symbol, strategyName, backtest), () => new ReportStorage$3());
8871
8924
  /**
8872
8925
  * Processes tick events and accumulates scheduled/opened/cancelled events.
8873
8926
  * Should be called from signalEmitter subscription.
@@ -9009,7 +9062,7 @@ class ScheduleMarkdownService {
9009
9062
  ctx,
9010
9063
  });
9011
9064
  if (ctx) {
9012
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
9065
+ const key = CREATE_KEY_FN$5(ctx.symbol, ctx.strategyName, backtest);
9013
9066
  this.getStorage.clear(key);
9014
9067
  }
9015
9068
  else {
@@ -9034,6 +9087,15 @@ class ScheduleMarkdownService {
9034
9087
  }
9035
9088
  }
9036
9089
 
9090
+ /**
9091
+ * Creates a unique key for memoizing PerformanceStorage instances.
9092
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
9093
+ * @param symbol - Trading pair symbol
9094
+ * @param strategyName - Name of the strategy
9095
+ * @param backtest - Whether running in backtest mode
9096
+ * @returns Unique string key for memoization
9097
+ */
9098
+ const CREATE_KEY_FN$4 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
9037
9099
  /**
9038
9100
  * Calculates percentile value from sorted array.
9039
9101
  */
@@ -9251,7 +9313,7 @@ class PerformanceMarkdownService {
9251
9313
  * Memoized function to get or create PerformanceStorage for a symbol-strategy-backtest triple.
9252
9314
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
9253
9315
  */
9254
- this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new PerformanceStorage());
9316
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$4(symbol, strategyName, backtest), () => new PerformanceStorage());
9255
9317
  /**
9256
9318
  * Processes performance events and accumulates metrics.
9257
9319
  * Should be called from performance tracking code.
@@ -9356,7 +9418,7 @@ class PerformanceMarkdownService {
9356
9418
  ctx,
9357
9419
  });
9358
9420
  if (ctx) {
9359
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
9421
+ const key = CREATE_KEY_FN$4(ctx.symbol, ctx.strategyName, backtest);
9360
9422
  this.getStorage.clear(key);
9361
9423
  }
9362
9424
  else {
@@ -9783,6 +9845,14 @@ class WalkerMarkdownService {
9783
9845
  }
9784
9846
  }
9785
9847
 
9848
+ /**
9849
+ * Creates a unique key for memoizing HeatmapStorage instances.
9850
+ * Key format: "strategyName:backtest" or "strategyName:live"
9851
+ * @param strategyName - Name of the strategy
9852
+ * @param backtest - Whether running in backtest mode
9853
+ * @returns Unique string key for memoization
9854
+ */
9855
+ const CREATE_KEY_FN$3 = (strategyName, backtest) => `${strategyName}:${backtest ? "backtest" : "live"}`;
9786
9856
  const HEATMAP_METHOD_NAME_GET_DATA = "HeatMarkdownService.getData";
9787
9857
  const HEATMAP_METHOD_NAME_GET_REPORT = "HeatMarkdownService.getReport";
9788
9858
  const HEATMAP_METHOD_NAME_DUMP = "HeatMarkdownService.dump";
@@ -10126,7 +10196,7 @@ class HeatMarkdownService {
10126
10196
  * Memoized function to get or create HeatmapStorage for a strategy and backtest mode.
10127
10197
  * Each strategy + backtest mode combination gets its own isolated heatmap storage instance.
10128
10198
  */
10129
- this.getStorage = memoize(([strategyName, backtest]) => `${strategyName}:${backtest ? "backtest" : "live"}`, () => new HeatmapStorage());
10199
+ this.getStorage = memoize(([strategyName, backtest]) => CREATE_KEY_FN$3(strategyName, backtest), () => new HeatmapStorage());
10130
10200
  /**
10131
10201
  * Processes tick events and accumulates closed signals.
10132
10202
  * Should be called from signal emitter subscription.
@@ -10262,7 +10332,7 @@ class HeatMarkdownService {
10262
10332
  ctx,
10263
10333
  });
10264
10334
  if (ctx) {
10265
- const key = `${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
10335
+ const key = CREATE_KEY_FN$3(ctx.strategyName, backtest);
10266
10336
  this.getStorage.clear(key);
10267
10337
  }
10268
10338
  else {
@@ -12472,6 +12542,15 @@ class ClientPartial {
12472
12542
  }
12473
12543
  }
12474
12544
 
12545
+ /**
12546
+ * Creates a unique key for memoizing ClientPartial instances.
12547
+ * Key format: "signalId:backtest" or "signalId:live"
12548
+ *
12549
+ * @param signalId - Signal ID
12550
+ * @param backtest - Whether running in backtest mode
12551
+ * @returns Unique string key for memoization
12552
+ */
12553
+ const CREATE_KEY_FN$2 = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
12475
12554
  /**
12476
12555
  * Callback function for emitting profit events to partialProfitSubject.
12477
12556
  *
@@ -12569,7 +12648,7 @@ class PartialConnectionService {
12569
12648
  * Key format: "signalId:backtest" or "signalId:live"
12570
12649
  * Value: ClientPartial instance with logger and event emitters
12571
12650
  */
12572
- this.getPartial = memoize(([signalId, backtest]) => `${signalId}:${backtest ? "backtest" : "live"}`, (signalId, backtest) => {
12651
+ this.getPartial = memoize(([signalId, backtest]) => CREATE_KEY_FN$2(signalId, backtest), (signalId, backtest) => {
12573
12652
  return new ClientPartial({
12574
12653
  signalId,
12575
12654
  logger: this.loggerService,
@@ -12659,12 +12738,19 @@ class PartialConnectionService {
12659
12738
  const partial = this.getPartial(data.id, backtest);
12660
12739
  await partial.waitForInit(symbol, data.strategyName);
12661
12740
  await partial.clear(symbol, data, priceClose, backtest);
12662
- const key = `${data.id}:${backtest ? "backtest" : "live"}`;
12741
+ const key = CREATE_KEY_FN$2(data.id, backtest);
12663
12742
  this.getPartial.clear(key);
12664
12743
  };
12665
12744
  }
12666
12745
  }
12667
12746
 
12747
+ /**
12748
+ * Creates a unique key for memoizing ReportStorage instances.
12749
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
12750
+ * @param param0 - Tuple of symbol, strategyName and backtest boolean
12751
+ * @returns Unique string key for memoization
12752
+ */
12753
+ const CREATE_KEY_FN$1 = ([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
12668
12754
  /** Maximum number of events to store in partial reports */
12669
12755
  const MAX_EVENTS$1 = 250;
12670
12756
  /**
@@ -12839,7 +12925,7 @@ class PartialMarkdownService {
12839
12925
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
12840
12926
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
12841
12927
  */
12842
- this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$1());
12928
+ this.getStorage = memoize(CREATE_KEY_FN$1, () => new ReportStorage$1());
12843
12929
  /**
12844
12930
  * Processes profit events and accumulates them.
12845
12931
  * Should be called from partialProfitSubject subscription.
@@ -12986,7 +13072,7 @@ class PartialMarkdownService {
12986
13072
  ctx,
12987
13073
  });
12988
13074
  if (ctx) {
12989
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
13075
+ const key = CREATE_KEY_FN$1([ctx.symbol, ctx.strategyName, backtest]);
12990
13076
  this.getStorage.clear(key);
12991
13077
  }
12992
13078
  else {
@@ -13421,6 +13507,15 @@ class ConfigValidationService {
13421
13507
  }
13422
13508
  }
13423
13509
 
13510
+ /**
13511
+ * Creates a unique key for memoizing ReportStorage instances.
13512
+ * Key format: "symbol:strategyName:backtest" or "symbol:strategyName:live"
13513
+ * @param symbol - Trading pair symbol
13514
+ * @param strategyName - Name of the strategy
13515
+ * @param backtest - Whether running in backtest mode
13516
+ * @returns Unique string key for memoization
13517
+ */
13518
+ const CREATE_KEY_FN = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
13424
13519
  /** Maximum number of events to store in risk reports */
13425
13520
  const MAX_EVENTS = 250;
13426
13521
  /**
@@ -13565,7 +13660,7 @@ class RiskMarkdownService {
13565
13660
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
13566
13661
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
13567
13662
  */
13568
- this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage());
13663
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN(symbol, strategyName, backtest), () => new ReportStorage());
13569
13664
  /**
13570
13665
  * Processes risk rejection events and accumulates them.
13571
13666
  * Should be called from riskSubject subscription.
@@ -13693,7 +13788,7 @@ class RiskMarkdownService {
13693
13788
  ctx,
13694
13789
  });
13695
13790
  if (ctx) {
13696
- const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
13791
+ const key = CREATE_KEY_FN(ctx.symbol, ctx.strategyName, backtest);
13697
13792
  this.getStorage.clear(key);
13698
13793
  }
13699
13794
  else {
@@ -16405,8 +16500,8 @@ class BacktestInstance {
16405
16500
  }
16406
16501
  {
16407
16502
  const { riskName, riskList } = backtest$1.strategySchemaService.get(context.strategyName);
16408
- riskName && backtest$1.riskGlobalService.clear(true, riskName);
16409
- riskList && riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(true, riskName));
16503
+ riskName && backtest$1.riskGlobalService.clear(true, { riskName });
16504
+ riskList && riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(true, { riskName }));
16410
16505
  }
16411
16506
  return backtest$1.backtestCommandService.run(symbol, context);
16412
16507
  };
@@ -17079,8 +17174,8 @@ class LiveInstance {
17079
17174
  }
17080
17175
  {
17081
17176
  const { riskName, riskList } = backtest$1.strategySchemaService.get(context.strategyName);
17082
- riskName && backtest$1.riskGlobalService.clear(false, riskName);
17083
- riskList && riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(false, riskName));
17177
+ riskName && backtest$1.riskGlobalService.clear(false, { riskName });
17178
+ riskList && riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(false, { riskName }));
17084
17179
  }
17085
17180
  return backtest$1.liveCommandService.run(symbol, context);
17086
17181
  };
@@ -18031,9 +18126,9 @@ class WalkerInstance {
18031
18126
  }
18032
18127
  {
18033
18128
  const { riskName, riskList } = backtest$1.strategySchemaService.get(strategyName);
18034
- riskName && backtest$1.riskGlobalService.clear(true, riskName);
18129
+ riskName && backtest$1.riskGlobalService.clear(true, { riskName });
18035
18130
  riskList &&
18036
- riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(true, riskName));
18131
+ riskList.forEach((riskName) => backtest$1.riskGlobalService.clear(true, { riskName }));
18037
18132
  }
18038
18133
  }
18039
18134
  return backtest$1.walkerCommandService.run(symbol, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
package/types.d.ts CHANGED
@@ -8937,7 +8937,7 @@ declare class RiskConnectionService {
8937
8937
  * @param backtest - True if backtest mode, false if live mode
8938
8938
  * @returns Configured ClientRisk instance
8939
8939
  */
8940
- getRisk: ((riskName: RiskName, backtest: boolean) => ClientRisk) & functools_kit.IClearableMemoize<string> & functools_kit.IControlMemoize<string, ClientRisk>;
8940
+ getRisk: ((riskName: RiskName, backtest: boolean) => ClientRisk) & functools_kit.IClearableMemoize<`${string}:backtest` | `${string}:live`> & functools_kit.IControlMemoize<`${string}:backtest` | `${string}:live`, ClientRisk>;
8941
8941
  /**
8942
8942
  * Checks if a signal should be allowed based on risk limits.
8943
8943
  *
@@ -8980,9 +8980,12 @@ declare class RiskConnectionService {
8980
8980
  /**
8981
8981
  * Clears the cached ClientRisk instance for the given risk name.
8982
8982
  *
8983
- * @param riskName - Name of the risk schema to clear from cache
8983
+ * @param backtest - Whether running in backtest mode
8984
+ * @param ctx - Optional context with riskName (clears all if not provided)
8984
8985
  */
8985
- clear: (backtest: boolean, riskName?: RiskName) => Promise<void>;
8986
+ clear: (backtest: boolean, ctx?: {
8987
+ riskName: RiskName;
8988
+ }) => Promise<void>;
8986
8989
  }
8987
8990
 
8988
8991
  /**
@@ -9674,11 +9677,14 @@ declare class RiskGlobalService {
9674
9677
  }) => Promise<void>;
9675
9678
  /**
9676
9679
  * Clears risk data.
9677
- * If riskName is provided, clears data for that specific risk instance.
9678
- * If no riskName is provided, clears all risk data.
9679
- * @param riskName - Optional name of the risk instance to clear
9680
+ * If ctx is provided, clears data for that specific risk instance.
9681
+ * If no ctx is provided, clears all risk data.
9682
+ * @param backtest - Whether running in backtest mode
9683
+ * @param ctx - Optional context with riskName (clears all if not provided)
9680
9684
  */
9681
- clear: (backtest: boolean, riskName?: RiskName) => Promise<void>;
9685
+ clear: (backtest: boolean, ctx?: {
9686
+ riskName: RiskName;
9687
+ }) => Promise<void>;
9682
9688
  }
9683
9689
 
9684
9690
  /**