backtest-kit 1.6.4 → 1.6.6

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.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;
@@ -3766,7 +3777,7 @@ const GET_RISK_FN = (dto, backtest, self) => {
3766
3777
  * @param backtest - Whether running in backtest mode
3767
3778
  * @returns Unique string key for memoization
3768
3779
  */
3769
- const CREATE_KEY_FN$9 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
3780
+ const CREATE_KEY_FN$b = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
3770
3781
  /**
3771
3782
  * Callback function for emitting ping events to pingSubject.
3772
3783
  *
@@ -3827,7 +3838,7 @@ class StrategyConnectionService {
3827
3838
  * @param strategyName - Name of registered strategy schema
3828
3839
  * @returns Configured ClientStrategy instance
3829
3840
  */
3830
- this.getStrategy = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$9(symbol, strategyName, backtest), (symbol, strategyName, backtest) => {
3841
+ this.getStrategy = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$b(symbol, strategyName, backtest), (symbol, strategyName, backtest) => {
3831
3842
  const { riskName = "", riskList = [], getSignal, interval, callbacks, } = this.strategySchemaService.get(strategyName);
3832
3843
  return new ClientStrategy({
3833
3844
  symbol,
@@ -3994,7 +4005,7 @@ class StrategyConnectionService {
3994
4005
  ctx,
3995
4006
  });
3996
4007
  if (ctx) {
3997
- const key = CREATE_KEY_FN$9(ctx.symbol, ctx.strategyName, backtest);
4008
+ const key = CREATE_KEY_FN$b(ctx.symbol, ctx.strategyName, backtest);
3998
4009
  this.getStrategy.clear(key);
3999
4010
  }
4000
4011
  else {
@@ -4604,7 +4615,7 @@ class ClientRisk {
4604
4615
  * @param backtest - Whether running in backtest mode
4605
4616
  * @returns Unique string key for memoization
4606
4617
  */
4607
- const CREATE_KEY_FN$8 = (riskName, backtest) => `${riskName}:${backtest ? "backtest" : "live"}`;
4618
+ const CREATE_KEY_FN$a = (riskName, backtest) => `${riskName}:${backtest ? "backtest" : "live"}`;
4608
4619
  /**
4609
4620
  * Callback function for emitting risk rejection events to riskSubject.
4610
4621
  *
@@ -4676,7 +4687,7 @@ class RiskConnectionService {
4676
4687
  * @param backtest - True if backtest mode, false if live mode
4677
4688
  * @returns Configured ClientRisk instance
4678
4689
  */
4679
- this.getRisk = memoize(([riskName, backtest]) => CREATE_KEY_FN$8(riskName, backtest), (riskName, backtest) => {
4690
+ this.getRisk = memoize(([riskName, backtest]) => CREATE_KEY_FN$a(riskName, backtest), (riskName, backtest) => {
4680
4691
  const schema = this.riskSchemaService.get(riskName);
4681
4692
  return new ClientRisk({
4682
4693
  ...schema,
@@ -4743,7 +4754,7 @@ class RiskConnectionService {
4743
4754
  backtest,
4744
4755
  });
4745
4756
  if (ctx) {
4746
- const key = CREATE_KEY_FN$8(ctx.riskName, backtest);
4757
+ const key = CREATE_KEY_FN$a(ctx.riskName, backtest);
4747
4758
  this.getRisk.clear(key);
4748
4759
  }
4749
4760
  else {
@@ -4976,9 +4987,6 @@ class StrategyCoreService {
4976
4987
  symbol,
4977
4988
  strategyName,
4978
4989
  });
4979
- if (!MethodContextService.hasContext()) {
4980
- throw new Error("strategyCoreService getPendingSignal requires a method context");
4981
- }
4982
4990
  await this.validate(symbol, strategyName);
4983
4991
  return await this.strategyConnectionService.getPendingSignal(backtest, symbol, strategyName);
4984
4992
  };
@@ -4996,9 +5004,6 @@ class StrategyCoreService {
4996
5004
  symbol,
4997
5005
  strategyName,
4998
5006
  });
4999
- if (!MethodContextService.hasContext()) {
5000
- throw new Error("strategyCoreService getScheduledSignal requires a method context");
5001
- }
5002
5007
  await this.validate(symbol, strategyName);
5003
5008
  return await this.strategyConnectionService.getScheduledSignal(backtest, symbol, strategyName);
5004
5009
  };
@@ -5018,9 +5023,6 @@ class StrategyCoreService {
5018
5023
  strategyName,
5019
5024
  backtest,
5020
5025
  });
5021
- if (!MethodContextService.hasContext()) {
5022
- throw new Error("strategyCoreService getStopped requires a method context");
5023
- }
5024
5026
  await this.validate(symbol, strategyName);
5025
5027
  return await this.strategyConnectionService.getStopped(backtest, symbol, strategyName);
5026
5028
  };
@@ -7791,7 +7793,7 @@ const DEFAULT_COLUMNS = Object.freeze({ ...COLUMN_CONFIG });
7791
7793
  * @param backtest - Whether running in backtest mode
7792
7794
  * @returns Unique string key for memoization
7793
7795
  */
7794
- const CREATE_KEY_FN$7 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
7796
+ const CREATE_KEY_FN$9 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
7795
7797
  /**
7796
7798
  * Checks if a value is unsafe for display (not a number, NaN, or Infinity).
7797
7799
  *
@@ -8000,7 +8002,7 @@ class BacktestMarkdownService {
8000
8002
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
8001
8003
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
8002
8004
  */
8003
- this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$7(symbol, strategyName, backtest), () => new ReportStorage$5());
8005
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$9(symbol, strategyName, backtest), () => new ReportStorage$5());
8004
8006
  /**
8005
8007
  * Processes tick events and accumulates closed signals.
8006
8008
  * Should be called from IStrategyCallbacks.onTick.
@@ -8138,7 +8140,7 @@ class BacktestMarkdownService {
8138
8140
  ctx,
8139
8141
  });
8140
8142
  if (ctx) {
8141
- const key = CREATE_KEY_FN$7(ctx.symbol, ctx.strategyName, backtest);
8143
+ const key = CREATE_KEY_FN$9(ctx.symbol, ctx.strategyName, backtest);
8142
8144
  this.getStorage.clear(key);
8143
8145
  }
8144
8146
  else {
@@ -8171,7 +8173,7 @@ class BacktestMarkdownService {
8171
8173
  * @param backtest - Whether running in backtest mode
8172
8174
  * @returns Unique string key for memoization
8173
8175
  */
8174
- const CREATE_KEY_FN$6 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
8176
+ const CREATE_KEY_FN$8 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
8175
8177
  /**
8176
8178
  * Checks if a value is unsafe for display (not a number, NaN, or Infinity).
8177
8179
  *
@@ -8501,7 +8503,7 @@ class LiveMarkdownService {
8501
8503
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
8502
8504
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
8503
8505
  */
8504
- this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$6(symbol, strategyName, backtest), () => new ReportStorage$4());
8506
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$8(symbol, strategyName, backtest), () => new ReportStorage$4());
8505
8507
  /**
8506
8508
  * Processes tick events and accumulates all event types.
8507
8509
  * Should be called from IStrategyCallbacks.onTick.
@@ -8649,7 +8651,7 @@ class LiveMarkdownService {
8649
8651
  ctx,
8650
8652
  });
8651
8653
  if (ctx) {
8652
- const key = CREATE_KEY_FN$6(ctx.symbol, ctx.strategyName, backtest);
8654
+ const key = CREATE_KEY_FN$8(ctx.symbol, ctx.strategyName, backtest);
8653
8655
  this.getStorage.clear(key);
8654
8656
  }
8655
8657
  else {
@@ -8682,7 +8684,7 @@ class LiveMarkdownService {
8682
8684
  * @param backtest - Whether running in backtest mode
8683
8685
  * @returns Unique string key for memoization
8684
8686
  */
8685
- const CREATE_KEY_FN$5 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
8687
+ const CREATE_KEY_FN$7 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
8686
8688
  /** Maximum number of events to store in schedule reports */
8687
8689
  const MAX_EVENTS$4 = 250;
8688
8690
  /**
@@ -8918,7 +8920,7 @@ class ScheduleMarkdownService {
8918
8920
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
8919
8921
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
8920
8922
  */
8921
- this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$5(symbol, strategyName, backtest), () => new ReportStorage$3());
8923
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$7(symbol, strategyName, backtest), () => new ReportStorage$3());
8922
8924
  /**
8923
8925
  * Processes tick events and accumulates scheduled/opened/cancelled events.
8924
8926
  * Should be called from signalEmitter subscription.
@@ -9060,7 +9062,7 @@ class ScheduleMarkdownService {
9060
9062
  ctx,
9061
9063
  });
9062
9064
  if (ctx) {
9063
- const key = CREATE_KEY_FN$5(ctx.symbol, ctx.strategyName, backtest);
9065
+ const key = CREATE_KEY_FN$7(ctx.symbol, ctx.strategyName, backtest);
9064
9066
  this.getStorage.clear(key);
9065
9067
  }
9066
9068
  else {
@@ -9093,7 +9095,7 @@ class ScheduleMarkdownService {
9093
9095
  * @param backtest - Whether running in backtest mode
9094
9096
  * @returns Unique string key for memoization
9095
9097
  */
9096
- const CREATE_KEY_FN$4 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
9098
+ const CREATE_KEY_FN$6 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
9097
9099
  /**
9098
9100
  * Calculates percentile value from sorted array.
9099
9101
  */
@@ -9311,7 +9313,7 @@ class PerformanceMarkdownService {
9311
9313
  * Memoized function to get or create PerformanceStorage for a symbol-strategy-backtest triple.
9312
9314
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
9313
9315
  */
9314
- this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$4(symbol, strategyName, backtest), () => new PerformanceStorage());
9316
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$6(symbol, strategyName, backtest), () => new PerformanceStorage());
9315
9317
  /**
9316
9318
  * Processes performance events and accumulates metrics.
9317
9319
  * Should be called from performance tracking code.
@@ -9416,7 +9418,7 @@ class PerformanceMarkdownService {
9416
9418
  ctx,
9417
9419
  });
9418
9420
  if (ctx) {
9419
- const key = CREATE_KEY_FN$4(ctx.symbol, ctx.strategyName, backtest);
9421
+ const key = CREATE_KEY_FN$6(ctx.symbol, ctx.strategyName, backtest);
9420
9422
  this.getStorage.clear(key);
9421
9423
  }
9422
9424
  else {
@@ -9850,7 +9852,7 @@ class WalkerMarkdownService {
9850
9852
  * @param backtest - Whether running in backtest mode
9851
9853
  * @returns Unique string key for memoization
9852
9854
  */
9853
- const CREATE_KEY_FN$3 = (strategyName, backtest) => `${strategyName}:${backtest ? "backtest" : "live"}`;
9855
+ const CREATE_KEY_FN$5 = (strategyName, backtest) => `${strategyName}:${backtest ? "backtest" : "live"}`;
9854
9856
  const HEATMAP_METHOD_NAME_GET_DATA = "HeatMarkdownService.getData";
9855
9857
  const HEATMAP_METHOD_NAME_GET_REPORT = "HeatMarkdownService.getReport";
9856
9858
  const HEATMAP_METHOD_NAME_DUMP = "HeatMarkdownService.dump";
@@ -10194,7 +10196,7 @@ class HeatMarkdownService {
10194
10196
  * Memoized function to get or create HeatmapStorage for a strategy and backtest mode.
10195
10197
  * Each strategy + backtest mode combination gets its own isolated heatmap storage instance.
10196
10198
  */
10197
- this.getStorage = memoize(([strategyName, backtest]) => CREATE_KEY_FN$3(strategyName, backtest), () => new HeatmapStorage());
10199
+ this.getStorage = memoize(([strategyName, backtest]) => CREATE_KEY_FN$5(strategyName, backtest), () => new HeatmapStorage());
10198
10200
  /**
10199
10201
  * Processes tick events and accumulates closed signals.
10200
10202
  * Should be called from signal emitter subscription.
@@ -10330,7 +10332,7 @@ class HeatMarkdownService {
10330
10332
  ctx,
10331
10333
  });
10332
10334
  if (ctx) {
10333
- const key = CREATE_KEY_FN$3(ctx.strategyName, backtest);
10335
+ const key = CREATE_KEY_FN$5(ctx.strategyName, backtest);
10334
10336
  this.getStorage.clear(key);
10335
10337
  }
10336
10338
  else {
@@ -12548,7 +12550,7 @@ class ClientPartial {
12548
12550
  * @param backtest - Whether running in backtest mode
12549
12551
  * @returns Unique string key for memoization
12550
12552
  */
12551
- const CREATE_KEY_FN$2 = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
12553
+ const CREATE_KEY_FN$4 = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
12552
12554
  /**
12553
12555
  * Callback function for emitting profit events to partialProfitSubject.
12554
12556
  *
@@ -12646,7 +12648,7 @@ class PartialConnectionService {
12646
12648
  * Key format: "signalId:backtest" or "signalId:live"
12647
12649
  * Value: ClientPartial instance with logger and event emitters
12648
12650
  */
12649
- this.getPartial = memoize(([signalId, backtest]) => CREATE_KEY_FN$2(signalId, backtest), (signalId, backtest) => {
12651
+ this.getPartial = memoize(([signalId, backtest]) => CREATE_KEY_FN$4(signalId, backtest), (signalId, backtest) => {
12650
12652
  return new ClientPartial({
12651
12653
  signalId,
12652
12654
  logger: this.loggerService,
@@ -12736,7 +12738,7 @@ class PartialConnectionService {
12736
12738
  const partial = this.getPartial(data.id, backtest);
12737
12739
  await partial.waitForInit(symbol, data.strategyName);
12738
12740
  await partial.clear(symbol, data, priceClose, backtest);
12739
- const key = CREATE_KEY_FN$2(data.id, backtest);
12741
+ const key = CREATE_KEY_FN$4(data.id, backtest);
12740
12742
  this.getPartial.clear(key);
12741
12743
  };
12742
12744
  }
@@ -12748,7 +12750,7 @@ class PartialConnectionService {
12748
12750
  * @param param0 - Tuple of symbol, strategyName and backtest boolean
12749
12751
  * @returns Unique string key for memoization
12750
12752
  */
12751
- const CREATE_KEY_FN$1 = ([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
12753
+ const CREATE_KEY_FN$3 = ([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
12752
12754
  /** Maximum number of events to store in partial reports */
12753
12755
  const MAX_EVENTS$1 = 250;
12754
12756
  /**
@@ -12923,7 +12925,7 @@ class PartialMarkdownService {
12923
12925
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
12924
12926
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
12925
12927
  */
12926
- this.getStorage = memoize(CREATE_KEY_FN$1, () => new ReportStorage$1());
12928
+ this.getStorage = memoize(CREATE_KEY_FN$3, () => new ReportStorage$1());
12927
12929
  /**
12928
12930
  * Processes profit events and accumulates them.
12929
12931
  * Should be called from partialProfitSubject subscription.
@@ -13070,7 +13072,7 @@ class PartialMarkdownService {
13070
13072
  ctx,
13071
13073
  });
13072
13074
  if (ctx) {
13073
- const key = CREATE_KEY_FN$1([ctx.symbol, ctx.strategyName, backtest]);
13075
+ const key = CREATE_KEY_FN$3([ctx.symbol, ctx.strategyName, backtest]);
13074
13076
  this.getStorage.clear(key);
13075
13077
  }
13076
13078
  else {
@@ -13513,7 +13515,7 @@ class ConfigValidationService {
13513
13515
  * @param backtest - Whether running in backtest mode
13514
13516
  * @returns Unique string key for memoization
13515
13517
  */
13516
- const CREATE_KEY_FN = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
13518
+ const CREATE_KEY_FN$2 = (symbol, strategyName, backtest) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`;
13517
13519
  /** Maximum number of events to store in risk reports */
13518
13520
  const MAX_EVENTS = 250;
13519
13521
  /**
@@ -13658,7 +13660,7 @@ class RiskMarkdownService {
13658
13660
  * Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
13659
13661
  * Each symbol-strategy-backtest combination gets its own isolated storage instance.
13660
13662
  */
13661
- this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN(symbol, strategyName, backtest), () => new ReportStorage());
13663
+ this.getStorage = memoize(([symbol, strategyName, backtest]) => CREATE_KEY_FN$2(symbol, strategyName, backtest), () => new ReportStorage());
13662
13664
  /**
13663
13665
  * Processes risk rejection events and accumulates them.
13664
13666
  * Should be called from riskSubject subscription.
@@ -13786,7 +13788,7 @@ class RiskMarkdownService {
13786
13788
  ctx,
13787
13789
  });
13788
13790
  if (ctx) {
13789
- const key = CREATE_KEY_FN(ctx.symbol, ctx.strategyName, backtest);
13791
+ const key = CREATE_KEY_FN$2(ctx.symbol, ctx.strategyName, backtest);
13790
13792
  this.getStorage.clear(key);
13791
13793
  }
13792
13794
  else {
@@ -19498,7 +19500,15 @@ const INTERVAL_MINUTES = {
19498
19500
  "6h": 360,
19499
19501
  "8h": 480,
19500
19502
  };
19501
- const createKey = (strategyName, exchangeName, backtest) => `${strategyName}:${exchangeName}:${backtest ? "backtest" : "live"}`;
19503
+ /**
19504
+ * Create a cache key string from strategy name, exchange name, and backtest mode.
19505
+ *
19506
+ * @param strategyName - Name of the strategy
19507
+ * @param exchangeName - Name of the exchange
19508
+ * @param backtest - Whether running in backtest mode
19509
+ * @returns Cache key string
19510
+ */
19511
+ const CREATE_KEY_FN$1 = (strategyName, exchangeName, backtest) => `${strategyName}:${exchangeName}:${backtest ? "backtest" : "live"}`;
19502
19512
  /**
19503
19513
  * Instance class for caching function results with timeframe-based invalidation.
19504
19514
  *
@@ -19574,7 +19584,7 @@ class CacheInstance {
19574
19584
  throw new Error(`CacheInstance unknown cache ttl interval=${this.interval}`);
19575
19585
  }
19576
19586
  }
19577
- const key = createKey(backtest$1.methodContextService.context.strategyName, backtest$1.methodContextService.context.exchangeName, backtest$1.executionContextService.context.backtest);
19587
+ const key = CREATE_KEY_FN$1(backtest$1.methodContextService.context.strategyName, backtest$1.methodContextService.context.exchangeName, backtest$1.executionContextService.context.backtest);
19578
19588
  const currentWhen = backtest$1.executionContextService.context.when;
19579
19589
  const cached = this._cacheMap.get(key);
19580
19590
  if (cached) {
@@ -19612,7 +19622,7 @@ class CacheInstance {
19612
19622
  * ```
19613
19623
  */
19614
19624
  this.clear = () => {
19615
- const key = createKey(backtest$1.methodContextService.context.strategyName, backtest$1.methodContextService.context.exchangeName, backtest$1.executionContextService.context.backtest);
19625
+ const key = CREATE_KEY_FN$1(backtest$1.methodContextService.context.strategyName, backtest$1.methodContextService.context.exchangeName, backtest$1.executionContextService.context.backtest);
19616
19626
  this._cacheMap.delete(key);
19617
19627
  };
19618
19628
  }
@@ -19760,4 +19770,438 @@ class CacheUtils {
19760
19770
  */
19761
19771
  const Cache = new CacheUtils();
19762
19772
 
19763
- export { Backtest, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, MethodContextService, Optimizer, Partial, Performance, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, Risk, Schedule, Walker, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, cancel, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenPing, listenPingOnce, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setColumns, setConfig, setLogger, stop, validate };
19773
+ /** Maximum number of notifications to store in history */
19774
+ const MAX_NOTIFICATIONS = 250;
19775
+ /** Function to create unique notification IDs */
19776
+ const CREATE_KEY_FN = () => randomString();
19777
+ /**
19778
+ * Instance class for notification history management.
19779
+ *
19780
+ * Contains all business logic for notification collection from emitters/subjects.
19781
+ * Stores notifications in chronological order with automatic limit management.
19782
+ *
19783
+ * @example
19784
+ * ```typescript
19785
+ * const instance = new NotificationInstance();
19786
+ * await instance.waitForInit();
19787
+ *
19788
+ * // Get all notifications
19789
+ * const all = instance.getData();
19790
+ *
19791
+ * // Process notifications with type discrimination
19792
+ * all.forEach(notification => {
19793
+ * switch (notification.type) {
19794
+ * case "signal.closed":
19795
+ * console.log(`Closed: ${notification.pnlPercentage}%`);
19796
+ * break;
19797
+ * case "partial.loss":
19798
+ * if (notification.level >= 30) {
19799
+ * alert("High loss!");
19800
+ * }
19801
+ * break;
19802
+ * case "risk.rejection":
19803
+ * console.warn(notification.rejectionNote);
19804
+ * break;
19805
+ * }
19806
+ * });
19807
+ *
19808
+ * // Clear history
19809
+ * instance.clear();
19810
+ * ```
19811
+ */
19812
+ class NotificationInstance {
19813
+ constructor() {
19814
+ /** Internal notification history storage (newest first) */
19815
+ this._notifications = [];
19816
+ /**
19817
+ * Processes signal events and creates appropriate notifications.
19818
+ */
19819
+ this._handleSignal = async (data) => {
19820
+ if (data.action === "opened") {
19821
+ this._addNotification({
19822
+ type: "signal.opened",
19823
+ id: CREATE_KEY_FN(),
19824
+ timestamp: data.signal.pendingAt,
19825
+ backtest: data.backtest,
19826
+ symbol: data.symbol,
19827
+ strategyName: data.strategyName,
19828
+ exchangeName: data.exchangeName,
19829
+ signalId: data.signal.id,
19830
+ position: data.signal.position,
19831
+ priceOpen: data.signal.priceOpen,
19832
+ priceTakeProfit: data.signal.priceTakeProfit,
19833
+ priceStopLoss: data.signal.priceStopLoss,
19834
+ note: data.signal.note,
19835
+ });
19836
+ }
19837
+ else if (data.action === "closed") {
19838
+ const durationMs = data.closeTimestamp - data.signal.pendingAt;
19839
+ const durationMin = Math.round(durationMs / 60000);
19840
+ this._addNotification({
19841
+ type: "signal.closed",
19842
+ id: CREATE_KEY_FN(),
19843
+ timestamp: data.closeTimestamp,
19844
+ backtest: data.backtest,
19845
+ symbol: data.symbol,
19846
+ strategyName: data.strategyName,
19847
+ exchangeName: data.exchangeName,
19848
+ signalId: data.signal.id,
19849
+ position: data.signal.position,
19850
+ priceOpen: data.signal.priceOpen,
19851
+ priceClose: data.currentPrice,
19852
+ pnlPercentage: data.pnl.pnlPercentage,
19853
+ closeReason: data.closeReason,
19854
+ duration: durationMin,
19855
+ note: data.signal.note,
19856
+ });
19857
+ }
19858
+ else if (data.action === "scheduled") {
19859
+ this._addNotification({
19860
+ type: "signal.scheduled",
19861
+ id: CREATE_KEY_FN(),
19862
+ timestamp: data.signal.scheduledAt,
19863
+ backtest: data.backtest,
19864
+ symbol: data.symbol,
19865
+ strategyName: data.strategyName,
19866
+ exchangeName: data.exchangeName,
19867
+ signalId: data.signal.id,
19868
+ position: data.signal.position,
19869
+ priceOpen: data.signal.priceOpen,
19870
+ scheduledAt: data.signal.scheduledAt,
19871
+ currentPrice: data.currentPrice,
19872
+ });
19873
+ }
19874
+ else if (data.action === "cancelled") {
19875
+ const durationMs = data.closeTimestamp - data.signal.scheduledAt;
19876
+ const durationMin = Math.round(durationMs / 60000);
19877
+ this._addNotification({
19878
+ type: "signal.cancelled",
19879
+ id: CREATE_KEY_FN(),
19880
+ timestamp: data.closeTimestamp,
19881
+ backtest: data.backtest,
19882
+ symbol: data.symbol,
19883
+ strategyName: data.strategyName,
19884
+ exchangeName: data.exchangeName,
19885
+ signalId: data.signal.id,
19886
+ position: data.signal.position,
19887
+ cancelReason: data.reason,
19888
+ cancelId: data.cancelId,
19889
+ duration: durationMin,
19890
+ });
19891
+ }
19892
+ };
19893
+ /**
19894
+ * Processes partial profit events.
19895
+ */
19896
+ this._handlePartialProfit = async (data) => {
19897
+ this._addNotification({
19898
+ type: "partial.profit",
19899
+ id: CREATE_KEY_FN(),
19900
+ timestamp: data.timestamp,
19901
+ backtest: data.backtest,
19902
+ symbol: data.symbol,
19903
+ strategyName: data.strategyName,
19904
+ exchangeName: data.exchangeName,
19905
+ signalId: data.data.id,
19906
+ level: data.level,
19907
+ currentPrice: data.currentPrice,
19908
+ priceOpen: data.data.priceOpen,
19909
+ position: data.data.position,
19910
+ });
19911
+ };
19912
+ /**
19913
+ * Processes partial loss events.
19914
+ */
19915
+ this._handlePartialLoss = async (data) => {
19916
+ this._addNotification({
19917
+ type: "partial.loss",
19918
+ id: CREATE_KEY_FN(),
19919
+ timestamp: data.timestamp,
19920
+ backtest: data.backtest,
19921
+ symbol: data.symbol,
19922
+ strategyName: data.strategyName,
19923
+ exchangeName: data.exchangeName,
19924
+ signalId: data.data.id,
19925
+ level: data.level,
19926
+ currentPrice: data.currentPrice,
19927
+ priceOpen: data.data.priceOpen,
19928
+ position: data.data.position,
19929
+ });
19930
+ };
19931
+ /**
19932
+ * Processes risk rejection events.
19933
+ */
19934
+ this._handleRisk = async (data) => {
19935
+ this._addNotification({
19936
+ type: "risk.rejection",
19937
+ id: CREATE_KEY_FN(),
19938
+ timestamp: data.timestamp,
19939
+ backtest: data.backtest,
19940
+ symbol: data.symbol,
19941
+ strategyName: data.strategyName,
19942
+ exchangeName: data.exchangeName,
19943
+ rejectionNote: data.rejectionNote,
19944
+ rejectionId: data.rejectionId,
19945
+ activePositionCount: data.activePositionCount,
19946
+ currentPrice: data.currentPrice,
19947
+ pendingSignal: data.pendingSignal,
19948
+ });
19949
+ };
19950
+ /**
19951
+ * Processes done events (live/backtest).
19952
+ */
19953
+ this._handleDoneLive = async (data) => {
19954
+ this._addNotification({
19955
+ type: "live.done",
19956
+ id: CREATE_KEY_FN(),
19957
+ timestamp: Date.now(),
19958
+ backtest: false,
19959
+ symbol: data.symbol,
19960
+ strategyName: data.strategyName,
19961
+ exchangeName: data.exchangeName,
19962
+ });
19963
+ };
19964
+ /**
19965
+ * Processes done events (backtest).
19966
+ */
19967
+ this._handleDoneBacktest = async (data) => {
19968
+ this._addNotification({
19969
+ type: "backtest.done",
19970
+ id: CREATE_KEY_FN(),
19971
+ timestamp: Date.now(),
19972
+ backtest: true,
19973
+ symbol: data.symbol,
19974
+ strategyName: data.strategyName,
19975
+ exchangeName: data.exchangeName,
19976
+ });
19977
+ };
19978
+ /**
19979
+ * Processes error events.
19980
+ */
19981
+ this._handleError = async (error) => {
19982
+ this._addNotification({
19983
+ type: "error.info",
19984
+ id: CREATE_KEY_FN(),
19985
+ timestamp: Date.now(),
19986
+ error: errorData(error),
19987
+ message: getErrorMessage(error),
19988
+ backtest: false,
19989
+ });
19990
+ };
19991
+ /**
19992
+ * Processes critical error events.
19993
+ */
19994
+ this._handleCriticalError = async (error) => {
19995
+ this._addNotification({
19996
+ type: "error.critical",
19997
+ id: CREATE_KEY_FN(),
19998
+ timestamp: Date.now(),
19999
+ error: errorData(error),
20000
+ message: getErrorMessage(error),
20001
+ backtest: false,
20002
+ });
20003
+ };
20004
+ /**
20005
+ * Processes validation error events.
20006
+ */
20007
+ this._handleValidationError = async (error) => {
20008
+ this._addNotification({
20009
+ type: "error.validation",
20010
+ id: CREATE_KEY_FN(),
20011
+ timestamp: Date.now(),
20012
+ error: errorData(error),
20013
+ message: getErrorMessage(error),
20014
+ backtest: false,
20015
+ });
20016
+ };
20017
+ /**
20018
+ * Processes progress events.
20019
+ */
20020
+ this._handleProgressBacktest = async (data) => {
20021
+ this._addNotification({
20022
+ type: "progress.backtest",
20023
+ id: CREATE_KEY_FN(),
20024
+ timestamp: Date.now(),
20025
+ backtest: true,
20026
+ exchangeName: data.exchangeName,
20027
+ strategyName: data.strategyName,
20028
+ symbol: data.symbol,
20029
+ totalFrames: data.totalFrames,
20030
+ processedFrames: data.processedFrames,
20031
+ progress: data.progress,
20032
+ });
20033
+ };
20034
+ /**
20035
+ * Initializes notification system by subscribing to all emitters.
20036
+ * Uses singleshot to ensure initialization happens only once.
20037
+ * Automatically called on first use.
20038
+ */
20039
+ this.waitForInit = singleshot(async () => {
20040
+ // Signal events
20041
+ signalEmitter.subscribe(this._handleSignal);
20042
+ // Partial profit/loss events
20043
+ partialProfitSubject.subscribe(this._handlePartialProfit);
20044
+ partialLossSubject.subscribe(this._handlePartialLoss);
20045
+ // Risk events
20046
+ riskSubject.subscribe(this._handleRisk);
20047
+ // Done events
20048
+ doneLiveSubject.subscribe(this._handleDoneLive);
20049
+ doneBacktestSubject.subscribe(this._handleDoneBacktest);
20050
+ // Error events
20051
+ errorEmitter.subscribe(this._handleError);
20052
+ exitEmitter.subscribe(this._handleCriticalError);
20053
+ validationSubject.subscribe(this._handleValidationError);
20054
+ // Progress events
20055
+ progressBacktestEmitter.subscribe(this._handleProgressBacktest);
20056
+ });
20057
+ }
20058
+ /**
20059
+ * Adds notification to history with automatic limit management.
20060
+ */
20061
+ _addNotification(notification) {
20062
+ this._notifications.unshift(notification);
20063
+ // Trim history if exceeded MAX_NOTIFICATIONS
20064
+ if (this._notifications.length > MAX_NOTIFICATIONS) {
20065
+ this._notifications.pop();
20066
+ }
20067
+ }
20068
+ /**
20069
+ * Returns all notifications in chronological order (newest first).
20070
+ *
20071
+ * @returns Array of strongly-typed notification objects
20072
+ *
20073
+ * @example
20074
+ * ```typescript
20075
+ * const notifications = instance.getData();
20076
+ *
20077
+ * notifications.forEach(notification => {
20078
+ * switch (notification.type) {
20079
+ * case "signal.closed":
20080
+ * console.log(`${notification.symbol}: ${notification.pnlPercentage}%`);
20081
+ * break;
20082
+ * case "partial.loss":
20083
+ * if (notification.level >= 30) {
20084
+ * console.warn(`High loss: ${notification.symbol}`);
20085
+ * }
20086
+ * break;
20087
+ * }
20088
+ * });
20089
+ * ```
20090
+ */
20091
+ getData() {
20092
+ return [...this._notifications];
20093
+ }
20094
+ /**
20095
+ * Clears all notification history.
20096
+ *
20097
+ * @example
20098
+ * ```typescript
20099
+ * instance.clear();
20100
+ * ```
20101
+ */
20102
+ clear() {
20103
+ this._notifications = [];
20104
+ }
20105
+ }
20106
+ /**
20107
+ * Public facade for notification operations.
20108
+ *
20109
+ * Automatically calls waitForInit on each userspace method call.
20110
+ * Provides simplified access to notification instance methods.
20111
+ *
20112
+ * @example
20113
+ * ```typescript
20114
+ * import { Notification } from "./classes/Notification";
20115
+ *
20116
+ * // Get all notifications
20117
+ * const all = await Notification.getData();
20118
+ *
20119
+ * // Process notifications with type discrimination
20120
+ * all.forEach(notification => {
20121
+ * switch (notification.type) {
20122
+ * case "signal.closed":
20123
+ * console.log(`Closed: ${notification.pnlPercentage}%`);
20124
+ * break;
20125
+ * case "partial.loss":
20126
+ * if (notification.level >= 30) {
20127
+ * alert("High loss!");
20128
+ * }
20129
+ * break;
20130
+ * case "risk.rejection":
20131
+ * console.warn(notification.rejectionNote);
20132
+ * break;
20133
+ * }
20134
+ * });
20135
+ *
20136
+ * // Clear history
20137
+ * await Notification.clear();
20138
+ * ```
20139
+ */
20140
+ class NotificationUtils {
20141
+ constructor() {
20142
+ /** Internal instance containing business logic */
20143
+ this._instance = new NotificationInstance();
20144
+ }
20145
+ /**
20146
+ * Returns all notifications in chronological order (newest first).
20147
+ *
20148
+ * @returns Array of strongly-typed notification objects
20149
+ *
20150
+ * @example
20151
+ * ```typescript
20152
+ * const notifications = await Notification.getData();
20153
+ *
20154
+ * notifications.forEach(notification => {
20155
+ * switch (notification.type) {
20156
+ * case "signal.closed":
20157
+ * console.log(`${notification.symbol}: ${notification.pnlPercentage}%`);
20158
+ * break;
20159
+ * case "partial.loss":
20160
+ * if (notification.level >= 30) {
20161
+ * console.warn(`High loss: ${notification.symbol}`);
20162
+ * }
20163
+ * break;
20164
+ * }
20165
+ * });
20166
+ * ```
20167
+ */
20168
+ async getData() {
20169
+ await this._instance.waitForInit();
20170
+ return this._instance.getData();
20171
+ }
20172
+ /**
20173
+ * Clears all notification history.
20174
+ *
20175
+ * @example
20176
+ * ```typescript
20177
+ * await Notification.clear();
20178
+ * ```
20179
+ */
20180
+ async clear() {
20181
+ await this._instance.waitForInit();
20182
+ this._instance.clear();
20183
+ }
20184
+ }
20185
+ /**
20186
+ * Singleton instance of NotificationUtils for convenient notification access.
20187
+ *
20188
+ * @example
20189
+ * ```typescript
20190
+ * import { Notification } from "./classes/Notification";
20191
+ *
20192
+ * // Get all notifications
20193
+ * const all = await Notification.getData();
20194
+ *
20195
+ * // Filter by type using type discrimination
20196
+ * const closedSignals = all.filter(n => n.type === "signal.closed");
20197
+ * const highLosses = all.filter(n =>
20198
+ * n.type === "partial.loss" && n.level >= 30
20199
+ * );
20200
+ *
20201
+ * // Clear history
20202
+ * await Notification.clear();
20203
+ * ```
20204
+ */
20205
+ const Notification = new NotificationUtils();
20206
+
20207
+ export { Backtest, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, MethodContextService, Notification, Optimizer, Partial, Performance, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, Risk, Schedule, Walker, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, cancel, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenPing, listenPingOnce, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setColumns, setConfig, setLogger, stop, validate };