backtest-kit 6.13.0 → 6.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.cjs CHANGED
@@ -147,6 +147,9 @@ const reportServices$1 = {
147
147
  highestProfitReportService: Symbol('highestProfitReportService'),
148
148
  maxDrawdownReportService: Symbol('maxDrawdownReportService'),
149
149
  };
150
+ const helperServices$1 = {
151
+ notificationHelperService: Symbol('notificationHelperService'),
152
+ };
150
153
  const validationServices$1 = {
151
154
  exchangeValidationService: Symbol('exchangeValidationService'),
152
155
  strategyValidationService: Symbol('strategyValidationService'),
@@ -172,6 +175,7 @@ const TYPES = {
172
175
  ...markdownServices$1,
173
176
  ...reportServices$1,
174
177
  ...validationServices$1,
178
+ ...helperServices$1,
175
179
  };
176
180
 
177
181
  /**
@@ -764,6 +768,11 @@ const highestProfitSubject = new functoolsKit.Subject();
764
768
  * Allows users to track drawdown levels and implement custom risk management logic based on drawdown thresholds.
765
769
  */
766
770
  const maxDrawdownSubject = new functoolsKit.Subject();
771
+ /**
772
+ * Signal info emitter for user-defined informational notes on open positions.
773
+ * Emits when a strategy calls commitSignalInfo() to broadcast a custom annotation.
774
+ */
775
+ const signalNotifySubject = new functoolsKit.Subject();
767
776
 
768
777
  var emitters = /*#__PURE__*/Object.freeze({
769
778
  __proto__: null,
@@ -788,6 +797,7 @@ var emitters = /*#__PURE__*/Object.freeze({
788
797
  signalBacktestEmitter: signalBacktestEmitter,
789
798
  signalEmitter: signalEmitter,
790
799
  signalLiveEmitter: signalLiveEmitter,
800
+ signalNotifySubject: signalNotifySubject,
791
801
  strategyCommitSubject: strategyCommitSubject,
792
802
  syncSubject: syncSubject,
793
803
  validationSubject: validationSubject,
@@ -10290,7 +10300,7 @@ const GET_RISK_FN = (dto, backtest, exchangeName, frameName, self) => {
10290
10300
  * @param backtest - Whether running in backtest mode
10291
10301
  * @returns Unique string key for memoization
10292
10302
  */
10293
- const CREATE_KEY_FN$u = (symbol, strategyName, exchangeName, frameName, backtest) => {
10303
+ const CREATE_KEY_FN$v = (symbol, strategyName, exchangeName, frameName, backtest) => {
10294
10304
  const parts = [symbol, strategyName, exchangeName];
10295
10305
  if (frameName)
10296
10306
  parts.push(frameName);
@@ -10557,7 +10567,7 @@ class StrategyConnectionService {
10557
10567
  * @param backtest - Whether running in backtest mode
10558
10568
  * @returns Configured ClientStrategy instance
10559
10569
  */
10560
- this.getStrategy = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$u(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => {
10570
+ this.getStrategy = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$v(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => {
10561
10571
  const { riskName = "", riskList = [], getSignal, interval = STRATEGY_DEFAULT_INTERVAL, callbacks, } = this.strategySchemaService.get(strategyName);
10562
10572
  return new ClientStrategy({
10563
10573
  symbol,
@@ -11478,7 +11488,7 @@ class StrategyConnectionService {
11478
11488
  }
11479
11489
  return;
11480
11490
  }
11481
- const key = CREATE_KEY_FN$u(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
11491
+ const key = CREATE_KEY_FN$v(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
11482
11492
  if (!this.getStrategy.has(key)) {
11483
11493
  return;
11484
11494
  }
@@ -12647,7 +12657,7 @@ class ClientRisk {
12647
12657
  * @param backtest - Whether running in backtest mode
12648
12658
  * @returns Unique string key for memoization
12649
12659
  */
12650
- const CREATE_KEY_FN$t = (riskName, exchangeName, frameName, backtest) => {
12660
+ const CREATE_KEY_FN$u = (riskName, exchangeName, frameName, backtest) => {
12651
12661
  const parts = [riskName, exchangeName];
12652
12662
  if (frameName)
12653
12663
  parts.push(frameName);
@@ -12747,7 +12757,7 @@ class RiskConnectionService {
12747
12757
  * @param backtest - True if backtest mode, false if live mode
12748
12758
  * @returns Configured ClientRisk instance
12749
12759
  */
12750
- this.getRisk = functoolsKit.memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$t(riskName, exchangeName, frameName, backtest), (riskName, exchangeName, frameName, backtest) => {
12760
+ this.getRisk = functoolsKit.memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$u(riskName, exchangeName, frameName, backtest), (riskName, exchangeName, frameName, backtest) => {
12751
12761
  const schema = this.riskSchemaService.get(riskName);
12752
12762
  return new ClientRisk({
12753
12763
  ...schema,
@@ -12816,7 +12826,7 @@ class RiskConnectionService {
12816
12826
  payload,
12817
12827
  });
12818
12828
  if (payload) {
12819
- const key = CREATE_KEY_FN$t(payload.riskName, payload.exchangeName, payload.frameName, payload.backtest);
12829
+ const key = CREATE_KEY_FN$u(payload.riskName, payload.exchangeName, payload.frameName, payload.backtest);
12820
12830
  this.getRisk.clear(key);
12821
12831
  }
12822
12832
  else {
@@ -13860,7 +13870,7 @@ class ClientAction {
13860
13870
  * @param backtest - Whether running in backtest mode
13861
13871
  * @returns Unique string key for memoization
13862
13872
  */
13863
- const CREATE_KEY_FN$s = (actionName, strategyName, exchangeName, frameName, backtest) => {
13873
+ const CREATE_KEY_FN$t = (actionName, strategyName, exchangeName, frameName, backtest) => {
13864
13874
  const parts = [actionName, strategyName, exchangeName];
13865
13875
  if (frameName)
13866
13876
  parts.push(frameName);
@@ -13912,7 +13922,7 @@ class ActionConnectionService {
13912
13922
  * @param backtest - True if backtest mode, false if live mode
13913
13923
  * @returns Configured ClientAction instance
13914
13924
  */
13915
- this.getAction = functoolsKit.memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$s(actionName, strategyName, exchangeName, frameName, backtest), (actionName, strategyName, exchangeName, frameName, backtest) => {
13925
+ this.getAction = functoolsKit.memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$t(actionName, strategyName, exchangeName, frameName, backtest), (actionName, strategyName, exchangeName, frameName, backtest) => {
13916
13926
  const schema = this.actionSchemaService.get(actionName);
13917
13927
  return new ClientAction({
13918
13928
  ...schema,
@@ -14123,7 +14133,7 @@ class ActionConnectionService {
14123
14133
  await Promise.all(actions.map(async (action) => await action.dispose()));
14124
14134
  return;
14125
14135
  }
14126
- const key = CREATE_KEY_FN$s(payload.actionName, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
14136
+ const key = CREATE_KEY_FN$t(payload.actionName, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
14127
14137
  if (!this.getAction.has(key)) {
14128
14138
  return;
14129
14139
  }
@@ -14134,14 +14144,14 @@ class ActionConnectionService {
14134
14144
  }
14135
14145
  }
14136
14146
 
14137
- const METHOD_NAME_VALIDATE$2 = "exchangeCoreService validate";
14147
+ const METHOD_NAME_VALIDATE$3 = "exchangeCoreService validate";
14138
14148
  /**
14139
14149
  * Creates a unique key for memoizing validate calls.
14140
14150
  * Key format: "exchangeName"
14141
14151
  * @param exchangeName - Exchange name
14142
14152
  * @returns Unique string key for memoization
14143
14153
  */
14144
- const CREATE_KEY_FN$r = (exchangeName) => {
14154
+ const CREATE_KEY_FN$s = (exchangeName) => {
14145
14155
  return exchangeName;
14146
14156
  };
14147
14157
  /**
@@ -14165,11 +14175,11 @@ class ExchangeCoreService {
14165
14175
  * @param exchangeName - Name of the exchange to validate
14166
14176
  * @returns Promise that resolves when validation is complete
14167
14177
  */
14168
- this.validate = functoolsKit.memoize(([exchangeName]) => CREATE_KEY_FN$r(exchangeName), async (exchangeName) => {
14169
- this.loggerService.log(METHOD_NAME_VALIDATE$2, {
14178
+ this.validate = functoolsKit.memoize(([exchangeName]) => CREATE_KEY_FN$s(exchangeName), async (exchangeName) => {
14179
+ this.loggerService.log(METHOD_NAME_VALIDATE$3, {
14170
14180
  exchangeName,
14171
14181
  });
14172
- this.exchangeValidationService.validate(exchangeName, METHOD_NAME_VALIDATE$2);
14182
+ this.exchangeValidationService.validate(exchangeName, METHOD_NAME_VALIDATE$3);
14173
14183
  });
14174
14184
  /**
14175
14185
  * Fetches historical candles with execution context.
@@ -14410,14 +14420,14 @@ class ExchangeCoreService {
14410
14420
  }
14411
14421
  }
14412
14422
 
14413
- const METHOD_NAME_VALIDATE$1 = "strategyCoreService validate";
14423
+ const METHOD_NAME_VALIDATE$2 = "strategyCoreService validate";
14414
14424
  /**
14415
14425
  * Creates a unique key for memoizing validate calls.
14416
14426
  * Key format: "strategyName:exchangeName:frameName"
14417
14427
  * @param context - Execution context with strategyName, exchangeName, frameName
14418
14428
  * @returns Unique string key for memoization
14419
14429
  */
14420
- const CREATE_KEY_FN$q = (context) => {
14430
+ const CREATE_KEY_FN$r = (context) => {
14421
14431
  const parts = [context.strategyName, context.exchangeName];
14422
14432
  if (context.frameName)
14423
14433
  parts.push(context.frameName);
@@ -14449,16 +14459,16 @@ class StrategyCoreService {
14449
14459
  * @param context - Execution context with strategyName, exchangeName, frameName
14450
14460
  * @returns Promise that resolves when validation is complete
14451
14461
  */
14452
- this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$q(context), async (context) => {
14453
- this.loggerService.log(METHOD_NAME_VALIDATE$1, {
14462
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$r(context), async (context) => {
14463
+ this.loggerService.log(METHOD_NAME_VALIDATE$2, {
14454
14464
  context,
14455
14465
  });
14456
14466
  const { riskName, riskList } = this.strategySchemaService.get(context.strategyName);
14457
- this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$1);
14458
- this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$1);
14459
- context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$1);
14460
- riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1);
14461
- riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1));
14467
+ this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$2);
14468
+ this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$2);
14469
+ context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$2);
14470
+ riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$2);
14471
+ riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$2));
14462
14472
  });
14463
14473
  /**
14464
14474
  * Retrieves the currently active pending signal for the symbol.
@@ -15787,7 +15797,7 @@ class SizingGlobalService {
15787
15797
  * @param context - Context with riskName, exchangeName, frameName
15788
15798
  * @returns Unique string key for memoization
15789
15799
  */
15790
- const CREATE_KEY_FN$p = (context) => {
15800
+ const CREATE_KEY_FN$q = (context) => {
15791
15801
  const parts = [context.riskName, context.exchangeName];
15792
15802
  if (context.frameName)
15793
15803
  parts.push(context.frameName);
@@ -15813,7 +15823,7 @@ class RiskGlobalService {
15813
15823
  * @param payload - Payload with riskName, exchangeName and frameName
15814
15824
  * @returns Promise that resolves when validation is complete
15815
15825
  */
15816
- this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$p(context), async (context) => {
15826
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$q(context), async (context) => {
15817
15827
  this.loggerService.log("riskGlobalService validate", {
15818
15828
  context,
15819
15829
  });
@@ -15884,14 +15894,14 @@ class RiskGlobalService {
15884
15894
  }
15885
15895
  }
15886
15896
 
15887
- const METHOD_NAME_VALIDATE = "actionCoreService validate";
15897
+ const METHOD_NAME_VALIDATE$1 = "actionCoreService validate";
15888
15898
  /**
15889
15899
  * Creates a unique key for memoizing validate calls.
15890
15900
  * Key format: "strategyName:exchangeName:frameName"
15891
15901
  * @param context - Execution context with strategyName, exchangeName, frameName
15892
15902
  * @returns Unique string key for memoization
15893
15903
  */
15894
- const CREATE_KEY_FN$o = (context) => {
15904
+ const CREATE_KEY_FN$p = (context) => {
15895
15905
  const parts = [context.strategyName, context.exchangeName];
15896
15906
  if (context.frameName)
15897
15907
  parts.push(context.frameName);
@@ -15935,17 +15945,17 @@ class ActionCoreService {
15935
15945
  * @param context - Strategy execution context with strategyName, exchangeName and frameName
15936
15946
  * @returns Promise that resolves when all validations complete
15937
15947
  */
15938
- this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$o(context), async (context) => {
15939
- this.loggerService.log(METHOD_NAME_VALIDATE, {
15948
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$p(context), async (context) => {
15949
+ this.loggerService.log(METHOD_NAME_VALIDATE$1, {
15940
15950
  context,
15941
15951
  });
15942
15952
  const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
15943
- this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE);
15944
- this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE);
15945
- context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE);
15946
- riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE);
15947
- riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE));
15948
- actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE));
15953
+ this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$1);
15954
+ this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$1);
15955
+ context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$1);
15956
+ riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1);
15957
+ riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1));
15958
+ actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE$1));
15949
15959
  });
15950
15960
  /**
15951
15961
  * Initializes all ClientAction instances for the strategy.
@@ -20978,7 +20988,7 @@ const ReportWriter = new ReportWriterAdapter();
20978
20988
  * @param backtest - Whether running in backtest mode
20979
20989
  * @returns Unique string key for memoization
20980
20990
  */
20981
- const CREATE_KEY_FN$n = (symbol, strategyName, exchangeName, frameName, backtest) => {
20991
+ const CREATE_KEY_FN$o = (symbol, strategyName, exchangeName, frameName, backtest) => {
20982
20992
  const parts = [symbol, strategyName, exchangeName];
20983
20993
  if (frameName)
20984
20994
  parts.push(frameName);
@@ -21224,7 +21234,7 @@ class BacktestMarkdownService {
21224
21234
  * Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
21225
21235
  * Each combination gets its own isolated storage instance.
21226
21236
  */
21227
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$n(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$a(symbol, strategyName, exchangeName, frameName));
21237
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$o(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$a(symbol, strategyName, exchangeName, frameName));
21228
21238
  /**
21229
21239
  * Processes tick events and accumulates closed signals.
21230
21240
  * Should be called from IStrategyCallbacks.onTick.
@@ -21381,7 +21391,7 @@ class BacktestMarkdownService {
21381
21391
  payload,
21382
21392
  });
21383
21393
  if (payload) {
21384
- const key = CREATE_KEY_FN$n(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
21394
+ const key = CREATE_KEY_FN$o(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
21385
21395
  this.getStorage.clear(key);
21386
21396
  }
21387
21397
  else {
@@ -21443,7 +21453,7 @@ class BacktestMarkdownService {
21443
21453
  * @param backtest - Whether running in backtest mode
21444
21454
  * @returns Unique string key for memoization
21445
21455
  */
21446
- const CREATE_KEY_FN$m = (symbol, strategyName, exchangeName, frameName, backtest) => {
21456
+ const CREATE_KEY_FN$n = (symbol, strategyName, exchangeName, frameName, backtest) => {
21447
21457
  const parts = [symbol, strategyName, exchangeName];
21448
21458
  if (frameName)
21449
21459
  parts.push(frameName);
@@ -21938,7 +21948,7 @@ class LiveMarkdownService {
21938
21948
  * Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
21939
21949
  * Each combination gets its own isolated storage instance.
21940
21950
  */
21941
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$m(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$9(symbol, strategyName, exchangeName, frameName));
21951
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$n(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$9(symbol, strategyName, exchangeName, frameName));
21942
21952
  /**
21943
21953
  * Subscribes to live signal emitter to receive tick events.
21944
21954
  * Protected against multiple subscriptions.
@@ -22156,7 +22166,7 @@ class LiveMarkdownService {
22156
22166
  payload,
22157
22167
  });
22158
22168
  if (payload) {
22159
- const key = CREATE_KEY_FN$m(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
22169
+ const key = CREATE_KEY_FN$n(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
22160
22170
  this.getStorage.clear(key);
22161
22171
  }
22162
22172
  else {
@@ -22176,7 +22186,7 @@ class LiveMarkdownService {
22176
22186
  * @param backtest - Whether running in backtest mode
22177
22187
  * @returns Unique string key for memoization
22178
22188
  */
22179
- const CREATE_KEY_FN$l = (symbol, strategyName, exchangeName, frameName, backtest) => {
22189
+ const CREATE_KEY_FN$m = (symbol, strategyName, exchangeName, frameName, backtest) => {
22180
22190
  const parts = [symbol, strategyName, exchangeName];
22181
22191
  if (frameName)
22182
22192
  parts.push(frameName);
@@ -22465,7 +22475,7 @@ class ScheduleMarkdownService {
22465
22475
  * Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
22466
22476
  * Each combination gets its own isolated storage instance.
22467
22477
  */
22468
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$l(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$8(symbol, strategyName, exchangeName, frameName));
22478
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$m(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$8(symbol, strategyName, exchangeName, frameName));
22469
22479
  /**
22470
22480
  * Subscribes to signal emitter to receive scheduled signal events.
22471
22481
  * Protected against multiple subscriptions.
@@ -22668,7 +22678,7 @@ class ScheduleMarkdownService {
22668
22678
  payload,
22669
22679
  });
22670
22680
  if (payload) {
22671
- const key = CREATE_KEY_FN$l(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
22681
+ const key = CREATE_KEY_FN$m(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
22672
22682
  this.getStorage.clear(key);
22673
22683
  }
22674
22684
  else {
@@ -22688,7 +22698,7 @@ class ScheduleMarkdownService {
22688
22698
  * @param backtest - Whether running in backtest mode
22689
22699
  * @returns Unique string key for memoization
22690
22700
  */
22691
- const CREATE_KEY_FN$k = (symbol, strategyName, exchangeName, frameName, backtest) => {
22701
+ const CREATE_KEY_FN$l = (symbol, strategyName, exchangeName, frameName, backtest) => {
22692
22702
  const parts = [symbol, strategyName, exchangeName];
22693
22703
  if (frameName)
22694
22704
  parts.push(frameName);
@@ -22933,7 +22943,7 @@ class PerformanceMarkdownService {
22933
22943
  * Memoized function to get or create PerformanceStorage for a symbol-strategy-exchange-frame-backtest combination.
22934
22944
  * Each combination gets its own isolated storage instance.
22935
22945
  */
22936
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$k(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new PerformanceStorage(symbol, strategyName, exchangeName, frameName));
22946
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$l(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new PerformanceStorage(symbol, strategyName, exchangeName, frameName));
22937
22947
  /**
22938
22948
  * Subscribes to performance emitter to receive performance events.
22939
22949
  * Protected against multiple subscriptions.
@@ -23100,7 +23110,7 @@ class PerformanceMarkdownService {
23100
23110
  payload,
23101
23111
  });
23102
23112
  if (payload) {
23103
- const key = CREATE_KEY_FN$k(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
23113
+ const key = CREATE_KEY_FN$l(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
23104
23114
  this.getStorage.clear(key);
23105
23115
  }
23106
23116
  else {
@@ -23579,7 +23589,7 @@ class WalkerMarkdownService {
23579
23589
  * @param backtest - Whether running in backtest mode
23580
23590
  * @returns Unique string key for memoization
23581
23591
  */
23582
- const CREATE_KEY_FN$j = (exchangeName, frameName, backtest) => {
23592
+ const CREATE_KEY_FN$k = (exchangeName, frameName, backtest) => {
23583
23593
  const parts = [exchangeName];
23584
23594
  if (frameName)
23585
23595
  parts.push(frameName);
@@ -24026,7 +24036,7 @@ class HeatMarkdownService {
24026
24036
  * Memoized function to get or create HeatmapStorage for exchange, frame and backtest mode.
24027
24037
  * Each exchangeName + frameName + backtest mode combination gets its own isolated heatmap storage instance.
24028
24038
  */
24029
- this.getStorage = functoolsKit.memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$j(exchangeName, frameName, backtest), (exchangeName, frameName, backtest) => new HeatmapStorage(exchangeName, frameName, backtest));
24039
+ this.getStorage = functoolsKit.memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$k(exchangeName, frameName, backtest), (exchangeName, frameName, backtest) => new HeatmapStorage(exchangeName, frameName, backtest));
24030
24040
  /**
24031
24041
  * Subscribes to signal emitter to receive tick events.
24032
24042
  * Protected against multiple subscriptions.
@@ -24244,7 +24254,7 @@ class HeatMarkdownService {
24244
24254
  payload,
24245
24255
  });
24246
24256
  if (payload) {
24247
- const key = CREATE_KEY_FN$j(payload.exchangeName, payload.frameName, payload.backtest);
24257
+ const key = CREATE_KEY_FN$k(payload.exchangeName, payload.frameName, payload.backtest);
24248
24258
  this.getStorage.clear(key);
24249
24259
  }
24250
24260
  else {
@@ -25275,7 +25285,7 @@ class ClientPartial {
25275
25285
  * @param backtest - Whether running in backtest mode
25276
25286
  * @returns Unique string key for memoization
25277
25287
  */
25278
- const CREATE_KEY_FN$i = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
25288
+ const CREATE_KEY_FN$j = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
25279
25289
  /**
25280
25290
  * Creates a callback function for emitting profit events to partialProfitSubject.
25281
25291
  *
@@ -25397,7 +25407,7 @@ class PartialConnectionService {
25397
25407
  * Key format: "signalId:backtest" or "signalId:live"
25398
25408
  * Value: ClientPartial instance with logger and event emitters
25399
25409
  */
25400
- this.getPartial = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$i(signalId, backtest), (signalId, backtest) => {
25410
+ this.getPartial = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$j(signalId, backtest), (signalId, backtest) => {
25401
25411
  return new ClientPartial({
25402
25412
  signalId,
25403
25413
  logger: this.loggerService,
@@ -25487,7 +25497,7 @@ class PartialConnectionService {
25487
25497
  const partial = this.getPartial(data.id, backtest);
25488
25498
  await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
25489
25499
  await partial.clear(symbol, data, priceClose, backtest);
25490
- const key = CREATE_KEY_FN$i(data.id, backtest);
25500
+ const key = CREATE_KEY_FN$j(data.id, backtest);
25491
25501
  this.getPartial.clear(key);
25492
25502
  };
25493
25503
  }
@@ -25503,7 +25513,7 @@ class PartialConnectionService {
25503
25513
  * @param backtest - Whether running in backtest mode
25504
25514
  * @returns Unique string key for memoization
25505
25515
  */
25506
- const CREATE_KEY_FN$h = (symbol, strategyName, exchangeName, frameName, backtest) => {
25516
+ const CREATE_KEY_FN$i = (symbol, strategyName, exchangeName, frameName, backtest) => {
25507
25517
  const parts = [symbol, strategyName, exchangeName];
25508
25518
  if (frameName)
25509
25519
  parts.push(frameName);
@@ -25726,7 +25736,7 @@ class PartialMarkdownService {
25726
25736
  * Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
25727
25737
  * Each combination gets its own isolated storage instance.
25728
25738
  */
25729
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$h(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$6(symbol, strategyName, exchangeName, frameName));
25739
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$i(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$6(symbol, strategyName, exchangeName, frameName));
25730
25740
  /**
25731
25741
  * Subscribes to partial profit/loss signal emitters to receive events.
25732
25742
  * Protected against multiple subscriptions.
@@ -25936,7 +25946,7 @@ class PartialMarkdownService {
25936
25946
  payload,
25937
25947
  });
25938
25948
  if (payload) {
25939
- const key = CREATE_KEY_FN$h(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
25949
+ const key = CREATE_KEY_FN$i(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
25940
25950
  this.getStorage.clear(key);
25941
25951
  }
25942
25952
  else {
@@ -25952,7 +25962,7 @@ class PartialMarkdownService {
25952
25962
  * @param context - Context with strategyName, exchangeName, frameName
25953
25963
  * @returns Unique string key for memoization
25954
25964
  */
25955
- const CREATE_KEY_FN$g = (context) => {
25965
+ const CREATE_KEY_FN$h = (context) => {
25956
25966
  const parts = [context.strategyName, context.exchangeName];
25957
25967
  if (context.frameName)
25958
25968
  parts.push(context.frameName);
@@ -26026,7 +26036,7 @@ class PartialGlobalService {
26026
26036
  * @param context - Context with strategyName, exchangeName and frameName
26027
26037
  * @param methodName - Name of the calling method for error tracking
26028
26038
  */
26029
- this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$g(context), (context, methodName) => {
26039
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$h(context), (context, methodName) => {
26030
26040
  this.loggerService.log("partialGlobalService validate", {
26031
26041
  context,
26032
26042
  methodName,
@@ -26481,7 +26491,7 @@ class ClientBreakeven {
26481
26491
  * @param backtest - Whether running in backtest mode
26482
26492
  * @returns Unique string key for memoization
26483
26493
  */
26484
- const CREATE_KEY_FN$f = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
26494
+ const CREATE_KEY_FN$g = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
26485
26495
  /**
26486
26496
  * Creates a callback function for emitting breakeven events to breakevenSubject.
26487
26497
  *
@@ -26567,7 +26577,7 @@ class BreakevenConnectionService {
26567
26577
  * Key format: "signalId:backtest" or "signalId:live"
26568
26578
  * Value: ClientBreakeven instance with logger and event emitter
26569
26579
  */
26570
- this.getBreakeven = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$f(signalId, backtest), (signalId, backtest) => {
26580
+ this.getBreakeven = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$g(signalId, backtest), (signalId, backtest) => {
26571
26581
  return new ClientBreakeven({
26572
26582
  signalId,
26573
26583
  logger: this.loggerService,
@@ -26628,7 +26638,7 @@ class BreakevenConnectionService {
26628
26638
  const breakeven = this.getBreakeven(data.id, backtest);
26629
26639
  await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
26630
26640
  await breakeven.clear(symbol, data, priceClose, backtest);
26631
- const key = CREATE_KEY_FN$f(data.id, backtest);
26641
+ const key = CREATE_KEY_FN$g(data.id, backtest);
26632
26642
  this.getBreakeven.clear(key);
26633
26643
  };
26634
26644
  }
@@ -26644,7 +26654,7 @@ class BreakevenConnectionService {
26644
26654
  * @param backtest - Whether running in backtest mode
26645
26655
  * @returns Unique string key for memoization
26646
26656
  */
26647
- const CREATE_KEY_FN$e = (symbol, strategyName, exchangeName, frameName, backtest) => {
26657
+ const CREATE_KEY_FN$f = (symbol, strategyName, exchangeName, frameName, backtest) => {
26648
26658
  const parts = [symbol, strategyName, exchangeName];
26649
26659
  if (frameName)
26650
26660
  parts.push(frameName);
@@ -26819,7 +26829,7 @@ class BreakevenMarkdownService {
26819
26829
  * Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
26820
26830
  * Each combination gets its own isolated storage instance.
26821
26831
  */
26822
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$e(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$5(symbol, strategyName, exchangeName, frameName));
26832
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$f(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$5(symbol, strategyName, exchangeName, frameName));
26823
26833
  /**
26824
26834
  * Subscribes to breakeven signal emitter to receive events.
26825
26835
  * Protected against multiple subscriptions.
@@ -27008,7 +27018,7 @@ class BreakevenMarkdownService {
27008
27018
  payload,
27009
27019
  });
27010
27020
  if (payload) {
27011
- const key = CREATE_KEY_FN$e(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
27021
+ const key = CREATE_KEY_FN$f(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
27012
27022
  this.getStorage.clear(key);
27013
27023
  }
27014
27024
  else {
@@ -27024,7 +27034,7 @@ class BreakevenMarkdownService {
27024
27034
  * @param context - Context with strategyName, exchangeName, frameName
27025
27035
  * @returns Unique string key for memoization
27026
27036
  */
27027
- const CREATE_KEY_FN$d = (context) => {
27037
+ const CREATE_KEY_FN$e = (context) => {
27028
27038
  const parts = [context.strategyName, context.exchangeName];
27029
27039
  if (context.frameName)
27030
27040
  parts.push(context.frameName);
@@ -27098,7 +27108,7 @@ class BreakevenGlobalService {
27098
27108
  * @param context - Context with strategyName, exchangeName and frameName
27099
27109
  * @param methodName - Name of the calling method for error tracking
27100
27110
  */
27101
- this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$d(context), (context, methodName) => {
27111
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$e(context), (context, methodName) => {
27102
27112
  this.loggerService.log("breakevenGlobalService validate", {
27103
27113
  context,
27104
27114
  methodName,
@@ -27319,7 +27329,7 @@ class ConfigValidationService {
27319
27329
  * @param backtest - Whether running in backtest mode
27320
27330
  * @returns Unique string key for memoization
27321
27331
  */
27322
- const CREATE_KEY_FN$c = (symbol, strategyName, exchangeName, frameName, backtest) => {
27332
+ const CREATE_KEY_FN$d = (symbol, strategyName, exchangeName, frameName, backtest) => {
27323
27333
  const parts = [symbol, strategyName, exchangeName];
27324
27334
  if (frameName)
27325
27335
  parts.push(frameName);
@@ -27486,7 +27496,7 @@ class RiskMarkdownService {
27486
27496
  * Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
27487
27497
  * Each combination gets its own isolated storage instance.
27488
27498
  */
27489
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$c(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$4(symbol, strategyName, exchangeName, frameName));
27499
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$d(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$4(symbol, strategyName, exchangeName, frameName));
27490
27500
  /**
27491
27501
  * Subscribes to risk rejection emitter to receive rejection events.
27492
27502
  * Protected against multiple subscriptions.
@@ -27675,7 +27685,7 @@ class RiskMarkdownService {
27675
27685
  payload,
27676
27686
  });
27677
27687
  if (payload) {
27678
- const key = CREATE_KEY_FN$c(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
27688
+ const key = CREATE_KEY_FN$d(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
27679
27689
  this.getStorage.clear(key);
27680
27690
  }
27681
27691
  else {
@@ -30057,7 +30067,7 @@ class HighestProfitReportService {
30057
30067
  * @returns Colon-separated key string for memoization
30058
30068
  * @internal
30059
30069
  */
30060
- const CREATE_KEY_FN$b = (symbol, strategyName, exchangeName, frameName, backtest) => {
30070
+ const CREATE_KEY_FN$c = (symbol, strategyName, exchangeName, frameName, backtest) => {
30061
30071
  const parts = [symbol, strategyName, exchangeName];
30062
30072
  if (frameName)
30063
30073
  parts.push(frameName);
@@ -30299,7 +30309,7 @@ class StrategyMarkdownService {
30299
30309
  *
30300
30310
  * @internal
30301
30311
  */
30302
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$b(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$3(symbol, strategyName, exchangeName, frameName));
30312
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$c(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$3(symbol, strategyName, exchangeName, frameName));
30303
30313
  /**
30304
30314
  * Records a cancel-scheduled event when a scheduled signal is cancelled.
30305
30315
  *
@@ -30873,7 +30883,7 @@ class StrategyMarkdownService {
30873
30883
  this.clear = async (payload) => {
30874
30884
  this.loggerService.log("strategyMarkdownService clear", { payload });
30875
30885
  if (payload) {
30876
- const key = CREATE_KEY_FN$b(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
30886
+ const key = CREATE_KEY_FN$c(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
30877
30887
  this.getStorage.clear(key);
30878
30888
  }
30879
30889
  else {
@@ -30981,7 +30991,7 @@ class StrategyMarkdownService {
30981
30991
  * Creates a unique key for memoizing ReportStorage instances.
30982
30992
  * Key format: "symbol:strategyName:exchangeName[:frameName]:backtest|live"
30983
30993
  */
30984
- const CREATE_KEY_FN$a = (symbol, strategyName, exchangeName, frameName, backtest) => {
30994
+ const CREATE_KEY_FN$b = (symbol, strategyName, exchangeName, frameName, backtest) => {
30985
30995
  const parts = [symbol, strategyName, exchangeName];
30986
30996
  if (frameName)
30987
30997
  parts.push(frameName);
@@ -31174,7 +31184,7 @@ let ReportStorage$2 = class ReportStorage {
31174
31184
  class SyncMarkdownService {
31175
31185
  constructor() {
31176
31186
  this.loggerService = inject(TYPES.loggerService);
31177
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$a(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$2(symbol, strategyName, exchangeName, frameName, backtest));
31187
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$b(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$2(symbol, strategyName, exchangeName, frameName, backtest));
31178
31188
  /**
31179
31189
  * Subscribes to `syncSubject` to start receiving `SignalSyncContract` events.
31180
31190
  * Protected against multiple subscriptions via `singleshot` — subsequent calls
@@ -31370,7 +31380,7 @@ class SyncMarkdownService {
31370
31380
  this.clear = async (payload) => {
31371
31381
  this.loggerService.log("syncMarkdownService clear", { payload });
31372
31382
  if (payload) {
31373
- const key = CREATE_KEY_FN$a(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
31383
+ const key = CREATE_KEY_FN$b(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
31374
31384
  this.getStorage.clear(key);
31375
31385
  }
31376
31386
  else {
@@ -31383,7 +31393,7 @@ class SyncMarkdownService {
31383
31393
  /**
31384
31394
  * Creates a unique memoization key for a symbol-strategy-exchange-frame-backtest combination.
31385
31395
  */
31386
- const CREATE_KEY_FN$9 = (symbol, strategyName, exchangeName, frameName, backtest) => {
31396
+ const CREATE_KEY_FN$a = (symbol, strategyName, exchangeName, frameName, backtest) => {
31387
31397
  const parts = [symbol, strategyName, exchangeName];
31388
31398
  if (frameName)
31389
31399
  parts.push(frameName);
@@ -31559,7 +31569,7 @@ let ReportStorage$1 = class ReportStorage {
31559
31569
  class HighestProfitMarkdownService {
31560
31570
  constructor() {
31561
31571
  this.loggerService = inject(TYPES.loggerService);
31562
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$9(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$1(symbol, strategyName, exchangeName, frameName));
31572
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$a(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$1(symbol, strategyName, exchangeName, frameName));
31563
31573
  /**
31564
31574
  * Subscribes to `highestProfitSubject` to start receiving `HighestProfitContract`
31565
31575
  * events. Protected against multiple subscriptions via `singleshot` — subsequent
@@ -31725,7 +31735,7 @@ class HighestProfitMarkdownService {
31725
31735
  this.clear = async (payload) => {
31726
31736
  this.loggerService.log("highestProfitMarkdownService clear", { payload });
31727
31737
  if (payload) {
31728
- const key = CREATE_KEY_FN$9(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
31738
+ const key = CREATE_KEY_FN$a(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
31729
31739
  this.getStorage.clear(key);
31730
31740
  }
31731
31741
  else {
@@ -31747,7 +31757,7 @@ const LISTEN_TIMEOUT$1 = 120000;
31747
31757
  * @param backtest - Whether running in backtest mode
31748
31758
  * @returns Unique string key for memoization
31749
31759
  */
31750
- const CREATE_KEY_FN$8 = (symbol, strategyName, exchangeName, frameName, backtest) => {
31760
+ const CREATE_KEY_FN$9 = (symbol, strategyName, exchangeName, frameName, backtest) => {
31751
31761
  const parts = [symbol, strategyName, exchangeName];
31752
31762
  if (frameName)
31753
31763
  parts.push(frameName);
@@ -31790,7 +31800,7 @@ class PriceMetaService {
31790
31800
  * Each subject holds the latest currentPrice emitted by the strategy iterator for that key.
31791
31801
  * Instances are cached until clear() is called.
31792
31802
  */
31793
- this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$8(symbol, strategyName, exchangeName, frameName, backtest), () => new functoolsKit.BehaviorSubject());
31803
+ this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$9(symbol, strategyName, exchangeName, frameName, backtest), () => new functoolsKit.BehaviorSubject());
31794
31804
  /**
31795
31805
  * Returns the current market price for the given symbol and context.
31796
31806
  *
@@ -31819,10 +31829,10 @@ class PriceMetaService {
31819
31829
  if (source.data) {
31820
31830
  return source.data;
31821
31831
  }
31822
- console.warn(`PriceMetaService: No currentPrice available for ${CREATE_KEY_FN$8(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}. Trying to fetch from strategy iterator as a fallback...`);
31832
+ console.warn(`PriceMetaService: No currentPrice available for ${CREATE_KEY_FN$9(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}. Trying to fetch from strategy iterator as a fallback...`);
31823
31833
  const currentPrice = await functoolsKit.waitForNext(source, (data) => !!data, LISTEN_TIMEOUT$1);
31824
31834
  if (typeof currentPrice === "symbol") {
31825
- throw new Error(`PriceMetaService: Timeout while waiting for currentPrice for ${CREATE_KEY_FN$8(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
31835
+ throw new Error(`PriceMetaService: Timeout while waiting for currentPrice for ${CREATE_KEY_FN$9(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
31826
31836
  }
31827
31837
  return currentPrice;
31828
31838
  };
@@ -31864,7 +31874,7 @@ class PriceMetaService {
31864
31874
  this.getSource.clear();
31865
31875
  return;
31866
31876
  }
31867
- const key = CREATE_KEY_FN$8(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
31877
+ const key = CREATE_KEY_FN$9(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
31868
31878
  this.getSource.clear(key);
31869
31879
  };
31870
31880
  }
@@ -31882,7 +31892,7 @@ const LISTEN_TIMEOUT = 120000;
31882
31892
  * @param backtest - Whether running in backtest mode
31883
31893
  * @returns Unique string key for memoization
31884
31894
  */
31885
- const CREATE_KEY_FN$7 = (symbol, strategyName, exchangeName, frameName, backtest) => {
31895
+ const CREATE_KEY_FN$8 = (symbol, strategyName, exchangeName, frameName, backtest) => {
31886
31896
  const parts = [symbol, strategyName, exchangeName];
31887
31897
  if (frameName)
31888
31898
  parts.push(frameName);
@@ -31925,7 +31935,7 @@ class TimeMetaService {
31925
31935
  * Each subject holds the latest createdAt timestamp emitted by the strategy iterator for that key.
31926
31936
  * Instances are cached until clear() is called.
31927
31937
  */
31928
- this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$7(symbol, strategyName, exchangeName, frameName, backtest), () => new functoolsKit.BehaviorSubject());
31938
+ this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$8(symbol, strategyName, exchangeName, frameName, backtest), () => new functoolsKit.BehaviorSubject());
31929
31939
  /**
31930
31940
  * Returns the current candle timestamp (in milliseconds) for the given symbol and context.
31931
31941
  *
@@ -31953,10 +31963,10 @@ class TimeMetaService {
31953
31963
  if (source.data) {
31954
31964
  return source.data;
31955
31965
  }
31956
- console.warn(`TimeMetaService: No timestamp available for ${CREATE_KEY_FN$7(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}. Trying to fetch from strategy iterator as a fallback...`);
31966
+ console.warn(`TimeMetaService: No timestamp available for ${CREATE_KEY_FN$8(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}. Trying to fetch from strategy iterator as a fallback...`);
31957
31967
  const timestamp = await functoolsKit.waitForNext(source, (data) => !!data, LISTEN_TIMEOUT);
31958
31968
  if (typeof timestamp === "symbol") {
31959
- throw new Error(`TimeMetaService: Timeout while waiting for timestamp for ${CREATE_KEY_FN$7(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
31969
+ throw new Error(`TimeMetaService: Timeout while waiting for timestamp for ${CREATE_KEY_FN$8(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
31960
31970
  }
31961
31971
  return timestamp;
31962
31972
  };
@@ -31998,7 +32008,7 @@ class TimeMetaService {
31998
32008
  this.getSource.clear();
31999
32009
  return;
32000
32010
  }
32001
- const key = CREATE_KEY_FN$7(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
32011
+ const key = CREATE_KEY_FN$8(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
32002
32012
  this.getSource.clear(key);
32003
32013
  };
32004
32014
  }
@@ -32094,7 +32104,7 @@ class MaxDrawdownReportService {
32094
32104
  /**
32095
32105
  * Creates a unique memoization key for a symbol-strategy-exchange-frame-backtest combination.
32096
32106
  */
32097
- const CREATE_KEY_FN$6 = (symbol, strategyName, exchangeName, frameName, backtest) => {
32107
+ const CREATE_KEY_FN$7 = (symbol, strategyName, exchangeName, frameName, backtest) => {
32098
32108
  const parts = [symbol, strategyName, exchangeName];
32099
32109
  if (frameName)
32100
32110
  parts.push(frameName);
@@ -32218,7 +32228,7 @@ class ReportStorage {
32218
32228
  class MaxDrawdownMarkdownService {
32219
32229
  constructor() {
32220
32230
  this.loggerService = inject(TYPES.loggerService);
32221
- this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$6(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage(symbol, strategyName, exchangeName, frameName));
32231
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$7(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage(symbol, strategyName, exchangeName, frameName));
32222
32232
  /**
32223
32233
  * Subscribes to `maxDrawdownSubject` to start receiving `MaxDrawdownContract`
32224
32234
  * events. Protected against multiple subscriptions via `singleshot`.
@@ -32297,7 +32307,7 @@ class MaxDrawdownMarkdownService {
32297
32307
  this.clear = async (payload) => {
32298
32308
  this.loggerService.log("maxDrawdownMarkdownService clear", { payload });
32299
32309
  if (payload) {
32300
- const key = CREATE_KEY_FN$6(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
32310
+ const key = CREATE_KEY_FN$7(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
32301
32311
  this.getStorage.clear(key);
32302
32312
  }
32303
32313
  else {
@@ -32307,6 +32317,125 @@ class MaxDrawdownMarkdownService {
32307
32317
  }
32308
32318
  }
32309
32319
 
32320
+ const METHOD_NAME_COMMIT_SIGNAL_NOTIFY = "notificationHelperService.commitSignalNotify";
32321
+ const METHOD_NAME_VALIDATE = "notificationHelperService.validate";
32322
+ /**
32323
+ * Creates a unique key for memoizing validate calls.
32324
+ * Key format: "strategyName:exchangeName:frameName"
32325
+ * @param context - Execution context with strategyName, exchangeName, frameName
32326
+ * @returns Unique string key for memoization
32327
+ */
32328
+ const CREATE_KEY_FN$6 = (context) => {
32329
+ const parts = [context.strategyName, context.exchangeName];
32330
+ if (context.frameName)
32331
+ parts.push(context.frameName);
32332
+ return parts.join(":");
32333
+ };
32334
+ /**
32335
+ * Helper service for emitting signal info notifications.
32336
+ *
32337
+ * Handles validation (memoized per context) and emission of `signal.info` events
32338
+ * via `signalNotifySubject`. Used internally by the framework action pipeline —
32339
+ * end users interact with this via `commitSignalNotify()` in `onActivePing` callbacks.
32340
+ */
32341
+ class NotificationHelperService {
32342
+ constructor() {
32343
+ this.loggerService = inject(TYPES.loggerService);
32344
+ this.strategySchemaService = inject(TYPES.strategySchemaService);
32345
+ this.riskValidationService = inject(TYPES.riskValidationService);
32346
+ this.strategyValidationService = inject(TYPES.strategyValidationService);
32347
+ this.exchangeValidationService = inject(TYPES.exchangeValidationService);
32348
+ this.frameValidationService = inject(TYPES.frameValidationService);
32349
+ this.actionValidationService = inject(TYPES.actionValidationService);
32350
+ this.strategyCoreService = inject(TYPES.strategyCoreService);
32351
+ this.timeMetaService = inject(TYPES.timeMetaService);
32352
+ /**
32353
+ * Validates strategy, exchange, frame, risk, and action schemas for the given context.
32354
+ *
32355
+ * Memoized per unique `"strategyName:exchangeName[:frameName]"` key — subsequent calls
32356
+ * with the same context are no-ops, so validation runs at most once per context.
32357
+ *
32358
+ * @param context - Routing context: strategyName, exchangeName, frameName
32359
+ * @throws {Error} If any registered schema fails validation
32360
+ */
32361
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$6(context), async (context) => {
32362
+ this.loggerService.log(METHOD_NAME_VALIDATE, {
32363
+ context,
32364
+ });
32365
+ this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE);
32366
+ this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE);
32367
+ const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
32368
+ context.frameName &&
32369
+ this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE);
32370
+ riskName &&
32371
+ this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE);
32372
+ riskList &&
32373
+ riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE));
32374
+ actions &&
32375
+ actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE));
32376
+ });
32377
+ /**
32378
+ * Emits a `signal.info` notification for the currently active pending signal.
32379
+ *
32380
+ * Validates all schemas (via memoized `validate`), resolves the pending signal
32381
+ * for the given symbol, then emits a `SignalInfoContract` via `signalNotifySubject`,
32382
+ * which is routed to all registered `listenSignalNotify` callbacks and persisted
32383
+ * by `NotificationAdapter`.
32384
+ *
32385
+ * @param payload - Optional notification fields (notificationId, notificationNote)
32386
+ * @param symbol - Trading pair symbol (e.g. "BTCUSDT")
32387
+ * @param currentPrice - Market price at the time of the call
32388
+ * @param context - Routing context: strategyName, exchangeName, frameName
32389
+ * @param backtest - true when called during a backtest run
32390
+ *
32391
+ * @throws {Error} If no active pending signal is found for the given symbol
32392
+ *
32393
+ * @example
32394
+ * ```typescript
32395
+ * // Inside onActivePing callback:
32396
+ * await commitSignalNotify("BTCUSDT", {
32397
+ * notificationNote: "RSI crossed 70, consider closing",
32398
+ * notificationId: "msg-123",
32399
+ * });
32400
+ * ```
32401
+ */
32402
+ this.commitSignalNotify = async (payload, symbol, currentPrice, context, backtest) => {
32403
+ this.loggerService.info(METHOD_NAME_COMMIT_SIGNAL_NOTIFY, {
32404
+ symbol,
32405
+ context,
32406
+ backtest,
32407
+ currentPrice,
32408
+ });
32409
+ this.validate(context);
32410
+ const pendingSignal = await this.strategyCoreService.getPendingSignal(backtest, symbol, currentPrice, {
32411
+ strategyName: context.strategyName,
32412
+ exchangeName: context.exchangeName,
32413
+ frameName: "",
32414
+ });
32415
+ if (!pendingSignal) {
32416
+ throw new Error(`SignalUtils notify No pending signal found symbol=${symbol} `);
32417
+ }
32418
+ const timestamp = await this.timeMetaService.getTimestamp(symbol, {
32419
+ strategyName: context.strategyName,
32420
+ exchangeName: context.exchangeName,
32421
+ frameName: context.frameName,
32422
+ }, backtest);
32423
+ await signalNotifySubject.next({
32424
+ backtest,
32425
+ symbol,
32426
+ currentPrice,
32427
+ data: pendingSignal,
32428
+ exchangeName: context.exchangeName,
32429
+ strategyName: context.strategyName,
32430
+ frameName: context.frameName,
32431
+ note: payload.notificationNote || pendingSignal.note,
32432
+ notificationId: payload.notificationId,
32433
+ timestamp,
32434
+ });
32435
+ };
32436
+ }
32437
+ }
32438
+
32310
32439
  {
32311
32440
  provide(TYPES.loggerService, () => new LoggerService());
32312
32441
  }
@@ -32395,6 +32524,9 @@ class MaxDrawdownMarkdownService {
32395
32524
  provide(TYPES.highestProfitReportService, () => new HighestProfitReportService());
32396
32525
  provide(TYPES.maxDrawdownReportService, () => new MaxDrawdownReportService());
32397
32526
  }
32527
+ {
32528
+ provide(TYPES.notificationHelperService, () => new NotificationHelperService());
32529
+ }
32398
32530
  {
32399
32531
  provide(TYPES.exchangeValidationService, () => new ExchangeValidationService());
32400
32532
  provide(TYPES.strategyValidationService, () => new StrategyValidationService());
@@ -32495,6 +32627,9 @@ const reportServices = {
32495
32627
  highestProfitReportService: inject(TYPES.highestProfitReportService),
32496
32628
  maxDrawdownReportService: inject(TYPES.maxDrawdownReportService),
32497
32629
  };
32630
+ const helperServices = {
32631
+ notificationHelperService: inject(TYPES.notificationHelperService),
32632
+ };
32498
32633
  const validationServices = {
32499
32634
  exchangeValidationService: inject(TYPES.exchangeValidationService),
32500
32635
  strategyValidationService: inject(TYPES.strategyValidationService),
@@ -32520,6 +32655,7 @@ const backtest = {
32520
32655
  ...markdownServices,
32521
32656
  ...reportServices,
32522
32657
  ...validationServices,
32658
+ ...helperServices,
32523
32659
  };
32524
32660
  init();
32525
32661
 
@@ -35436,6 +35572,7 @@ const GET_POSITION_ENTRY_OVERLAP_METHOD_NAME = "strategy.getPositionEntryOverlap
35436
35572
  const GET_POSITION_PARTIAL_OVERLAP_METHOD_NAME = "strategy.getPositionPartialOverlap";
35437
35573
  const HAS_NO_PENDING_SIGNAL_METHOD_NAME = "strategy.hasNoPendingSignal";
35438
35574
  const HAS_NO_SCHEDULED_SIGNAL_METHOD_NAME = "strategy.hasNoScheduledSignal";
35575
+ const COMMIT_SIGNAL_NOTIFY_METHOD_NAME = "strategy.commitSignalNotify";
35439
35576
  /**
35440
35577
  * Cancels the scheduled signal without stopping the strategy.
35441
35578
  *
@@ -37400,6 +37537,50 @@ async function hasNoScheduledSignal(symbol) {
37400
37537
  const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
37401
37538
  return await functoolsKit.not(backtest.strategyCoreService.hasScheduledSignal(isBacktest, symbol, { exchangeName, frameName, strategyName }));
37402
37539
  }
37540
+ /**
37541
+ * Emits a `signal.info` notification for the currently active pending signal.
37542
+ *
37543
+ * Broadcasts a user-defined informational note without affecting position state.
37544
+ * Useful for annotating strategy decisions, triggering external alerts, or logging
37545
+ * mid-position events (e.g. RSI crossing a threshold, volume spike detected).
37546
+ *
37547
+ * Automatically reads backtest/live mode from execution context.
37548
+ * Automatically reads strategyName, exchangeName, frameName from method context.
37549
+ * Automatically fetches current price via getAveragePrice.
37550
+ *
37551
+ * @param symbol - Trading pair symbol (e.g. "BTCUSDT")
37552
+ * @param payload - Optional notification fields
37553
+ * @param payload.notificationNote - Human-readable note. Falls back to signal.note if omitted.
37554
+ * @param payload.notificationId - Optional correlation ID for external systems (e.g. Telegram message ID).
37555
+ *
37556
+ * @throws {Error} If called outside an execution context
37557
+ * @throws {Error} If called outside a method context
37558
+ * @throws {Error} If no active pending signal exists for the given symbol
37559
+ *
37560
+ * @example
37561
+ * ```typescript
37562
+ * import { commitSignalNotify } from "backtest-kit";
37563
+ *
37564
+ * // Inside onActivePing callback:
37565
+ * await commitSignalNotify("BTCUSDT", {
37566
+ * notificationNote: "RSI crossed 70, consider closing",
37567
+ * notificationId: "msg-123",
37568
+ * });
37569
+ * ```
37570
+ */
37571
+ async function commitSignalNotify(symbol, payload = {}) {
37572
+ backtest.loggerService.info(COMMIT_SIGNAL_NOTIFY_METHOD_NAME, { symbol, payload });
37573
+ if (!ExecutionContextService.hasContext()) {
37574
+ throw new Error("commitSignalNotify requires an execution context");
37575
+ }
37576
+ if (!MethodContextService.hasContext()) {
37577
+ throw new Error("commitSignalNotify requires a method context");
37578
+ }
37579
+ const currentPrice = await getAveragePrice(symbol);
37580
+ const { backtest: isBacktest } = backtest.executionContextService.context;
37581
+ const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
37582
+ await backtest.notificationHelperService.commitSignalNotify(payload, symbol, currentPrice, { strategyName, exchangeName, frameName }, isBacktest);
37583
+ }
37403
37584
 
37404
37585
  const STOP_STRATEGY_METHOD_NAME = "control.stopStrategy";
37405
37586
  /**
@@ -37483,6 +37664,8 @@ const LISTEN_HIGHEST_PROFIT_METHOD_NAME = "event.listenHighestProfit";
37483
37664
  const LISTEN_HIGHEST_PROFIT_ONCE_METHOD_NAME = "event.listenHighestProfitOnce";
37484
37665
  const LISTEN_MAX_DRAWDOWN_METHOD_NAME = "event.listenMaxDrawdown";
37485
37666
  const LISTEN_MAX_DRAWDOWN_ONCE_METHOD_NAME = "event.listenMaxDrawdownOnce";
37667
+ const LISTEN_SIGNAL_NOTIFY_METHOD_NAME = "event.listenSignalNotify";
37668
+ const LISTEN_SIGNAL_NOTIFY_ONCE_METHOD_NAME = "event.listenSignalNotifyOnce";
37486
37669
  /**
37487
37670
  * Subscribes to all signal events with queued async processing.
37488
37671
  *
@@ -38874,6 +39057,46 @@ function listenMaxDrawdownOnce(filterFn, fn) {
38874
39057
  };
38875
39058
  return disposeFn = listenMaxDrawdown(wrappedFn);
38876
39059
  }
39060
+ /**
39061
+ * Subscribes to signal info events with queued async processing.
39062
+ * Emits when a strategy calls commitSignalInfo() to broadcast a user-defined note for an open position.
39063
+ * Events are processed sequentially in order received, even if callback is async.
39064
+ * Uses queued wrapper to prevent concurrent execution of the callback.
39065
+ * @param fn - Callback function to handle signal info events
39066
+ * @return Unsubscribe function to stop listening to events
39067
+ */
39068
+ function listenSignalNotify(fn) {
39069
+ backtest.loggerService.log(LISTEN_SIGNAL_NOTIFY_METHOD_NAME);
39070
+ const wrappedFn = async (event) => {
39071
+ if (await backtest.strategyCoreService.hasPendingSignal(event.backtest, event.symbol, {
39072
+ strategyName: event.strategyName,
39073
+ exchangeName: event.exchangeName,
39074
+ frameName: event.frameName,
39075
+ })) {
39076
+ await fn(event);
39077
+ }
39078
+ };
39079
+ return signalNotifySubject.subscribe(functoolsKit.queued(wrappedFn));
39080
+ }
39081
+ /**
39082
+ * Subscribes to filtered signal info events with one-time execution.
39083
+ * Listens for events matching the filter predicate, then executes callback once
39084
+ * and automatically unsubscribes.
39085
+ * @param filterFn - Predicate to filter which events trigger the callback
39086
+ * @param fn - Callback function to handle the filtered event (called only once)
39087
+ * @return Unsubscribe function to cancel the listener before it fires
39088
+ */
39089
+ function listenSignalNotifyOnce(filterFn, fn) {
39090
+ backtest.loggerService.log(LISTEN_SIGNAL_NOTIFY_ONCE_METHOD_NAME);
39091
+ let disposeFn;
39092
+ const wrappedFn = async (event) => {
39093
+ if (filterFn(event)) {
39094
+ await fn(event);
39095
+ disposeFn && disposeFn();
39096
+ }
39097
+ };
39098
+ return disposeFn = listenSignalNotify(wrappedFn);
39099
+ }
38877
39100
 
38878
39101
  const BACKTEST_METHOD_NAME_RUN = "BacktestUtils.run";
38879
39102
  const BACKTEST_METHOD_NAME_BACKGROUND = "BacktestUtils.background";
@@ -38930,6 +39153,7 @@ const BACKTEST_METHOD_NAME_TRAILING_STOP_COST = "BacktestUtils.commitTrailingSto
38930
39153
  const BACKTEST_METHOD_NAME_TRAILING_PROFIT_COST = "BacktestUtils.commitTrailingTakeCost";
38931
39154
  const BACKTEST_METHOD_NAME_ACTIVATE_SCHEDULED = "Backtest.commitActivateScheduled";
38932
39155
  const BACKTEST_METHOD_NAME_AVERAGE_BUY = "Backtest.commitAverageBuy";
39156
+ const BACKTEST_METHOD_NAME_SIGNAL_NOTIFY = "Backtest.commitSignalNotify";
38933
39157
  const BACKTEST_METHOD_NAME_GET_DATA = "BacktestUtils.getData";
38934
39158
  const BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "BacktestUtils.hasNoPendingSignal";
38935
39159
  const BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "BacktestUtils.hasNoScheduledSignal";
@@ -41285,6 +41509,33 @@ class BacktestUtils {
41285
41509
  });
41286
41510
  return await backtest.strategyCoreService.averageBuy(true, symbol, currentPrice, context, cost);
41287
41511
  };
41512
+ /**
41513
+ * Emits a `signal.info` notification for the currently active pending signal.
41514
+ *
41515
+ * @param symbol - Trading pair symbol
41516
+ * @param currentPrice - Market price at the time of the call
41517
+ * @param context - Execution context with strategyName, exchangeName, frameName
41518
+ * @param payload - Optional notification fields (notificationNote, notificationId)
41519
+ *
41520
+ * @throws {Error} If no active pending signal exists for the given symbol
41521
+ *
41522
+ * @example
41523
+ * ```typescript
41524
+ * await Backtest.commitSignalNotify("BTCUSDT", 42000, {
41525
+ * strategyName: "my-strategy",
41526
+ * exchangeName: "binance",
41527
+ * frameName: "1h"
41528
+ * }, { notificationNote: "RSI crossed 70" });
41529
+ * ```
41530
+ */
41531
+ this.commitSignalNotify = async (symbol, currentPrice, context, payload = {}) => {
41532
+ backtest.loggerService.info(BACKTEST_METHOD_NAME_SIGNAL_NOTIFY, {
41533
+ symbol,
41534
+ currentPrice,
41535
+ context,
41536
+ });
41537
+ await backtest.notificationHelperService.commitSignalNotify(payload, symbol, currentPrice, context, true);
41538
+ };
41288
41539
  /**
41289
41540
  * Gets statistical data from all closed signals for a symbol-strategy pair.
41290
41541
  *
@@ -41498,6 +41749,7 @@ const LIVE_METHOD_NAME_TRAILING_STOP_COST = "LiveUtils.commitTrailingStopCost";
41498
41749
  const LIVE_METHOD_NAME_TRAILING_PROFIT_COST = "LiveUtils.commitTrailingTakeCost";
41499
41750
  const LIVE_METHOD_NAME_ACTIVATE_SCHEDULED = "Live.commitActivateScheduled";
41500
41751
  const LIVE_METHOD_NAME_AVERAGE_BUY = "Live.commitAverageBuy";
41752
+ const LIVE_METHOD_NAME_SIGNAL_NOTIFY = "Live.commitSignalNotify";
41501
41753
  const LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "LiveUtils.hasNoPendingSignal";
41502
41754
  const LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "LiveUtils.hasNoScheduledSignal";
41503
41755
  /**
@@ -44194,6 +44446,36 @@ class LiveUtils {
44194
44446
  frameName: "",
44195
44447
  }, cost);
44196
44448
  };
44449
+ /**
44450
+ * Emits a `signal.info` notification for the currently active pending signal.
44451
+ *
44452
+ * @param symbol - Trading pair symbol
44453
+ * @param currentPrice - Market price at the time of the call
44454
+ * @param context - Execution context with strategyName and exchangeName
44455
+ * @param payload - Optional notification fields (notificationNote, notificationId)
44456
+ *
44457
+ * @throws {Error} If no active pending signal exists for the given symbol
44458
+ *
44459
+ * @example
44460
+ * ```typescript
44461
+ * await Live.commitSignalNotify("BTCUSDT", 42000, {
44462
+ * strategyName: "my-strategy",
44463
+ * exchangeName: "binance",
44464
+ * }, { notificationNote: "RSI crossed 70" });
44465
+ * ```
44466
+ */
44467
+ this.commitSignalNotify = async (symbol, currentPrice, context, payload = {}) => {
44468
+ backtest.loggerService.info(LIVE_METHOD_NAME_SIGNAL_NOTIFY, {
44469
+ symbol,
44470
+ currentPrice,
44471
+ context,
44472
+ });
44473
+ await backtest.notificationHelperService.commitSignalNotify(payload, symbol, currentPrice, {
44474
+ strategyName: context.strategyName,
44475
+ exchangeName: context.exchangeName,
44476
+ frameName: "",
44477
+ }, false);
44478
+ };
44197
44479
  /**
44198
44480
  * Gets statistical data from all live trading events for a symbol-strategy pair.
44199
44481
  *
@@ -48388,6 +48670,87 @@ class MarkdownUtils {
48388
48670
  backtest.maxDrawdownMarkdownService.unsubscribe();
48389
48671
  }
48390
48672
  };
48673
+ /**
48674
+ * Clears markdown report data selectively.
48675
+ *
48676
+ * Clears accumulated data for specified markdown services without unsubscribing.
48677
+ * Use this method to reset report data for specific services while keeping them active.
48678
+ *
48679
+ * Each cleared service will:
48680
+ * - Clear accumulated data for all reports
48681
+ * - Start fresh with new data for future events
48682
+ * - Not affect event subscriptions or report generation status
48683
+ *
48684
+ * @param config - Service configuration object specifying which services to clear. Defaults to clearing all services.
48685
+ * @param config.backtest - Clear backtest result report data
48686
+ * @param config.breakeven - Clear breakeven event tracking data
48687
+ * @param config.partial - Clear partial profit/loss event tracking data
48688
+ * @param config.heat - Clear portfolio heatmap analysis data
48689
+ * @param config.walker - Clear walker strategy comparison report data
48690
+ * @param config.performance - Clear performance bottleneck analysis data
48691
+ * @param config.risk - Clear risk rejection tracking data
48692
+ * @param config.schedule - Clear scheduled signal tracking data
48693
+ * @param config.live - Clear live trading event report data
48694
+ * @param config.strategy - Clear strategy report data
48695
+ * @param config.sync - Clear sync report data
48696
+ * @param config.highest_profit - Clear highest profit report data
48697
+ * @param config.max_drawdown - Clear max drawdown report data
48698
+ */
48699
+ this.clear = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, strategy = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET) => {
48700
+ LOGGER_SERVICE$1.debug(MARKDOWN_METHOD_NAME_CLEAR, {
48701
+ backtest: bt,
48702
+ breakeven,
48703
+ heat,
48704
+ live,
48705
+ partial,
48706
+ performance,
48707
+ risk,
48708
+ strategy,
48709
+ schedule,
48710
+ walker,
48711
+ sync,
48712
+ highest_profit,
48713
+ });
48714
+ if (bt) {
48715
+ backtest.backtestMarkdownService.clear();
48716
+ }
48717
+ if (breakeven) {
48718
+ backtest.breakevenMarkdownService.clear();
48719
+ }
48720
+ if (heat) {
48721
+ backtest.heatMarkdownService.clear();
48722
+ }
48723
+ if (live) {
48724
+ backtest.liveMarkdownService.clear();
48725
+ }
48726
+ if (partial) {
48727
+ backtest.partialMarkdownService.clear();
48728
+ }
48729
+ if (performance) {
48730
+ backtest.performanceMarkdownService.clear();
48731
+ }
48732
+ if (risk) {
48733
+ backtest.riskMarkdownService.clear();
48734
+ }
48735
+ if (strategy) {
48736
+ backtest.strategyMarkdownService.clear();
48737
+ }
48738
+ if (schedule) {
48739
+ backtest.scheduleMarkdownService.clear();
48740
+ }
48741
+ if (walker) {
48742
+ backtest.walkerMarkdownService.clear();
48743
+ }
48744
+ if (sync) {
48745
+ backtest.syncMarkdownService.clear();
48746
+ }
48747
+ if (highest_profit) {
48748
+ backtest.highestProfitMarkdownService.clear();
48749
+ }
48750
+ if (max_drawdown) {
48751
+ backtest.maxDrawdownMarkdownService.clear();
48752
+ }
48753
+ };
48391
48754
  }
48392
48755
  }
48393
48756
  /**
@@ -48430,15 +48793,6 @@ class MarkdownAdapter extends MarkdownUtils {
48430
48793
  LOGGER_SERVICE$1.debug(MARKDOWN_METHOD_NAME_USE_JSONL);
48431
48794
  MarkdownWriter.useJsonl();
48432
48795
  }
48433
- /**
48434
- * Clears the memoized storage cache.
48435
- * Call this when process.cwd() changes between strategy iterations
48436
- * so new storage instances are created with the updated base path.
48437
- */
48438
- clear() {
48439
- LOGGER_SERVICE$1.log(MARKDOWN_METHOD_NAME_CLEAR);
48440
- MarkdownWriter.clear();
48441
- }
48442
48796
  /**
48443
48797
  * Switches to a dummy markdown adapter that discards all writes.
48444
48798
  * All future markdown writes will be no-ops.
@@ -49135,6 +49489,7 @@ const SUBJECT_ISOLATION_LIST = [
49135
49489
  strategyCommitSubject,
49136
49490
  syncSubject,
49137
49491
  validationSubject,
49492
+ signalNotifySubject,
49138
49493
  ];
49139
49494
  /**
49140
49495
  * Creates a snapshot function for a given subject by clearing its internal
@@ -53980,7 +54335,44 @@ const CREATE_VALIDATION_ERROR_NOTIFICATION_FN = (error) => ({
53980
54335
  message: functoolsKit.getErrorMessage(error),
53981
54336
  backtest: false,
53982
54337
  });
54338
+ /**
54339
+ * Creates a notification model for signal info events.
54340
+ * @param data - The signal info contract data
54341
+ * @returns NotificationModel for signal info event
54342
+ */
54343
+ const CREATE_SIGNAL_INFO_NOTIFICATION_FN = (data) => ({
54344
+ type: "signal.info",
54345
+ id: CREATE_KEY_FN$2(),
54346
+ timestamp: data.timestamp,
54347
+ backtest: data.backtest,
54348
+ symbol: data.symbol,
54349
+ strategyName: data.strategyName,
54350
+ exchangeName: data.exchangeName,
54351
+ signalId: data.data.id,
54352
+ currentPrice: data.currentPrice,
54353
+ position: data.data.position,
54354
+ priceOpen: data.data.priceOpen,
54355
+ priceTakeProfit: data.data.priceTakeProfit,
54356
+ priceStopLoss: data.data.priceStopLoss,
54357
+ originalPriceTakeProfit: data.data.originalPriceTakeProfit,
54358
+ originalPriceStopLoss: data.data.originalPriceStopLoss,
54359
+ originalPriceOpen: data.data.originalPriceOpen,
54360
+ totalEntries: data.data.totalEntries,
54361
+ totalPartials: data.data.totalPartials,
54362
+ pnl: data.data.pnl,
54363
+ pnlPercentage: data.data.pnl.pnlPercentage,
54364
+ pnlPriceOpen: data.data.pnl.priceOpen,
54365
+ pnlPriceClose: data.data.pnl.priceClose,
54366
+ pnlCost: data.data.pnl.pnlCost,
54367
+ pnlEntries: data.data.pnl.pnlEntries,
54368
+ note: data.note,
54369
+ notificationId: data.notificationId,
54370
+ scheduledAt: data.data.scheduledAt,
54371
+ pendingAt: data.data.pendingAt,
54372
+ createdAt: data.timestamp,
54373
+ });
53983
54374
  const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL = "NotificationMemoryBacktestUtils.handleSignal";
54375
+ const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationMemoryBacktestUtils.handleSignalNotify";
53984
54376
  const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationMemoryBacktestUtils.handlePartialProfit";
53985
54377
  const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationMemoryBacktestUtils.handlePartialLoss";
53986
54378
  const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationMemoryBacktestUtils.handleBreakeven";
@@ -53993,6 +54385,7 @@ const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_VALIDATION_ERROR = "Notifi
53993
54385
  const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_GET_DATA = "NotificationMemoryBacktestUtils.getData";
53994
54386
  const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_DISPOSE = "NotificationMemoryBacktestUtils.dispose";
53995
54387
  const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL = "NotificationMemoryLiveUtils.handleSignal";
54388
+ const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationMemoryLiveUtils.handleSignalNotify";
53996
54389
  const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationMemoryLiveUtils.handlePartialProfit";
53997
54390
  const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationMemoryLiveUtils.handlePartialLoss";
53998
54391
  const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationMemoryLiveUtils.handleBreakeven";
@@ -54021,6 +54414,7 @@ const NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_CLEAR = "NotificationLiveAdapter.cle
54021
54414
  const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "NotificationPersistBacktestUtils.waitForInit";
54022
54415
  const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_UPDATE_NOTIFICATIONS = "NotificationPersistBacktestUtils._updateNotifications";
54023
54416
  const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL = "NotificationPersistBacktestUtils.handleSignal";
54417
+ const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationPersistBacktestUtils.handleSignalNotify";
54024
54418
  const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationPersistBacktestUtils.handlePartialProfit";
54025
54419
  const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationPersistBacktestUtils.handlePartialLoss";
54026
54420
  const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationPersistBacktestUtils.handleBreakeven";
@@ -54035,6 +54429,7 @@ const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_DISPOSE = "NotificationPersistBa
54035
54429
  const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_WAIT_FOR_INIT = "NotificationPersistLiveUtils.waitForInit";
54036
54430
  const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_UPDATE_NOTIFICATIONS = "NotificationPersistLiveUtils._updateNotifications";
54037
54431
  const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL = "NotificationPersistLiveUtils.handleSignal";
54432
+ const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationPersistLiveUtils.handleSignalNotify";
54038
54433
  const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationPersistLiveUtils.handlePartialProfit";
54039
54434
  const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationPersistLiveUtils.handlePartialLoss";
54040
54435
  const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationPersistLiveUtils.handleBreakeven";
@@ -54077,6 +54472,12 @@ class NotificationMemoryBacktestUtils {
54077
54472
  this._addNotification(notification);
54078
54473
  }
54079
54474
  };
54475
+ this.handleSignalNotify = async (data) => {
54476
+ backtest.loggerService.info(NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
54477
+ signalId: data.data.id,
54478
+ });
54479
+ this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
54480
+ };
54080
54481
  /**
54081
54482
  * Handles partial profit availability event.
54082
54483
  * @param data - The partial profit contract data
@@ -54221,6 +54622,8 @@ class NotificationDummyBacktestUtils {
54221
54622
  */
54222
54623
  this.handleSignal = async () => {
54223
54624
  };
54625
+ this.handleSignalNotify = async () => {
54626
+ };
54224
54627
  /**
54225
54628
  * No-op handler for partial profit event.
54226
54629
  */
@@ -54328,6 +54731,14 @@ class NotificationPersistBacktestUtils {
54328
54731
  await this._updateNotifications();
54329
54732
  }
54330
54733
  };
54734
+ this.handleSignalNotify = async (data) => {
54735
+ backtest.loggerService.info(NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
54736
+ signalId: data.data.id,
54737
+ });
54738
+ await this.waitForInit();
54739
+ this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
54740
+ await this._updateNotifications();
54741
+ };
54331
54742
  /**
54332
54743
  * Handles partial profit availability event.
54333
54744
  * @param data - The partial profit contract data
@@ -54529,6 +54940,12 @@ class NotificationMemoryLiveUtils {
54529
54940
  this._addNotification(notification);
54530
54941
  }
54531
54942
  };
54943
+ this.handleSignalNotify = async (data) => {
54944
+ backtest.loggerService.info(NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
54945
+ signalId: data.data.id,
54946
+ });
54947
+ this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
54948
+ };
54532
54949
  /**
54533
54950
  * Handles partial profit availability event.
54534
54951
  * @param data - The partial profit contract data
@@ -54673,6 +55090,8 @@ class NotificationDummyLiveUtils {
54673
55090
  */
54674
55091
  this.handleSignal = async () => {
54675
55092
  };
55093
+ this.handleSignalNotify = async () => {
55094
+ };
54676
55095
  /**
54677
55096
  * No-op handler for partial profit event.
54678
55097
  */
@@ -54781,6 +55200,14 @@ class NotificationPersistLiveUtils {
54781
55200
  await this._updateNotifications();
54782
55201
  }
54783
55202
  };
55203
+ this.handleSignalNotify = async (data) => {
55204
+ backtest.loggerService.info(NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
55205
+ signalId: data.data.id,
55206
+ });
55207
+ await this.waitForInit();
55208
+ this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
55209
+ await this._updateNotifications();
55210
+ };
54784
55211
  /**
54785
55212
  * Handles partial profit availability event.
54786
55213
  * @param data - The partial profit contract data
@@ -54974,6 +55401,9 @@ class NotificationBacktestAdapter {
54974
55401
  this.handleSignal = async (data) => {
54975
55402
  return await this._notificationBacktestUtils.handleSignal(data);
54976
55403
  };
55404
+ this.handleSignalNotify = async (data) => {
55405
+ return await this._notificationBacktestUtils.handleSignalNotify(data);
55406
+ };
54977
55407
  /**
54978
55408
  * Handles partial profit availability event.
54979
55409
  * Proxies call to the underlying notification adapter.
@@ -55129,6 +55559,9 @@ class NotificationLiveAdapter {
55129
55559
  this.handleSignal = async (data) => {
55130
55560
  return await this._notificationLiveUtils.handleSignal(data);
55131
55561
  };
55562
+ this.handleSignalNotify = async (data) => {
55563
+ return await this._notificationLiveUtils.handleSignalNotify(data);
55564
+ };
55132
55565
  /**
55133
55566
  * Handles partial profit availability event.
55134
55567
  * Proxies call to the underlying notification adapter.
@@ -55307,7 +55740,10 @@ class NotificationAdapter {
55307
55740
  const unBacktestError = errorEmitter.subscribe((error) => NotificationBacktest.handleError(error));
55308
55741
  const unBacktestExit = exitEmitter.subscribe((error) => NotificationBacktest.handleCriticalError(error));
55309
55742
  const unBacktestValidation = validationSubject.subscribe((error) => NotificationBacktest.handleValidationError(error));
55310
- unBacktest = functoolsKit.compose(() => unBacktestSignal(), () => unBacktestPartialProfit(), () => unBacktestPartialLoss(), () => unBacktestBreakeven(), () => unBacktestStrategyCommit(), () => unBacktestSync(), () => unBacktestRisk(), () => unBacktestError(), () => unBacktestExit(), () => unBacktestValidation());
55743
+ const unBacktestSignalNotify = signalNotifySubject
55744
+ .filter(({ backtest }) => backtest)
55745
+ .connect((data) => NotificationBacktest.handleSignalNotify(data));
55746
+ unBacktest = functoolsKit.compose(() => unBacktestSignal(), () => unBacktestPartialProfit(), () => unBacktestPartialLoss(), () => unBacktestBreakeven(), () => unBacktestStrategyCommit(), () => unBacktestSync(), () => unBacktestRisk(), () => unBacktestError(), () => unBacktestExit(), () => unBacktestValidation(), () => unBacktestSignalNotify());
55311
55747
  }
55312
55748
  {
55313
55749
  const unLiveSignal = signalLiveEmitter.subscribe((data) => NotificationLive.handleSignal(data));
@@ -55332,7 +55768,10 @@ class NotificationAdapter {
55332
55768
  const unLiveError = errorEmitter.subscribe((error) => NotificationLive.handleError(error));
55333
55769
  const unLiveExit = exitEmitter.subscribe((error) => NotificationLive.handleCriticalError(error));
55334
55770
  const unLiveValidation = validationSubject.subscribe((error) => NotificationLive.handleValidationError(error));
55335
- unLive = functoolsKit.compose(() => unLiveSignal(), () => unLivePartialProfit(), () => unLivePartialLoss(), () => unLiveBreakeven(), () => unLiveStrategyCommit(), () => unLiveSync(), () => unLiveRisk(), () => unLiveError(), () => unLiveExit(), () => unLiveValidation());
55771
+ const unLiveSignalNotify = signalNotifySubject
55772
+ .filter(({ backtest }) => !backtest)
55773
+ .connect((data) => NotificationLive.handleSignalNotify(data));
55774
+ unLive = functoolsKit.compose(() => unLiveSignal(), () => unLivePartialProfit(), () => unLivePartialLoss(), () => unLiveBreakeven(), () => unLiveStrategyCommit(), () => unLiveSync(), () => unLiveRisk(), () => unLiveError(), () => unLiveExit(), () => unLiveValidation(), () => unLiveSignalNotify());
55336
55775
  }
55337
55776
  return () => {
55338
55777
  unLive();
@@ -55570,11 +56009,17 @@ class CacheFnInstance {
55570
56009
  return cached;
55571
56010
  }
55572
56011
  }
56012
+ const value = this.fn(...args);
55573
56013
  const newCache = {
55574
56014
  when: currentWhen,
55575
- value: this.fn(...args),
56015
+ value,
55576
56016
  };
55577
56017
  this._cacheMap.set(key, newCache);
56018
+ if (value && value instanceof Promise) {
56019
+ value.catch(() => {
56020
+ this._cacheMap.delete(key);
56021
+ });
56022
+ }
55578
56023
  return newCache;
55579
56024
  };
55580
56025
  /**
@@ -56155,7 +56600,7 @@ class IntervalFnInstance {
56155
56600
  * within the same interval or when `fn` itself returned `null`
56156
56601
  * @throws Error if method context, execution context, or interval is missing
56157
56602
  */
56158
- this.run = async (...args) => {
56603
+ this.run = (...args) => {
56159
56604
  backtest.loggerService.debug(INTERVAL_METHOD_NAME_RUN, { args });
56160
56605
  const step = INTERVAL_MINUTES[this.interval];
56161
56606
  {
@@ -56177,10 +56622,15 @@ class IntervalFnInstance {
56177
56622
  if (this._stateMap.get(stateKey) === currentAligned) {
56178
56623
  return null;
56179
56624
  }
56180
- const result = await this.fn.apply(null, args);
56625
+ const result = this.fn.apply(null, args);
56181
56626
  if (result !== null) {
56182
56627
  this._stateMap.set(stateKey, currentAligned);
56183
56628
  }
56629
+ if (result && result instanceof Promise) {
56630
+ result.catch(() => {
56631
+ this._stateMap.delete(stateKey);
56632
+ });
56633
+ }
56184
56634
  return result;
56185
56635
  };
56186
56636
  /**
@@ -57788,6 +58238,7 @@ exports.commitPartialLoss = commitPartialLoss;
57788
58238
  exports.commitPartialLossCost = commitPartialLossCost;
57789
58239
  exports.commitPartialProfit = commitPartialProfit;
57790
58240
  exports.commitPartialProfitCost = commitPartialProfitCost;
58241
+ exports.commitSignalNotify = commitSignalNotify;
57791
58242
  exports.commitTrailingStop = commitTrailingStop;
57792
58243
  exports.commitTrailingStopCost = commitTrailingStopCost;
57793
58244
  exports.commitTrailingTake = commitTrailingTake;
@@ -57906,6 +58357,8 @@ exports.listenSignalBacktest = listenSignalBacktest;
57906
58357
  exports.listenSignalBacktestOnce = listenSignalBacktestOnce;
57907
58358
  exports.listenSignalLive = listenSignalLive;
57908
58359
  exports.listenSignalLiveOnce = listenSignalLiveOnce;
58360
+ exports.listenSignalNotify = listenSignalNotify;
58361
+ exports.listenSignalNotifyOnce = listenSignalNotifyOnce;
57909
58362
  exports.listenSignalOnce = listenSignalOnce;
57910
58363
  exports.listenStrategyCommit = listenStrategyCommit;
57911
58364
  exports.listenStrategyCommitOnce = listenStrategyCommitOnce;