backtest-kit 11.8.0 → 11.9.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
@@ -4681,7 +4681,7 @@ const LOGGER_SERVICE$8 = new LoggerService();
4681
4681
  * @param backtest - `true` for backtest, `false` for live.
4682
4682
  * @returns Colon-joined composite key.
4683
4683
  */
4684
- const CREATE_KEY_FN$y = (symbol, strategyName, exchangeName, frameName, backtest) => {
4684
+ const CREATE_KEY_FN$B = (symbol, strategyName, exchangeName, frameName, backtest) => {
4685
4685
  const parts = [symbol, strategyName, exchangeName];
4686
4686
  if (frameName)
4687
4687
  parts.push(frameName);
@@ -4724,7 +4724,7 @@ class LookupUtils {
4724
4724
  LOGGER_SERVICE$8.info(METHOD_NAME_ADD_ACTIVITY, {
4725
4725
  activity,
4726
4726
  });
4727
- const key = CREATE_KEY_FN$y(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
4727
+ const key = CREATE_KEY_FN$B(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
4728
4728
  this._lookupMap.set(key, activity);
4729
4729
  };
4730
4730
  /**
@@ -4738,7 +4738,7 @@ class LookupUtils {
4738
4738
  LOGGER_SERVICE$8.info(METHOD_NAME_REMOVE_ACTIVITY, {
4739
4739
  activity,
4740
4740
  });
4741
- const key = CREATE_KEY_FN$y(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
4741
+ const key = CREATE_KEY_FN$B(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
4742
4742
  this._lookupMap.delete(key);
4743
4743
  };
4744
4744
  /**
@@ -12356,7 +12356,7 @@ const GET_RISK_FN = (dto, backtest, exchangeName, frameName, self) => {
12356
12356
  * @param backtest - Whether running in backtest mode
12357
12357
  * @returns Unique string key for memoization
12358
12358
  */
12359
- const CREATE_KEY_FN$x = (symbol, strategyName, exchangeName, frameName, backtest) => {
12359
+ const CREATE_KEY_FN$A = (symbol, strategyName, exchangeName, frameName, backtest) => {
12360
12360
  const parts = [symbol, strategyName, exchangeName];
12361
12361
  if (frameName)
12362
12362
  parts.push(frameName);
@@ -12658,7 +12658,7 @@ class StrategyConnectionService {
12658
12658
  * @param backtest - Whether running in backtest mode
12659
12659
  * @returns Configured ClientStrategy instance
12660
12660
  */
12661
- this.getStrategy = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$x(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => {
12661
+ this.getStrategy = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$A(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => {
12662
12662
  const { riskName = "", riskList = [], getSignal, interval = STRATEGY_DEFAULT_INTERVAL, callbacks, } = this.strategySchemaService.get(strategyName);
12663
12663
  return new ClientStrategy({
12664
12664
  symbol,
@@ -13620,7 +13620,7 @@ class StrategyConnectionService {
13620
13620
  }
13621
13621
  return;
13622
13622
  }
13623
- const key = CREATE_KEY_FN$x(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
13623
+ const key = CREATE_KEY_FN$A(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
13624
13624
  if (!this.getStrategy.has(key)) {
13625
13625
  return;
13626
13626
  }
@@ -14166,6 +14166,7 @@ class ClientFrame {
14166
14166
  }
14167
14167
  }
14168
14168
 
14169
+ const DEFAULT_INTERVAL = "1m";
14169
14170
  /**
14170
14171
  * Connection service routing frame operations to correct ClientFrame instance.
14171
14172
  *
@@ -14209,7 +14210,7 @@ class FrameConnectionService {
14209
14210
  logger: this.loggerService,
14210
14211
  startDate,
14211
14212
  endDate,
14212
- interval,
14213
+ interval: interval || DEFAULT_INTERVAL,
14213
14214
  callbacks,
14214
14215
  });
14215
14216
  });
@@ -14868,7 +14869,7 @@ class ClientRisk {
14868
14869
  * @param backtest - Whether running in backtest mode
14869
14870
  * @returns Unique string key for memoization
14870
14871
  */
14871
- const CREATE_KEY_FN$w = (riskName, exchangeName, frameName, backtest) => {
14872
+ const CREATE_KEY_FN$z = (riskName, exchangeName, frameName, backtest) => {
14872
14873
  const parts = [riskName, exchangeName];
14873
14874
  if (frameName)
14874
14875
  parts.push(frameName);
@@ -14968,7 +14969,7 @@ class RiskConnectionService {
14968
14969
  * @param backtest - True if backtest mode, false if live mode
14969
14970
  * @returns Configured ClientRisk instance
14970
14971
  */
14971
- this.getRisk = functoolsKit.memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$w(riskName, exchangeName, frameName, backtest), (riskName, exchangeName, frameName, backtest) => {
14972
+ this.getRisk = functoolsKit.memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$z(riskName, exchangeName, frameName, backtest), (riskName, exchangeName, frameName, backtest) => {
14972
14973
  const schema = this.riskSchemaService.get(riskName);
14973
14974
  return new ClientRisk({
14974
14975
  ...schema,
@@ -15058,7 +15059,7 @@ class RiskConnectionService {
15058
15059
  payload,
15059
15060
  });
15060
15061
  if (payload) {
15061
- const key = CREATE_KEY_FN$w(payload.riskName, payload.exchangeName, payload.frameName, payload.backtest);
15062
+ const key = CREATE_KEY_FN$z(payload.riskName, payload.exchangeName, payload.frameName, payload.backtest);
15062
15063
  this.getRisk.clear(key);
15063
15064
  }
15064
15065
  else {
@@ -16177,7 +16178,7 @@ class ClientAction {
16177
16178
  * @param backtest - Whether running in backtest mode
16178
16179
  * @returns Unique string key for memoization
16179
16180
  */
16180
- const CREATE_KEY_FN$v = (actionName, strategyName, exchangeName, frameName, backtest) => {
16181
+ const CREATE_KEY_FN$y = (actionName, strategyName, exchangeName, frameName, backtest) => {
16181
16182
  const parts = [actionName, strategyName, exchangeName];
16182
16183
  if (frameName)
16183
16184
  parts.push(frameName);
@@ -16229,7 +16230,7 @@ class ActionConnectionService {
16229
16230
  * @param backtest - True if backtest mode, false if live mode
16230
16231
  * @returns Configured ClientAction instance
16231
16232
  */
16232
- this.getAction = functoolsKit.memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$v(actionName, strategyName, exchangeName, frameName, backtest), (actionName, strategyName, exchangeName, frameName, backtest) => {
16233
+ this.getAction = functoolsKit.memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$y(actionName, strategyName, exchangeName, frameName, backtest), (actionName, strategyName, exchangeName, frameName, backtest) => {
16233
16234
  const schema = this.actionSchemaService.get(actionName);
16234
16235
  return new ClientAction({
16235
16236
  ...schema,
@@ -16455,7 +16456,7 @@ class ActionConnectionService {
16455
16456
  await Promise.all(actions.map(async (action) => await action.dispose()));
16456
16457
  return;
16457
16458
  }
16458
- const key = CREATE_KEY_FN$v(payload.actionName, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
16459
+ const key = CREATE_KEY_FN$y(payload.actionName, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
16459
16460
  if (!this.getAction.has(key)) {
16460
16461
  return;
16461
16462
  }
@@ -16466,14 +16467,14 @@ class ActionConnectionService {
16466
16467
  }
16467
16468
  }
16468
16469
 
16469
- const METHOD_NAME_VALIDATE$3 = "exchangeCoreService validate";
16470
+ const METHOD_NAME_VALIDATE$6 = "exchangeCoreService validate";
16470
16471
  /**
16471
16472
  * Creates a unique key for memoizing validate calls.
16472
16473
  * Key format: "exchangeName"
16473
16474
  * @param exchangeName - Exchange name
16474
16475
  * @returns Unique string key for memoization
16475
16476
  */
16476
- const CREATE_KEY_FN$u = (exchangeName) => {
16477
+ const CREATE_KEY_FN$x = (exchangeName) => {
16477
16478
  return exchangeName;
16478
16479
  };
16479
16480
  /**
@@ -16497,11 +16498,11 @@ class ExchangeCoreService {
16497
16498
  * @param exchangeName - Name of the exchange to validate
16498
16499
  * @returns Promise that resolves when validation is complete
16499
16500
  */
16500
- this.validate = functoolsKit.memoize(([exchangeName]) => CREATE_KEY_FN$u(exchangeName), async (exchangeName) => {
16501
- this.loggerService.log(METHOD_NAME_VALIDATE$3, {
16501
+ this.validate = functoolsKit.memoize(([exchangeName]) => CREATE_KEY_FN$x(exchangeName), async (exchangeName) => {
16502
+ this.loggerService.log(METHOD_NAME_VALIDATE$6, {
16502
16503
  exchangeName,
16503
16504
  });
16504
- this.exchangeValidationService.validate(exchangeName, METHOD_NAME_VALIDATE$3);
16505
+ this.exchangeValidationService.validate(exchangeName, METHOD_NAME_VALIDATE$6);
16505
16506
  });
16506
16507
  /**
16507
16508
  * Fetches historical candles with execution context.
@@ -16770,14 +16771,14 @@ class ExchangeCoreService {
16770
16771
  }
16771
16772
  }
16772
16773
 
16773
- const METHOD_NAME_VALIDATE$2 = "strategyCoreService validate";
16774
+ const METHOD_NAME_VALIDATE$5 = "strategyCoreService validate";
16774
16775
  /**
16775
16776
  * Creates a unique key for memoizing validate calls.
16776
16777
  * Key format: "strategyName:exchangeName:frameName"
16777
16778
  * @param context - Execution context with strategyName, exchangeName, frameName
16778
16779
  * @returns Unique string key for memoization
16779
16780
  */
16780
- const CREATE_KEY_FN$t = (context) => {
16781
+ const CREATE_KEY_FN$w = (context) => {
16781
16782
  const parts = [context.strategyName, context.exchangeName];
16782
16783
  if (context.frameName)
16783
16784
  parts.push(context.frameName);
@@ -16800,6 +16801,7 @@ class StrategyCoreService {
16800
16801
  this.strategyValidationService = inject(TYPES.strategyValidationService);
16801
16802
  this.exchangeValidationService = inject(TYPES.exchangeValidationService);
16802
16803
  this.frameValidationService = inject(TYPES.frameValidationService);
16804
+ this.actionValidationService = inject(TYPES.actionValidationService);
16803
16805
  /**
16804
16806
  * Validates strategy and associated risk configuration.
16805
16807
  *
@@ -16809,16 +16811,17 @@ class StrategyCoreService {
16809
16811
  * @param context - Execution context with strategyName, exchangeName, frameName
16810
16812
  * @returns Promise that resolves when validation is complete
16811
16813
  */
16812
- this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$t(context), async (context) => {
16813
- this.loggerService.log(METHOD_NAME_VALIDATE$2, {
16814
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$w(context), async (context) => {
16815
+ this.loggerService.log(METHOD_NAME_VALIDATE$5, {
16814
16816
  context,
16815
16817
  });
16816
- const { riskName, riskList } = this.strategySchemaService.get(context.strategyName);
16817
- this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$2);
16818
- this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$2);
16819
- context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$2);
16820
- riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$2);
16821
- riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$2));
16818
+ const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
16819
+ this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$5);
16820
+ this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$5);
16821
+ context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$5);
16822
+ riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$5);
16823
+ riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$5));
16824
+ actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE$5));
16822
16825
  });
16823
16826
  /**
16824
16827
  * Retrieves the currently active pending signal for the symbol.
@@ -18179,7 +18182,7 @@ class SizingGlobalService {
18179
18182
  * @param context - Context with riskName, exchangeName, frameName
18180
18183
  * @returns Unique string key for memoization
18181
18184
  */
18182
- const CREATE_KEY_FN$s = (context) => {
18185
+ const CREATE_KEY_FN$v = (context) => {
18183
18186
  const parts = [context.riskName, context.exchangeName];
18184
18187
  if (context.frameName)
18185
18188
  parts.push(context.frameName);
@@ -18205,7 +18208,7 @@ class RiskGlobalService {
18205
18208
  * @param payload - Payload with riskName, exchangeName and frameName
18206
18209
  * @returns Promise that resolves when validation is complete
18207
18210
  */
18208
- this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$s(context), async (context) => {
18211
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$v(context), async (context) => {
18209
18212
  this.loggerService.log("riskGlobalService validate", {
18210
18213
  context,
18211
18214
  });
@@ -18297,14 +18300,14 @@ class RiskGlobalService {
18297
18300
  }
18298
18301
  }
18299
18302
 
18300
- const METHOD_NAME_VALIDATE$1 = "actionCoreService validate";
18303
+ const METHOD_NAME_VALIDATE$4 = "actionCoreService validate";
18301
18304
  /**
18302
18305
  * Creates a unique key for memoizing validate calls.
18303
18306
  * Key format: "strategyName:exchangeName:frameName"
18304
18307
  * @param context - Execution context with strategyName, exchangeName, frameName
18305
18308
  * @returns Unique string key for memoization
18306
18309
  */
18307
- const CREATE_KEY_FN$r = (context) => {
18310
+ const CREATE_KEY_FN$u = (context) => {
18308
18311
  const parts = [context.strategyName, context.exchangeName];
18309
18312
  if (context.frameName)
18310
18313
  parts.push(context.frameName);
@@ -18348,17 +18351,17 @@ class ActionCoreService {
18348
18351
  * @param context - Strategy execution context with strategyName, exchangeName and frameName
18349
18352
  * @returns Promise that resolves when all validations complete
18350
18353
  */
18351
- this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$r(context), async (context) => {
18352
- this.loggerService.log(METHOD_NAME_VALIDATE$1, {
18354
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$u(context), async (context) => {
18355
+ this.loggerService.log(METHOD_NAME_VALIDATE$4, {
18353
18356
  context,
18354
18357
  });
18355
18358
  const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
18356
- this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$1);
18357
- this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$1);
18358
- context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$1);
18359
- riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1);
18360
- riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1));
18361
- actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE$1));
18359
+ this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$4);
18360
+ this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$4);
18361
+ context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$4);
18362
+ riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$4);
18363
+ riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$4));
18364
+ actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE$4));
18362
18365
  });
18363
18366
  /**
18364
18367
  * Initializes all ClientAction instances for the strategy.
@@ -18854,8 +18857,8 @@ class FrameSchemaService {
18854
18857
  if (typeof frameSchema.frameName !== "string") {
18855
18858
  throw new Error(`frame schema validation failed: missing frameName`);
18856
18859
  }
18857
- if (typeof frameSchema.interval !== "string") {
18858
- throw new Error(`frame schema validation failed: missing interval for frameName=${frameSchema.frameName}`);
18860
+ if (frameSchema.interval && typeof frameSchema.interval !== "string") {
18861
+ throw new Error(`frame schema validation failed: invalid interval for frameName=${frameSchema.frameName}`);
18859
18862
  }
18860
18863
  if (!(frameSchema.startDate instanceof Date)) {
18861
18864
  throw new Error(`frame schema validation failed: missing startDate for frameName=${frameSchema.frameName}`);
@@ -20848,6 +20851,17 @@ class WalkerLogicPublicService {
20848
20851
  }
20849
20852
 
20850
20853
  const METHOD_NAME_RUN$2 = "liveCommandService run";
20854
+ const METHOD_NAME_VALIDATE$3 = "liveCommandService validate";
20855
+ /**
20856
+ * Creates a unique key for memoizing validate calls.
20857
+ * Key format: "strategyName:exchangeName:frameName"
20858
+ * @param context - Context with strategyName, exchangeName, frameName
20859
+ * @returns Unique string key for memoization
20860
+ */
20861
+ const CREATE_KEY_FN$t = (context) => {
20862
+ const parts = [context.strategyName, context.exchangeName];
20863
+ return parts.join(":");
20864
+ };
20851
20865
  /**
20852
20866
  * Global service providing access to live trading functionality.
20853
20867
  *
@@ -20863,6 +20877,25 @@ class LiveCommandService {
20863
20877
  this.strategySchemaService = inject(TYPES.strategySchemaService);
20864
20878
  this.riskValidationService = inject(TYPES.riskValidationService);
20865
20879
  this.actionValidationService = inject(TYPES.actionValidationService);
20880
+ /**
20881
+ * Validates strategy and associated risk configuration.
20882
+ * Memoized to avoid redundant validations for the same strategy-exchange combination.
20883
+ *
20884
+ * @param context - Context with strategyName, exchangeName
20885
+ * @param methodName - Name of the calling method for error tracking
20886
+ */
20887
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$t(context), (context, methodName) => {
20888
+ this.loggerService.log(METHOD_NAME_VALIDATE$3, {
20889
+ context,
20890
+ methodName,
20891
+ });
20892
+ this.strategyValidationService.validate(context.strategyName, methodName);
20893
+ this.exchangeValidationService.validate(context.exchangeName, methodName);
20894
+ const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
20895
+ riskName && this.riskValidationService.validate(riskName, methodName);
20896
+ riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, methodName));
20897
+ actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, methodName));
20898
+ });
20866
20899
  /**
20867
20900
  * Runs live trading for a symbol with context propagation.
20868
20901
  *
@@ -20877,22 +20910,26 @@ class LiveCommandService {
20877
20910
  symbol,
20878
20911
  context,
20879
20912
  });
20880
- {
20881
- this.strategyValidationService.validate(context.strategyName, METHOD_NAME_RUN$2);
20882
- this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_RUN$2);
20883
- }
20884
- {
20885
- const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
20886
- riskName && this.riskValidationService.validate(riskName, METHOD_NAME_RUN$2);
20887
- riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_RUN$2));
20888
- actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_RUN$2));
20889
- }
20913
+ this.validate(context, METHOD_NAME_RUN$2);
20890
20914
  return this.liveLogicPublicService.run(symbol, context);
20891
20915
  };
20892
20916
  }
20893
20917
  }
20894
20918
 
20895
20919
  const METHOD_NAME_RUN$1 = "backtestCommandService run";
20920
+ const METHOD_NAME_VALIDATE$2 = "backtestCommandService validate";
20921
+ /**
20922
+ * Creates a unique key for memoizing validate calls.
20923
+ * Key format: "strategyName:exchangeName:frameName"
20924
+ * @param context - Context with strategyName, exchangeName, frameName
20925
+ * @returns Unique string key for memoization
20926
+ */
20927
+ const CREATE_KEY_FN$s = (context) => {
20928
+ const parts = [context.strategyName, context.exchangeName];
20929
+ if (context.frameName)
20930
+ parts.push(context.frameName);
20931
+ return parts.join(":");
20932
+ };
20896
20933
  /**
20897
20934
  * Global service providing access to backtest functionality.
20898
20935
  *
@@ -20909,6 +20946,26 @@ class BacktestCommandService {
20909
20946
  this.strategyValidationService = inject(TYPES.strategyValidationService);
20910
20947
  this.exchangeValidationService = inject(TYPES.exchangeValidationService);
20911
20948
  this.frameValidationService = inject(TYPES.frameValidationService);
20949
+ /**
20950
+ * Validates strategy and associated risk configuration.
20951
+ * Memoized to avoid redundant validations for the same strategy-exchange-frame combination.
20952
+ *
20953
+ * @param context - Context with strategyName, exchangeName and frameName
20954
+ * @param methodName - Name of the calling method for error tracking
20955
+ */
20956
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$s(context), (context, methodName) => {
20957
+ this.loggerService.log(METHOD_NAME_VALIDATE$2, {
20958
+ context,
20959
+ methodName,
20960
+ });
20961
+ this.strategyValidationService.validate(context.strategyName, methodName);
20962
+ this.exchangeValidationService.validate(context.exchangeName, methodName);
20963
+ this.frameValidationService.validate(context.frameName, methodName);
20964
+ const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
20965
+ riskName && this.riskValidationService.validate(riskName, methodName);
20966
+ riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, methodName));
20967
+ actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, methodName));
20968
+ });
20912
20969
  /**
20913
20970
  * Runs backtest for a symbol with context propagation.
20914
20971
  *
@@ -20921,23 +20978,26 @@ class BacktestCommandService {
20921
20978
  symbol,
20922
20979
  context,
20923
20980
  });
20924
- {
20925
- this.strategyValidationService.validate(context.strategyName, METHOD_NAME_RUN$1);
20926
- this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_RUN$1);
20927
- this.frameValidationService.validate(context.frameName, METHOD_NAME_RUN$1);
20928
- }
20929
- {
20930
- const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
20931
- riskName && this.riskValidationService.validate(riskName, METHOD_NAME_RUN$1);
20932
- riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_RUN$1));
20933
- actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_RUN$1));
20934
- }
20981
+ this.validate(context, METHOD_NAME_RUN$1);
20935
20982
  return this.backtestLogicPublicService.run(symbol, context);
20936
20983
  };
20937
20984
  }
20938
20985
  }
20939
20986
 
20940
20987
  const METHOD_NAME_RUN = "walkerCommandService run";
20988
+ const METHOD_NAME_VALIDATE$1 = "walkerCommandService validate";
20989
+ /**
20990
+ * Creates a unique key for memoizing validate calls.
20991
+ * Key format: "walkerName:exchangeName:frameName"
20992
+ * @param context - Context with walkerName, exchangeName, frameName
20993
+ * @returns Unique string key for memoization
20994
+ */
20995
+ const CREATE_KEY_FN$r = (context) => {
20996
+ const parts = [context.walkerName, context.exchangeName];
20997
+ if (context.frameName)
20998
+ parts.push(context.frameName);
20999
+ return parts.join(":");
21000
+ };
20941
21001
  /**
20942
21002
  * Global service providing access to walker functionality.
20943
21003
  *
@@ -20956,6 +21016,34 @@ class WalkerCommandService {
20956
21016
  this.strategySchemaService = inject(TYPES.strategySchemaService);
20957
21017
  this.riskValidationService = inject(TYPES.riskValidationService);
20958
21018
  this.actionValidationService = inject(TYPES.actionValidationService);
21019
+ /**
21020
+ * Validates walker and associated strategy configurations.
21021
+ * Memoized to avoid redundant validations for the same walker-exchange-frame combination.
21022
+ *
21023
+ * Strategy/risk/action validation is performed explicitly here in addition to the
21024
+ * cascade inside WalkerValidationService — this is critical-path code and the
21025
+ * redundant check is intentional defense-in-depth.
21026
+ *
21027
+ * @param context - Context with walkerName, exchangeName and frameName
21028
+ * @param methodName - Name of the calling method for error tracking
21029
+ */
21030
+ this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$r(context), (context, methodName) => {
21031
+ this.loggerService.log(METHOD_NAME_VALIDATE$1, {
21032
+ context,
21033
+ methodName,
21034
+ });
21035
+ this.exchangeValidationService.validate(context.exchangeName, methodName);
21036
+ this.frameValidationService.validate(context.frameName, methodName);
21037
+ this.walkerValidationService.validate(context.walkerName, methodName);
21038
+ const walkerSchema = this.walkerSchemaService.get(context.walkerName);
21039
+ for (const strategyName of walkerSchema.strategies) {
21040
+ const { riskName, riskList, actions } = this.strategySchemaService.get(strategyName);
21041
+ this.strategyValidationService.validate(strategyName, methodName);
21042
+ riskName && this.riskValidationService.validate(riskName, methodName);
21043
+ riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, methodName));
21044
+ actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, methodName));
21045
+ }
21046
+ });
20959
21047
  /**
20960
21048
  * Runs walker comparison for a symbol with context propagation.
20961
21049
  *
@@ -20967,21 +21055,7 @@ class WalkerCommandService {
20967
21055
  symbol,
20968
21056
  context,
20969
21057
  });
20970
- {
20971
- this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_RUN);
20972
- this.frameValidationService.validate(context.frameName, METHOD_NAME_RUN);
20973
- this.walkerValidationService.validate(context.walkerName, METHOD_NAME_RUN);
20974
- }
20975
- {
20976
- const walkerSchema = this.walkerSchemaService.get(context.walkerName);
20977
- for (const strategyName of walkerSchema.strategies) {
20978
- const { riskName, riskList, actions } = this.strategySchemaService.get(strategyName);
20979
- this.strategyValidationService.validate(strategyName, METHOD_NAME_RUN);
20980
- riskName && this.riskValidationService.validate(riskName, METHOD_NAME_RUN);
20981
- riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_RUN));
20982
- actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_RUN));
20983
- }
20984
- }
21058
+ this.validate(context, METHOD_NAME_RUN);
20985
21059
  return this.walkerLogicPublicService.run(symbol, context);
20986
21060
  };
20987
21061
  }
@@ -28704,6 +28778,36 @@ class WalkerValidationService {
28704
28778
  * Injected logger service instance
28705
28779
  */
28706
28780
  this.loggerService = inject(TYPES.loggerService);
28781
+ /**
28782
+ * @private
28783
+ * @readonly
28784
+ * Injected walker schema service instance
28785
+ */
28786
+ this.walkerSchemaService = inject(TYPES.walkerSchemaService);
28787
+ /**
28788
+ * @private
28789
+ * @readonly
28790
+ * Injected strategy validation service instance
28791
+ */
28792
+ this.strategyValidationService = inject(TYPES.strategyValidationService);
28793
+ /**
28794
+ * @private
28795
+ * @readonly
28796
+ * Injected strategy schema service instance
28797
+ */
28798
+ this.strategySchemaService = inject(TYPES.strategySchemaService);
28799
+ /**
28800
+ * @private
28801
+ * @readonly
28802
+ * Injected risk validation service instance
28803
+ */
28804
+ this.riskValidationService = inject(TYPES.riskValidationService);
28805
+ /**
28806
+ * @private
28807
+ * @readonly
28808
+ * Injected action validation service instance
28809
+ */
28810
+ this.actionValidationService = inject(TYPES.actionValidationService);
28707
28811
  /**
28708
28812
  * @private
28709
28813
  * Map storing walker schemas by walker name
@@ -28725,9 +28829,12 @@ class WalkerValidationService {
28725
28829
  this._walkerMap.set(walkerName, walkerSchema);
28726
28830
  };
28727
28831
  /**
28728
- * Validates the existence of a walker
28832
+ * Validates the existence of a walker and its associated strategy configurations.
28833
+ * Each strategy referenced by the walker is validated via StrategyValidationService,
28834
+ * which in turn validates the strategy's risk profiles and actions.
28729
28835
  * @public
28730
28836
  * @throws {Error} If walkerName is not found
28837
+ * @throws {Error} If any referenced strategy (or its risk/actions) is invalid
28731
28838
  * Memoized function to cache validation results
28732
28839
  */
28733
28840
  this.validate = functoolsKit.memoize(([walkerName]) => walkerName, (walkerName, source) => {
@@ -28739,6 +28846,14 @@ class WalkerValidationService {
28739
28846
  if (!walker) {
28740
28847
  throw new Error(`walker ${walkerName} not found source=${source}`);
28741
28848
  }
28849
+ const walkerSchema = this.walkerSchemaService.get(walkerName);
28850
+ for (const strategyName of walkerSchema.strategies) {
28851
+ const { riskName, riskList, actions } = this.strategySchemaService.get(strategyName);
28852
+ this.strategyValidationService.validate(strategyName, source);
28853
+ riskName && this.riskValidationService.validate(riskName, source);
28854
+ riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, source));
28855
+ actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, source));
28856
+ }
28742
28857
  return true;
28743
28858
  });
28744
28859
  /**
@@ -30175,6 +30290,10 @@ class PartialGlobalService {
30175
30290
  * Frame validation service for validating frame existence.
30176
30291
  */
30177
30292
  this.frameValidationService = inject(TYPES.frameValidationService);
30293
+ /**
30294
+ * Action validation service for validating action existence.
30295
+ */
30296
+ this.actionValidationService = inject(TYPES.actionValidationService);
30178
30297
  /**
30179
30298
  * Validates strategy and associated risk configuration.
30180
30299
  * Memoized to avoid redundant validations for the same strategy-exchange-frame combination.
@@ -30190,9 +30309,10 @@ class PartialGlobalService {
30190
30309
  this.strategyValidationService.validate(context.strategyName, methodName);
30191
30310
  this.exchangeValidationService.validate(context.exchangeName, methodName);
30192
30311
  context.frameName && this.frameValidationService.validate(context.frameName, methodName);
30193
- const { riskName, riskList } = this.strategySchemaService.get(context.strategyName);
30312
+ const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
30194
30313
  riskName && this.riskValidationService.validate(riskName, methodName);
30195
30314
  riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, methodName));
30315
+ actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, methodName));
30196
30316
  });
30197
30317
  /**
30198
30318
  * Processes profit state and emits events for newly reached profit levels.
@@ -31259,6 +31379,10 @@ class BreakevenGlobalService {
31259
31379
  * Frame validation service for validating frame existence.
31260
31380
  */
31261
31381
  this.frameValidationService = inject(TYPES.frameValidationService);
31382
+ /**
31383
+ * Action validation service for validating frame existence.
31384
+ */
31385
+ this.actionValidationService = inject(TYPES.actionValidationService);
31262
31386
  /**
31263
31387
  * Validates strategy and associated risk configuration.
31264
31388
  * Memoized to avoid redundant validations for the same strategy-exchange-frame combination.
@@ -31274,9 +31398,10 @@ class BreakevenGlobalService {
31274
31398
  this.strategyValidationService.validate(context.strategyName, methodName);
31275
31399
  this.exchangeValidationService.validate(context.exchangeName, methodName);
31276
31400
  context.frameName && this.frameValidationService.validate(context.frameName, methodName);
31277
- const { riskName, riskList } = this.strategySchemaService.get(context.strategyName);
31401
+ const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
31278
31402
  riskName && this.riskValidationService.validate(riskName, methodName);
31279
31403
  riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, methodName));
31404
+ actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, methodName));
31280
31405
  });
31281
31406
  /**
31282
31407
  * Checks if breakeven should be triggered and emits event if conditions met.
@@ -50618,6 +50743,7 @@ const GET_TIMESTAMP_METHOD_NAME = "meta.getTimestamp";
50618
50743
  const GET_MODE_METHOD_NAME = "meta.getMode";
50619
50744
  const GET_SYMBOL_METHOD_NAME = "meta.getSymbol";
50620
50745
  const GET_CONTEXT_METHOD_NAME = "meta.getContext";
50746
+ const GET_RUNTIME_INFO_METHOD_NAME = "meta.getRuntimeInfo";
50621
50747
  /**
50622
50748
  * Gets the current date from execution context.
50623
50749
  *
@@ -50734,6 +50860,45 @@ async function getContext() {
50734
50860
  }
50735
50861
  return backtest.methodContextService.context;
50736
50862
  }
50863
+ /**
50864
+ * Gets runtime information about the current execution environment.
50865
+ *
50866
+ * This includes details such as the current symbol, exchange, timeframe, strategy, and whether it's a backtest or live run.
50867
+ *
50868
+ * @returns Promise resolving to an object containing runtime information
50869
+ * @throws Error if method context or execution context is not active
50870
+ *
50871
+ * @example
50872
+ * ```typescript
50873
+ * const runtimeInfo = await getRuntimeInfo();
50874
+ * console.log(runtimeInfo);
50875
+ * // {
50876
+ * // symbol: "BTCUSDT",
50877
+ * // context: {,
50878
+ * // exchangeName: "Binance",
50879
+ * // frameName: "1m",
50880
+ * // strategyName: "MyStrategy",
50881
+ * // },
50882
+ * // backtest: false
50883
+ * // }
50884
+ * ```
50885
+ */
50886
+ async function getRuntimeInfo() {
50887
+ backtest.loggerService.info(GET_RUNTIME_INFO_METHOD_NAME);
50888
+ if (!MethodContextService.hasContext()) {
50889
+ throw new Error("getRuntimeInfo requires a method context");
50890
+ }
50891
+ if (!ExecutionContextService.hasContext()) {
50892
+ throw new Error("getRuntimeInfo requires an execution context");
50893
+ }
50894
+ const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
50895
+ const { symbol, backtest: isBacktest } = backtest.executionContextService.context;
50896
+ return await backtest.runtimeMetaService.getRuntimeInfo(symbol, {
50897
+ exchangeName,
50898
+ frameName,
50899
+ strategyName,
50900
+ }, isBacktest);
50901
+ }
50737
50902
 
50738
50903
  const RECENT_PERSIST_BACKTEST_METHOD_NAME_HANDLE_ACTIVE_PING = "RecentPersistBacktestUtils.handleActivePing";
50739
50904
  const RECENT_PERSIST_BACKTEST_METHOD_NAME_GET_LATEST_SIGNAL = "RecentPersistBacktestUtils.getLatestSignal";
@@ -66813,6 +66978,7 @@ exports.getPositionPnlPercent = getPositionPnlPercent;
66813
66978
  exports.getPositionWaitingMinutes = getPositionWaitingMinutes;
66814
66979
  exports.getRawCandles = getRawCandles;
66815
66980
  exports.getRiskSchema = getRiskSchema;
66981
+ exports.getRuntimeInfo = getRuntimeInfo;
66816
66982
  exports.getScheduledSignal = getScheduledSignal;
66817
66983
  exports.getSessionData = getSessionData;
66818
66984
  exports.getSignalState = getSignalState;