backtest-kit 1.13.3 → 2.0.1

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
@@ -541,14 +541,21 @@ const breakevenSubject = new functoolsKit.Subject();
541
541
  */
542
542
  const riskSubject = new functoolsKit.Subject();
543
543
  /**
544
- * Ping emitter for scheduled signal monitoring events.
544
+ * Schedule ping emitter for scheduled signal monitoring events.
545
545
  * Emits every minute when a scheduled signal is being monitored (waiting for activation).
546
546
  * Allows users to track scheduled signal lifecycle and implement custom cancellation logic.
547
547
  */
548
- const pingSubject = new functoolsKit.Subject();
548
+ const schedulePingSubject = new functoolsKit.Subject();
549
+ /**
550
+ * Active ping emitter for active pending signal monitoring events.
551
+ * Emits every minute when an active pending signal is being monitored.
552
+ * Allows users to track active signal lifecycle and implement custom dynamic management logic.
553
+ */
554
+ const activePingSubject = new functoolsKit.Subject();
549
555
 
550
556
  var emitters = /*#__PURE__*/Object.freeze({
551
557
  __proto__: null,
558
+ activePingSubject: activePingSubject,
552
559
  breakevenSubject: breakevenSubject,
553
560
  doneBacktestSubject: doneBacktestSubject,
554
561
  doneLiveSubject: doneLiveSubject,
@@ -558,11 +565,11 @@ var emitters = /*#__PURE__*/Object.freeze({
558
565
  partialLossSubject: partialLossSubject,
559
566
  partialProfitSubject: partialProfitSubject,
560
567
  performanceEmitter: performanceEmitter,
561
- pingSubject: pingSubject,
562
568
  progressBacktestEmitter: progressBacktestEmitter,
563
569
  progressOptimizerEmitter: progressOptimizerEmitter,
564
570
  progressWalkerEmitter: progressWalkerEmitter,
565
571
  riskSubject: riskSubject,
572
+ schedulePingSubject: schedulePingSubject,
566
573
  signalBacktestEmitter: signalBacktestEmitter,
567
574
  signalEmitter: signalEmitter,
568
575
  signalLiveEmitter: signalLiveEmitter,
@@ -773,11 +780,16 @@ class ClientExchange {
773
780
  const whenTimestamp = this.params.execution.context.when.getTime();
774
781
  const sinceTimestamp = since.getTime();
775
782
  const filteredData = allData.filter((candle) => candle.timestamp >= sinceTimestamp && candle.timestamp <= whenTimestamp);
776
- if (filteredData.length < limit) {
777
- this.params.logger.warn(`ClientExchange Expected ${limit} candles, got ${filteredData.length}`);
783
+ // Apply distinct by timestamp to remove duplicates
784
+ const uniqueData = Array.from(new Map(filteredData.map((candle) => [candle.timestamp, candle])).values());
785
+ if (filteredData.length !== uniqueData.length) {
786
+ this.params.logger.warn(`ClientExchange Removed ${filteredData.length - uniqueData.length} duplicate candles by timestamp`);
778
787
  }
779
- await CALL_CANDLE_DATA_CALLBACKS_FN(this, symbol, interval, since, limit, filteredData);
780
- return filteredData;
788
+ if (uniqueData.length < limit) {
789
+ this.params.logger.warn(`ClientExchange Expected ${limit} candles, got ${uniqueData.length}`);
790
+ }
791
+ await CALL_CANDLE_DATA_CALLBACKS_FN(this, symbol, interval, since, limit, uniqueData);
792
+ return uniqueData;
781
793
  }
782
794
  /**
783
795
  * Fetches future candles forwards from execution context time.
@@ -826,11 +838,16 @@ class ClientExchange {
826
838
  // Filter candles to strictly match the requested range
827
839
  const sinceTimestamp = since.getTime();
828
840
  const filteredData = allData.filter((candle) => candle.timestamp >= sinceTimestamp && candle.timestamp <= endTime);
829
- if (filteredData.length < limit) {
830
- this.params.logger.warn(`ClientExchange getNextCandles: Expected ${limit} candles, got ${filteredData.length}`);
841
+ // Apply distinct by timestamp to remove duplicates
842
+ const uniqueData = Array.from(new Map(filteredData.map((candle) => [candle.timestamp, candle])).values());
843
+ if (filteredData.length !== uniqueData.length) {
844
+ this.params.logger.warn(`ClientExchange getNextCandles: Removed ${filteredData.length - uniqueData.length} duplicate candles by timestamp`);
845
+ }
846
+ if (uniqueData.length < limit) {
847
+ this.params.logger.warn(`ClientExchange getNextCandles: Expected ${limit} candles, got ${uniqueData.length}`);
831
848
  }
832
- await CALL_CANDLE_DATA_CALLBACKS_FN(this, symbol, interval, since, limit, filteredData);
833
- return filteredData;
849
+ await CALL_CANDLE_DATA_CALLBACKS_FN(this, symbol, interval, since, limit, uniqueData);
850
+ return uniqueData;
834
851
  }
835
852
  /**
836
853
  * Calculates VWAP (Volume Weighted Average Price) from last N 1m candles.
@@ -3406,14 +3423,40 @@ const ACTIVATE_SCHEDULED_SIGNAL_FN = async (self, scheduled, activationTimestamp
3406
3423
  await CALL_TICK_CALLBACKS_FN(self, self.params.execution.context.symbol, result, activationTime, self.params.execution.context.backtest);
3407
3424
  return result;
3408
3425
  };
3409
- const CALL_PING_CALLBACKS_FN = functoolsKit.trycatch(beginTime(async (self, symbol, scheduled, timestamp, backtest) => {
3426
+ const CALL_SCHEDULE_PING_CALLBACKS_FN = functoolsKit.trycatch(beginTime(async (self, symbol, scheduled, timestamp, backtest) => {
3410
3427
  await ExecutionContextService.runInContext(async () => {
3411
3428
  const publicSignal = TO_PUBLIC_SIGNAL(scheduled);
3412
- // Call system onPing callback first (emits to pingSubject)
3413
- await self.params.onPing(self.params.execution.context.symbol, self.params.method.context.strategyName, self.params.method.context.exchangeName, publicSignal, self.params.execution.context.backtest, timestamp);
3414
- // Call user onPing callback only if signal is still active (not cancelled, not activated)
3415
- if (self.params.callbacks?.onPing) {
3416
- await self.params.callbacks.onPing(self.params.execution.context.symbol, publicSignal, new Date(timestamp), self.params.execution.context.backtest);
3429
+ // Call system onSchedulePing callback first (emits to pingSubject)
3430
+ await self.params.onSchedulePing(self.params.execution.context.symbol, self.params.method.context.strategyName, self.params.method.context.exchangeName, publicSignal, self.params.execution.context.backtest, timestamp);
3431
+ // Call user onSchedulePing callback only if signal is still active (not cancelled, not activated)
3432
+ if (self.params.callbacks?.onSchedulePing) {
3433
+ await self.params.callbacks.onSchedulePing(self.params.execution.context.symbol, publicSignal, new Date(timestamp), self.params.execution.context.backtest);
3434
+ }
3435
+ }, {
3436
+ when: new Date(timestamp),
3437
+ symbol: symbol,
3438
+ backtest: backtest,
3439
+ });
3440
+ }), {
3441
+ fallback: (error) => {
3442
+ const message = "ClientStrategy CALL_SCHEDULE_PING_CALLBACKS_FN thrown";
3443
+ const payload = {
3444
+ error: functoolsKit.errorData(error),
3445
+ message: functoolsKit.getErrorMessage(error),
3446
+ };
3447
+ backtest$1.loggerService.warn(message, payload);
3448
+ console.warn(message, payload);
3449
+ errorEmitter.next(error);
3450
+ },
3451
+ });
3452
+ const CALL_ACTIVE_PING_CALLBACKS_FN = functoolsKit.trycatch(beginTime(async (self, symbol, pending, timestamp, backtest) => {
3453
+ await ExecutionContextService.runInContext(async () => {
3454
+ const publicSignal = TO_PUBLIC_SIGNAL(pending);
3455
+ // Call system onActivePing callback first (emits to activePingSubject)
3456
+ await self.params.onActivePing(self.params.execution.context.symbol, self.params.method.context.strategyName, self.params.method.context.exchangeName, publicSignal, self.params.execution.context.backtest, timestamp);
3457
+ // Call user onActivePing callback only if signal is still active (not closed)
3458
+ if (self.params.callbacks?.onActivePing) {
3459
+ await self.params.callbacks.onActivePing(self.params.execution.context.symbol, publicSignal, new Date(timestamp), self.params.execution.context.backtest);
3417
3460
  }
3418
3461
  }, {
3419
3462
  when: new Date(timestamp),
@@ -3422,7 +3465,7 @@ const CALL_PING_CALLBACKS_FN = functoolsKit.trycatch(beginTime(async (self, symb
3422
3465
  });
3423
3466
  }), {
3424
3467
  fallback: (error) => {
3425
- const message = "ClientStrategy CALL_PING_CALLBACKS_FN thrown";
3468
+ const message = "ClientStrategy CALL_ACTIVE_PING_CALLBACKS_FN thrown";
3426
3469
  const payload = {
3427
3470
  error: functoolsKit.errorData(error),
3428
3471
  message: functoolsKit.getErrorMessage(error),
@@ -3794,10 +3837,10 @@ const CALL_BREAKEVEN_CLEAR_FN = functoolsKit.trycatch(beginTime(async (self, sym
3794
3837
  });
3795
3838
  const RETURN_SCHEDULED_SIGNAL_ACTIVE_FN = async (self, scheduled, currentPrice) => {
3796
3839
  const currentTime = self.params.execution.context.when.getTime();
3797
- await CALL_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, scheduled, currentTime, self.params.execution.context.backtest);
3840
+ await CALL_SCHEDULE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, scheduled, currentTime, self.params.execution.context.backtest);
3798
3841
  const pnl = toProfitLossDto(scheduled, currentPrice);
3799
3842
  const result = {
3800
- action: "active",
3843
+ action: "waiting",
3801
3844
  signal: TO_PUBLIC_SIGNAL(scheduled),
3802
3845
  currentPrice: currentPrice,
3803
3846
  strategyName: self.params.method.context.strategyName,
@@ -3924,6 +3967,7 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice) => {
3924
3967
  let percentTp = 0;
3925
3968
  let percentSl = 0;
3926
3969
  const currentTime = self.params.execution.context.when.getTime();
3970
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentTime, self.params.execution.context.backtest);
3927
3971
  // Calculate percentage of path to TP/SL for partial fill/loss callbacks
3928
3972
  {
3929
3973
  if (signal.position === "long") {
@@ -4129,7 +4173,7 @@ const PROCESS_SCHEDULED_SIGNAL_CANDLES_FN = async (self, scheduled, candles) =>
4129
4173
  const averagePrice = GET_AVG_PRICE_FN(recentCandles);
4130
4174
  // КРИТИЧНО: Проверяем был ли сигнал отменен пользователем через cancel()
4131
4175
  if (self._cancelledSignal) {
4132
- // Сигнал был отменен через cancel() в onPing
4176
+ // Сигнал был отменен через cancel() в onSchedulePing
4133
4177
  const result = await CANCEL_SCHEDULED_SIGNAL_IN_BACKTEST_FN(self, scheduled, averagePrice, candle.timestamp, "user");
4134
4178
  return { activated: false, cancelled: true, activationIndex: i, result };
4135
4179
  }
@@ -4186,7 +4230,7 @@ const PROCESS_SCHEDULED_SIGNAL_CANDLES_FN = async (self, scheduled, candles) =>
4186
4230
  result: null,
4187
4231
  };
4188
4232
  }
4189
- await CALL_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, scheduled, candle.timestamp, true);
4233
+ await CALL_SCHEDULE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, scheduled, candle.timestamp, true);
4190
4234
  }
4191
4235
  return {
4192
4236
  activated: false,
@@ -4212,6 +4256,7 @@ const PROCESS_PENDING_SIGNAL_CANDLES_FN = async (self, signal, candles) => {
4212
4256
  const startIndex = Math.max(0, i - (candlesCount - 1));
4213
4257
  const recentCandles = candles.slice(startIndex, i + 1);
4214
4258
  const averagePrice = GET_AVG_PRICE_FN(recentCandles);
4259
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentCandleTimestamp, true);
4215
4260
  let shouldClose = false;
4216
4261
  let closeReason;
4217
4262
  // Check time expiration FIRST (КРИТИЧНО!)
@@ -4757,7 +4802,15 @@ class ClientStrategy {
4757
4802
  return result;
4758
4803
  }
4759
4804
  if (activated) {
4760
- const remainingCandles = candles.slice(activationIndex + 1);
4805
+ // КРИТИЧНО: activationIndex - индекс свечи активации в массиве candles
4806
+ // BacktestLogicPrivateService включил буфер в начало массива, поэтому перед activationIndex достаточно свечей
4807
+ // PROCESS_PENDING_SIGNAL_CANDLES_FN пропустит первые bufferCandlesCount свечей для VWAP
4808
+ // Чтобы обработка началась со СЛЕДУЮЩЕЙ свечи после активации (activationIndex + 1),
4809
+ // нужно взять срез начиная с (activationIndex + 1 - bufferCandlesCount)
4810
+ // Это даст буфер ИЗ scheduled фазы + свеча после активации как первая обрабатываемая
4811
+ const bufferCandlesCount = GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT - 1;
4812
+ const sliceStart = Math.max(0, activationIndex + 1 - bufferCandlesCount);
4813
+ const remainingCandles = candles.slice(sliceStart);
4761
4814
  if (remainingCandles.length === 0) {
4762
4815
  const candlesCount = GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT;
4763
4816
  const recentCandles = candles.slice(Math.max(0, activationIndex - (candlesCount - 1)), activationIndex + 1);
@@ -4773,35 +4826,23 @@ class ClientStrategy {
4773
4826
  const lastCandleTimestamp = candles[candles.length - 1].timestamp;
4774
4827
  const elapsedTime = lastCandleTimestamp - scheduled.scheduledAt;
4775
4828
  if (elapsedTime < maxTimeToWait) {
4776
- // Timeout NOT reached yet - signal is still active (waiting for price)
4777
- // Return active result to continue monitoring in next backtest() call
4778
- const candlesCount = GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT;
4779
- const lastCandles = candles.slice(-candlesCount);
4780
- const lastPrice = GET_AVG_PRICE_FN(lastCandles);
4781
- this.params.logger.debug("ClientStrategy backtest scheduled signal still waiting (not expired)", {
4782
- symbol: this.params.execution.context.symbol,
4783
- signalId: scheduled.id,
4784
- elapsedMinutes: Math.floor(elapsedTime / 60000),
4785
- maxMinutes: GLOBAL_CONFIG.CC_SCHEDULE_AWAIT_MINUTES,
4786
- });
4787
- // Don't cancel - just return last active state
4788
- // In real backtest flow this won't happen as we process all candles at once,
4789
- // but this is correct behavior if someone calls backtest() with partial data
4790
- const pnl = toProfitLossDto(scheduled, lastPrice);
4791
- const result = {
4792
- action: "active",
4793
- signal: TO_PUBLIC_SIGNAL(scheduled),
4794
- currentPrice: lastPrice,
4795
- percentSl: 0,
4796
- percentTp: 0,
4797
- pnl,
4798
- strategyName: this.params.method.context.strategyName,
4799
- exchangeName: this.params.method.context.exchangeName,
4800
- frameName: this.params.method.context.frameName,
4801
- symbol: this.params.execution.context.symbol,
4802
- backtest: this.params.execution.context.backtest,
4803
- };
4804
- return result; // Cast to IStrategyBacktestResult (which includes Active)
4829
+ // EDGE CASE: backtest() called with partial candle data (should never happen in production)
4830
+ // In real backtest flow this won't happen as we process all candles at once
4831
+ // This indicates incorrect usage of backtest() - throw error instead of returning partial result
4832
+ const bufferCandlesCount = GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT - 1;
4833
+ // For scheduled signal that has NOT activated: buffer + wait time only (no lifetime yet)
4834
+ const requiredCandlesCount = bufferCandlesCount + GLOBAL_CONFIG.CC_SCHEDULE_AWAIT_MINUTES + 1;
4835
+ throw new Error(functoolsKit.str.newline(`ClientStrategy backtest: Insufficient candle data for scheduled signal (not yet activated). ` +
4836
+ `Signal scheduled at ${new Date(scheduled.scheduledAt).toISOString()}, ` +
4837
+ `last candle at ${new Date(lastCandleTimestamp).toISOString()}. ` +
4838
+ `Elapsed: ${Math.floor(elapsedTime / 60000)}min of ${GLOBAL_CONFIG.CC_SCHEDULE_AWAIT_MINUTES}min wait time. ` +
4839
+ `Provided ${candles.length} candles, but need at least ${requiredCandlesCount} candles. ` +
4840
+ `\nBreakdown: ` +
4841
+ `${bufferCandlesCount} buffer (VWAP) + ` +
4842
+ `${GLOBAL_CONFIG.CC_SCHEDULE_AWAIT_MINUTES} wait (for activation) = ${requiredCandlesCount} total. ` +
4843
+ `\nBuffer explanation: VWAP calculation requires ${GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT} candles, ` +
4844
+ `so first ${bufferCandlesCount} candles are skipped during scheduled phase processing. ` +
4845
+ `Provide complete candle range: [scheduledAt - ${bufferCandlesCount}min, scheduledAt + ${GLOBAL_CONFIG.CC_SCHEDULE_AWAIT_MINUTES}min].`));
4805
4846
  }
4806
4847
  // Timeout reached - cancel the scheduled signal
4807
4848
  const candlesCount = GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT;
@@ -4831,9 +4872,29 @@ class ClientStrategy {
4831
4872
  if (closedResult) {
4832
4873
  return closedResult;
4833
4874
  }
4875
+ // Signal didn't close during candle processing - check if we have enough data
4834
4876
  const lastCandles = candles.slice(-GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT);
4835
4877
  const lastPrice = GET_AVG_PRICE_FN(lastCandles);
4836
4878
  const closeTimestamp = lastCandles[lastCandles.length - 1].timestamp;
4879
+ const signalTime = signal.pendingAt;
4880
+ const maxTimeToWait = signal.minuteEstimatedTime * 60 * 1000;
4881
+ const elapsedTime = closeTimestamp - signalTime;
4882
+ // Check if we actually reached time expiration or just ran out of candles
4883
+ if (elapsedTime < maxTimeToWait) {
4884
+ // EDGE CASE: backtest() called with insufficient candle data
4885
+ const bufferCandlesCount = GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT - 1;
4886
+ const requiredCandlesCount = signal.minuteEstimatedTime + bufferCandlesCount + 1;
4887
+ throw new Error(functoolsKit.str.newline(`ClientStrategy backtest: Insufficient candle data for pending signal. ` +
4888
+ `Signal opened at ${new Date(signal.pendingAt).toISOString()}, ` +
4889
+ `last candle at ${new Date(closeTimestamp).toISOString()}. ` +
4890
+ `Elapsed: ${Math.floor(elapsedTime / 60000)}min of ${signal.minuteEstimatedTime}min required. ` +
4891
+ `Provided ${candles.length} candles, but need at least ${requiredCandlesCount} candles. ` +
4892
+ `\nBreakdown: ${signal.minuteEstimatedTime} candles for signal lifetime + ${bufferCandlesCount} buffer candles. ` +
4893
+ `\nBuffer explanation: VWAP calculation requires ${GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT} candles, ` +
4894
+ `so first ${bufferCandlesCount} candles are skipped to ensure accurate price averaging. ` +
4895
+ `Provide complete candle range: [pendingAt - ${bufferCandlesCount}min, pendingAt + ${signal.minuteEstimatedTime}min].`));
4896
+ }
4897
+ // Time actually expired - close with time_expired
4837
4898
  return await CLOSE_PENDING_SIGNAL_IN_BACKTEST_FN(this, signal, lastPrice, "time_expired", closeTimestamp);
4838
4899
  }
4839
4900
  /**
@@ -5622,6 +5683,9 @@ class ClientStrategy {
5622
5683
  const RISK_METHOD_NAME_GET_DATA = "RiskUtils.getData";
5623
5684
  const RISK_METHOD_NAME_GET_REPORT = "RiskUtils.getReport";
5624
5685
  const RISK_METHOD_NAME_DUMP = "RiskUtils.dump";
5686
+ const RISK_METHOD_NAME_CHECK_SIGNAL = "MergeRisk.checkSignal";
5687
+ const RISK_METHOD_NAME_ADD_SIGNAL = "MergeRisk.addSignal";
5688
+ const RISK_METHOD_NAME_REMOVE_SIGNAL = "MergeRisk.removeSignal";
5625
5689
  /**
5626
5690
  * Composite risk management class that combines multiple risk profiles.
5627
5691
  *
@@ -5677,7 +5741,7 @@ class MergeRisk {
5677
5741
  * @returns Promise resolving to true if all risks approve, false if any risk rejects
5678
5742
  */
5679
5743
  async checkSignal(params) {
5680
- backtest$1.loggerService.info("MergeRisk checkSignal", {
5744
+ backtest$1.loggerService.info(RISK_METHOD_NAME_CHECK_SIGNAL, {
5681
5745
  params,
5682
5746
  });
5683
5747
  for (const [riskName, risk] of Object.entries(this._riskMap)) {
@@ -5701,7 +5765,7 @@ class MergeRisk {
5701
5765
  * @returns Promise that resolves when all risks have registered the signal
5702
5766
  */
5703
5767
  async addSignal(symbol, context, positionData) {
5704
- backtest$1.loggerService.info("MergeRisk addSignal", {
5768
+ backtest$1.loggerService.info(RISK_METHOD_NAME_ADD_SIGNAL, {
5705
5769
  symbol,
5706
5770
  context,
5707
5771
  });
@@ -5718,7 +5782,7 @@ class MergeRisk {
5718
5782
  * @returns Promise that resolves when all risks have removed the signal
5719
5783
  */
5720
5784
  async removeSignal(symbol, context) {
5721
- backtest$1.loggerService.info("MergeRisk removeSignal", {
5785
+ backtest$1.loggerService.info(RISK_METHOD_NAME_REMOVE_SIGNAL, {
5722
5786
  symbol,
5723
5787
  context,
5724
5788
  });
@@ -6001,15 +6065,36 @@ const CREATE_KEY_FN$k = (symbol, strategyName, exchangeName, frameName, backtest
6001
6065
  return parts.join(":");
6002
6066
  };
6003
6067
  /**
6004
- * Creates a callback function for emitting ping events to pingSubject.
6068
+ * Creates a callback function for emitting schedule ping events to pingSubject.
6005
6069
  *
6006
6070
  * Called by ClientStrategy when a scheduled signal is being monitored every minute.
6007
6071
  * Emits PingContract event to all subscribers and calls ActionCoreService.
6008
6072
  *
6009
6073
  * @param self - Reference to StrategyConnectionService instance
6010
- * @returns Callback function for ping events
6074
+ * @returns Callback function for schedule ping events
6075
+ */
6076
+ const CREATE_COMMIT_SCHEDULE_PING_FN = (self) => async (symbol, strategyName, exchangeName, data, backtest, timestamp) => {
6077
+ const event = {
6078
+ symbol,
6079
+ strategyName,
6080
+ exchangeName,
6081
+ data,
6082
+ backtest,
6083
+ timestamp,
6084
+ };
6085
+ await schedulePingSubject.next(event);
6086
+ await self.actionCoreService.pingScheduled(backtest, event, { strategyName, exchangeName, frameName: data.frameName });
6087
+ };
6088
+ /**
6089
+ * Creates a callback function for emitting active ping events.
6090
+ *
6091
+ * Called by ClientStrategy when an active pending signal is being monitored every minute.
6092
+ * Placeholder for future activePingSubject implementation.
6093
+ *
6094
+ * @param self - Reference to StrategyConnectionService instance
6095
+ * @returns Callback function for active ping events
6011
6096
  */
6012
- const CREATE_COMMIT_PING_FN = (self) => async (symbol, strategyName, exchangeName, data, backtest, timestamp) => {
6097
+ const CREATE_COMMIT_ACTIVE_PING_FN = (self) => async (symbol, strategyName, exchangeName, data, backtest, timestamp) => {
6013
6098
  const event = {
6014
6099
  symbol,
6015
6100
  strategyName,
@@ -6018,8 +6103,8 @@ const CREATE_COMMIT_PING_FN = (self) => async (symbol, strategyName, exchangeNam
6018
6103
  backtest,
6019
6104
  timestamp,
6020
6105
  };
6021
- await pingSubject.next(event);
6022
- await self.actionCoreService.ping(backtest, event, { strategyName, exchangeName, frameName: data.frameName });
6106
+ await activePingSubject.next(event);
6107
+ await self.actionCoreService.pingActive(backtest, event, { strategyName, exchangeName, frameName: data.frameName });
6023
6108
  };
6024
6109
  /**
6025
6110
  * Creates a callback function for emitting init events.
@@ -6116,7 +6201,8 @@ class StrategyConnectionService {
6116
6201
  getSignal,
6117
6202
  callbacks,
6118
6203
  onInit: CREATE_COMMIT_INIT_FN(this),
6119
- onPing: CREATE_COMMIT_PING_FN(this),
6204
+ onSchedulePing: CREATE_COMMIT_SCHEDULE_PING_FN(this),
6205
+ onActivePing: CREATE_COMMIT_ACTIVE_PING_FN(this),
6120
6206
  onDispose: CREATE_COMMIT_DISPOSE_FN(this),
6121
6207
  });
6122
6208
  });
@@ -7509,8 +7595,8 @@ const CALL_SIGNAL_BACKTEST_CALLBACK_FN = functoolsKit.trycatch(async (self, even
7509
7595
  });
7510
7596
  /** Wrapper to call breakeven callback with error handling */
7511
7597
  const CALL_BREAKEVEN_CALLBACK_FN = functoolsKit.trycatch(async (self, event, strategyName, frameName, backtest) => {
7512
- if (self.params.callbacks?.onBreakeven) {
7513
- await self.params.callbacks.onBreakeven(event, self.params.actionName, strategyName, frameName, backtest);
7598
+ if (self.params.callbacks?.onBreakevenAvailable) {
7599
+ await self.params.callbacks.onBreakevenAvailable(event, self.params.actionName, strategyName, frameName, backtest);
7514
7600
  }
7515
7601
  }, {
7516
7602
  fallback: (error) => {
@@ -7526,8 +7612,8 @@ const CALL_BREAKEVEN_CALLBACK_FN = functoolsKit.trycatch(async (self, event, str
7526
7612
  });
7527
7613
  /** Wrapper to call partialProfit callback with error handling */
7528
7614
  const CALL_PARTIAL_PROFIT_CALLBACK_FN = functoolsKit.trycatch(async (self, event, strategyName, frameName, backtest) => {
7529
- if (self.params.callbacks?.onPartialProfit) {
7530
- await self.params.callbacks.onPartialProfit(event, self.params.actionName, strategyName, frameName, backtest);
7615
+ if (self.params.callbacks?.onPartialProfitAvailable) {
7616
+ await self.params.callbacks.onPartialProfitAvailable(event, self.params.actionName, strategyName, frameName, backtest);
7531
7617
  }
7532
7618
  }, {
7533
7619
  fallback: (error) => {
@@ -7543,8 +7629,8 @@ const CALL_PARTIAL_PROFIT_CALLBACK_FN = functoolsKit.trycatch(async (self, event
7543
7629
  });
7544
7630
  /** Wrapper to call partialLoss callback with error handling */
7545
7631
  const CALL_PARTIAL_LOSS_CALLBACK_FN = functoolsKit.trycatch(async (self, event, strategyName, frameName, backtest) => {
7546
- if (self.params.callbacks?.onPartialLoss) {
7547
- await self.params.callbacks.onPartialLoss(event, self.params.actionName, strategyName, frameName, backtest);
7632
+ if (self.params.callbacks?.onPartialLossAvailable) {
7633
+ await self.params.callbacks.onPartialLossAvailable(event, self.params.actionName, strategyName, frameName, backtest);
7548
7634
  }
7549
7635
  }, {
7550
7636
  fallback: (error) => {
@@ -7558,14 +7644,31 @@ const CALL_PARTIAL_LOSS_CALLBACK_FN = functoolsKit.trycatch(async (self, event,
7558
7644
  errorEmitter.next(error);
7559
7645
  },
7560
7646
  });
7561
- /** Wrapper to call ping callback with error handling */
7562
- const CALL_PING_CALLBACK_FN = functoolsKit.trycatch(async (self, event, strategyName, frameName, backtest) => {
7563
- if (self.params.callbacks?.onPing) {
7564
- await self.params.callbacks.onPing(event, self.params.actionName, strategyName, frameName, backtest);
7647
+ /** Wrapper to call scheduled ping callback with error handling */
7648
+ const CALL_PING_SCHEDULED_CALLBACK_FN = functoolsKit.trycatch(async (self, event, strategyName, frameName, backtest) => {
7649
+ if (self.params.callbacks?.onPingScheduled) {
7650
+ await self.params.callbacks.onPingScheduled(event, self.params.actionName, strategyName, frameName, backtest);
7651
+ }
7652
+ }, {
7653
+ fallback: (error) => {
7654
+ const message = "ClientAction CALL_PING_SCHEDULED_CALLBACK_FN thrown";
7655
+ const payload = {
7656
+ error: functoolsKit.errorData(error),
7657
+ message: functoolsKit.getErrorMessage(error),
7658
+ };
7659
+ backtest$1.loggerService.warn(message, payload);
7660
+ console.warn(message, payload);
7661
+ errorEmitter.next(error);
7662
+ },
7663
+ });
7664
+ /** Wrapper to call active ping callback with error handling */
7665
+ const CALL_PING_ACTIVE_CALLBACK_FN = functoolsKit.trycatch(async (self, event, strategyName, frameName, backtest) => {
7666
+ if (self.params.callbacks?.onPingActive) {
7667
+ await self.params.callbacks.onPingActive(event, self.params.actionName, strategyName, frameName, backtest);
7565
7668
  }
7566
7669
  }, {
7567
7670
  fallback: (error) => {
7568
- const message = "ClientAction CALL_PING_CALLBACK_FN thrown";
7671
+ const message = "ClientAction CALL_PING_ACTIVE_CALLBACK_FN thrown";
7569
7672
  const payload = {
7570
7673
  error: functoolsKit.errorData(error),
7571
7674
  message: functoolsKit.getErrorMessage(error),
@@ -7640,6 +7743,7 @@ const CREATE_HANDLER_FN = (self) => {
7640
7743
  self.params.strategyName,
7641
7744
  self.params.frameName,
7642
7745
  self.params.actionName,
7746
+ self.params.backtest,
7643
7747
  ]);
7644
7748
  }
7645
7749
  return self.params.handler;
@@ -7831,8 +7935,8 @@ class ClientAction {
7831
7935
  /**
7832
7936
  * Handles breakeven events when stop-loss is moved to entry price.
7833
7937
  */
7834
- async breakeven(event) {
7835
- this.params.logger.debug("ClientAction breakeven", {
7938
+ async breakevenAvailable(event) {
7939
+ this.params.logger.debug("ClientAction breakevenAvailable", {
7836
7940
  actionName: this.params.actionName,
7837
7941
  strategyName: this.params.strategyName,
7838
7942
  frameName: this.params.frameName,
@@ -7841,8 +7945,8 @@ class ClientAction {
7841
7945
  await this.waitForInit();
7842
7946
  }
7843
7947
  // Call handler method if defined
7844
- if (this._handlerInstance?.breakeven) {
7845
- await this._handlerInstance.breakeven(event);
7948
+ if (this._handlerInstance?.breakevenAvailable) {
7949
+ await this._handlerInstance.breakevenAvailable(event);
7846
7950
  }
7847
7951
  // Call callback if defined
7848
7952
  await CALL_BREAKEVEN_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
@@ -7851,8 +7955,8 @@ class ClientAction {
7851
7955
  /**
7852
7956
  * Handles partial profit level events (10%, 20%, 30%, etc).
7853
7957
  */
7854
- async partialProfit(event) {
7855
- this.params.logger.debug("ClientAction partialProfit", {
7958
+ async partialProfitAvailable(event) {
7959
+ this.params.logger.debug("ClientAction partialProfitAvailable", {
7856
7960
  actionName: this.params.actionName,
7857
7961
  strategyName: this.params.strategyName,
7858
7962
  frameName: this.params.frameName,
@@ -7861,8 +7965,8 @@ class ClientAction {
7861
7965
  await this.waitForInit();
7862
7966
  }
7863
7967
  // Call handler method if defined
7864
- if (this._handlerInstance?.partialProfit) {
7865
- await this._handlerInstance.partialProfit(event);
7968
+ if (this._handlerInstance?.partialProfitAvailable) {
7969
+ await this._handlerInstance.partialProfitAvailable(event);
7866
7970
  }
7867
7971
  // Call callback if defined
7868
7972
  await CALL_PARTIAL_PROFIT_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
@@ -7871,8 +7975,8 @@ class ClientAction {
7871
7975
  /**
7872
7976
  * Handles partial loss level events (-10%, -20%, -30%, etc).
7873
7977
  */
7874
- async partialLoss(event) {
7875
- this.params.logger.debug("ClientAction partialLoss", {
7978
+ async partialLossAvailable(event) {
7979
+ this.params.logger.debug("ClientAction partialLossAvailable", {
7876
7980
  actionName: this.params.actionName,
7877
7981
  strategyName: this.params.strategyName,
7878
7982
  frameName: this.params.frameName,
@@ -7881,18 +7985,38 @@ class ClientAction {
7881
7985
  await this.waitForInit();
7882
7986
  }
7883
7987
  // Call handler method if defined
7884
- if (this._handlerInstance?.partialLoss) {
7885
- await this._handlerInstance.partialLoss(event);
7988
+ if (this._handlerInstance?.partialLossAvailable) {
7989
+ await this._handlerInstance.partialLossAvailable(event);
7886
7990
  }
7887
7991
  // Call callback if defined
7888
7992
  await CALL_PARTIAL_LOSS_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
7889
7993
  }
7890
7994
  ;
7891
7995
  /**
7892
- * Handles ping events during scheduled signal monitoring.
7996
+ * Handles scheduled ping events during scheduled signal monitoring.
7997
+ */
7998
+ async pingScheduled(event) {
7999
+ this.params.logger.debug("ClientAction pingScheduled", {
8000
+ actionName: this.params.actionName,
8001
+ strategyName: this.params.strategyName,
8002
+ frameName: this.params.frameName,
8003
+ });
8004
+ if (!this._handlerInstance) {
8005
+ await this.waitForInit();
8006
+ }
8007
+ // Call handler method if defined
8008
+ if (this._handlerInstance?.pingScheduled) {
8009
+ await this._handlerInstance.pingScheduled(event);
8010
+ }
8011
+ // Call callback if defined
8012
+ await CALL_PING_SCHEDULED_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
8013
+ }
8014
+ ;
8015
+ /**
8016
+ * Handles active ping events during active pending signal monitoring.
7893
8017
  */
7894
- async ping(event) {
7895
- this.params.logger.debug("ClientAction ping", {
8018
+ async pingActive(event) {
8019
+ this.params.logger.debug("ClientAction pingActive", {
7896
8020
  actionName: this.params.actionName,
7897
8021
  strategyName: this.params.strategyName,
7898
8022
  frameName: this.params.frameName,
@@ -7901,11 +8025,11 @@ class ClientAction {
7901
8025
  await this.waitForInit();
7902
8026
  }
7903
8027
  // Call handler method if defined
7904
- if (this._handlerInstance?.ping) {
7905
- await this._handlerInstance.ping(event);
8028
+ if (this._handlerInstance?.pingActive) {
8029
+ await this._handlerInstance.pingActive(event);
7906
8030
  }
7907
8031
  // Call callback if defined
7908
- await CALL_PING_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
8032
+ await CALL_PING_ACTIVE_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
7909
8033
  }
7910
8034
  ;
7911
8035
  /**
@@ -8073,13 +8197,13 @@ class ActionConnectionService {
8073
8197
  * @param backtest - Whether running in backtest mode
8074
8198
  * @param context - Execution context with action name, strategy name, exchange name, frame name
8075
8199
  */
8076
- this.breakeven = async (event, backtest, context) => {
8077
- this.loggerService.log("actionConnectionService breakeven", {
8200
+ this.breakevenAvailable = async (event, backtest, context) => {
8201
+ this.loggerService.log("actionConnectionService breakevenAvailable", {
8078
8202
  backtest,
8079
8203
  context,
8080
8204
  });
8081
8205
  const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
8082
- await action.breakeven(event);
8206
+ await action.breakevenAvailable(event);
8083
8207
  };
8084
8208
  /**
8085
8209
  * Routes partialProfit event to appropriate ClientAction instance.
@@ -8088,13 +8212,13 @@ class ActionConnectionService {
8088
8212
  * @param backtest - Whether running in backtest mode
8089
8213
  * @param context - Execution context with action name, strategy name, exchange name, frame name
8090
8214
  */
8091
- this.partialProfit = async (event, backtest, context) => {
8092
- this.loggerService.log("actionConnectionService partialProfit", {
8215
+ this.partialProfitAvailable = async (event, backtest, context) => {
8216
+ this.loggerService.log("actionConnectionService partialProfitAvailable", {
8093
8217
  backtest,
8094
8218
  context,
8095
8219
  });
8096
8220
  const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
8097
- await action.partialProfit(event);
8221
+ await action.partialProfitAvailable(event);
8098
8222
  };
8099
8223
  /**
8100
8224
  * Routes partialLoss event to appropriate ClientAction instance.
@@ -8103,28 +8227,43 @@ class ActionConnectionService {
8103
8227
  * @param backtest - Whether running in backtest mode
8104
8228
  * @param context - Execution context with action name, strategy name, exchange name, frame name
8105
8229
  */
8106
- this.partialLoss = async (event, backtest, context) => {
8107
- this.loggerService.log("actionConnectionService partialLoss", {
8230
+ this.partialLossAvailable = async (event, backtest, context) => {
8231
+ this.loggerService.log("actionConnectionService partialLossAvailable", {
8232
+ backtest,
8233
+ context,
8234
+ });
8235
+ const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
8236
+ await action.partialLossAvailable(event);
8237
+ };
8238
+ /**
8239
+ * Routes scheduled ping event to appropriate ClientAction instance.
8240
+ *
8241
+ * @param event - Scheduled ping event data
8242
+ * @param backtest - Whether running in backtest mode
8243
+ * @param context - Execution context with action name, strategy name, exchange name, frame name
8244
+ */
8245
+ this.pingScheduled = async (event, backtest, context) => {
8246
+ this.loggerService.log("actionConnectionService pingScheduled", {
8108
8247
  backtest,
8109
8248
  context,
8110
8249
  });
8111
8250
  const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
8112
- await action.partialLoss(event);
8251
+ await action.pingScheduled(event);
8113
8252
  };
8114
8253
  /**
8115
- * Routes ping event to appropriate ClientAction instance.
8254
+ * Routes active ping event to appropriate ClientAction instance.
8116
8255
  *
8117
- * @param event - Ping event data
8256
+ * @param event - Active ping event data
8118
8257
  * @param backtest - Whether running in backtest mode
8119
8258
  * @param context - Execution context with action name, strategy name, exchange name, frame name
8120
8259
  */
8121
- this.ping = async (event, backtest, context) => {
8122
- this.loggerService.log("actionConnectionService ping", {
8260
+ this.pingActive = async (event, backtest, context) => {
8261
+ this.loggerService.log("actionConnectionService pingActive", {
8123
8262
  backtest,
8124
8263
  context,
8125
8264
  });
8126
8265
  const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
8127
- await action.ping(event);
8266
+ await action.pingActive(event);
8128
8267
  };
8129
8268
  /**
8130
8269
  * Routes riskRejection event to appropriate ClientAction instance.
@@ -9188,81 +9327,102 @@ class ActionCoreService {
9188
9327
  * Routes breakeven event to all registered actions for the strategy.
9189
9328
  *
9190
9329
  * Retrieves action list from strategy schema (IStrategySchema.actions)
9191
- * and invokes the breakeven handler on each ClientAction instance sequentially.
9330
+ * and invokes the breakevenAvailable handler on each ClientAction instance sequentially.
9192
9331
  *
9193
9332
  * @param backtest - Whether running in backtest mode (true) or live mode (false)
9194
9333
  * @param event - Breakeven milestone data (stop-loss moved to entry price)
9195
9334
  * @param context - Strategy execution context with strategyName, exchangeName, frameName
9196
9335
  */
9197
- this.breakeven = async (backtest, event, context) => {
9198
- this.loggerService.log("actionCoreService breakeven", {
9336
+ this.breakevenAvailable = async (backtest, event, context) => {
9337
+ this.loggerService.log("actionCoreService breakevenAvailable", {
9199
9338
  context,
9200
9339
  });
9201
9340
  await this.validate(context);
9202
9341
  const { actions = [] } = this.strategySchemaService.get(context.strategyName);
9203
9342
  for (const actionName of actions) {
9204
- await this.actionConnectionService.breakeven(event, backtest, { actionName, ...context });
9343
+ await this.actionConnectionService.breakevenAvailable(event, backtest, { actionName, ...context });
9205
9344
  }
9206
9345
  };
9207
9346
  /**
9208
9347
  * Routes partial profit event to all registered actions for the strategy.
9209
9348
  *
9210
9349
  * Retrieves action list from strategy schema (IStrategySchema.actions)
9211
- * and invokes the partialProfit handler on each ClientAction instance sequentially.
9350
+ * and invokes the partialProfitAvailable handler on each ClientAction instance sequentially.
9212
9351
  *
9213
9352
  * @param backtest - Whether running in backtest mode (true) or live mode (false)
9214
9353
  * @param event - Profit milestone data with level (10%, 20%, etc.) and price
9215
9354
  * @param context - Strategy execution context with strategyName, exchangeName, frameName
9216
9355
  */
9217
- this.partialProfit = async (backtest, event, context) => {
9218
- this.loggerService.log("actionCoreService partialProfit", {
9356
+ this.partialProfitAvailable = async (backtest, event, context) => {
9357
+ this.loggerService.log("actionCoreService partialProfitAvailable", {
9219
9358
  context,
9220
9359
  });
9221
9360
  await this.validate(context);
9222
9361
  const { actions = [] } = this.strategySchemaService.get(context.strategyName);
9223
9362
  for (const actionName of actions) {
9224
- await this.actionConnectionService.partialProfit(event, backtest, { actionName, ...context });
9363
+ await this.actionConnectionService.partialProfitAvailable(event, backtest, { actionName, ...context });
9225
9364
  }
9226
9365
  };
9227
9366
  /**
9228
9367
  * Routes partial loss event to all registered actions for the strategy.
9229
9368
  *
9230
9369
  * Retrieves action list from strategy schema (IStrategySchema.actions)
9231
- * and invokes the partialLoss handler on each ClientAction instance sequentially.
9370
+ * and invokes the partialLossAvailable handler on each ClientAction instance sequentially.
9232
9371
  *
9233
9372
  * @param backtest - Whether running in backtest mode (true) or live mode (false)
9234
9373
  * @param event - Loss milestone data with level (-10%, -20%, etc.) and price
9235
9374
  * @param context - Strategy execution context with strategyName, exchangeName, frameName
9236
9375
  */
9237
- this.partialLoss = async (backtest, event, context) => {
9238
- this.loggerService.log("actionCoreService partialLoss", {
9376
+ this.partialLossAvailable = async (backtest, event, context) => {
9377
+ this.loggerService.log("actionCoreService partialLossAvailable", {
9239
9378
  context,
9240
9379
  });
9241
9380
  await this.validate(context);
9242
9381
  const { actions = [] } = this.strategySchemaService.get(context.strategyName);
9243
9382
  for (const actionName of actions) {
9244
- await this.actionConnectionService.partialLoss(event, backtest, { actionName, ...context });
9383
+ await this.actionConnectionService.partialLossAvailable(event, backtest, { actionName, ...context });
9245
9384
  }
9246
9385
  };
9247
9386
  /**
9248
- * Routes ping event to all registered actions for the strategy.
9387
+ * Routes scheduled ping event to all registered actions for the strategy.
9249
9388
  *
9250
9389
  * Retrieves action list from strategy schema (IStrategySchema.actions)
9251
- * and invokes the ping handler on each ClientAction instance sequentially.
9390
+ * and invokes the pingScheduled handler on each ClientAction instance sequentially.
9252
9391
  * Called every minute during scheduled signal monitoring.
9253
9392
  *
9254
9393
  * @param backtest - Whether running in backtest mode (true) or live mode (false)
9255
9394
  * @param event - Scheduled signal monitoring data
9256
9395
  * @param context - Strategy execution context with strategyName, exchangeName, frameName
9257
9396
  */
9258
- this.ping = async (backtest, event, context) => {
9259
- this.loggerService.log("actionCoreService ping", {
9397
+ this.pingScheduled = async (backtest, event, context) => {
9398
+ this.loggerService.log("actionCoreService pingScheduled", {
9399
+ context,
9400
+ });
9401
+ await this.validate(context);
9402
+ const { actions = [] } = this.strategySchemaService.get(context.strategyName);
9403
+ for (const actionName of actions) {
9404
+ await this.actionConnectionService.pingScheduled(event, backtest, { actionName, ...context });
9405
+ }
9406
+ };
9407
+ /**
9408
+ * Routes active ping event to all registered actions for the strategy.
9409
+ *
9410
+ * Retrieves action list from strategy schema (IStrategySchema.actions)
9411
+ * and invokes the pingActive handler on each ClientAction instance sequentially.
9412
+ * Called every minute during active pending signal monitoring.
9413
+ *
9414
+ * @param backtest - Whether running in backtest mode (true) or live mode (false)
9415
+ * @param event - Active pending signal monitoring data
9416
+ * @param context - Strategy execution context with strategyName, exchangeName, frameName
9417
+ */
9418
+ this.pingActive = async (backtest, event, context) => {
9419
+ this.loggerService.log("actionCoreService pingActive", {
9260
9420
  context,
9261
9421
  });
9262
9422
  await this.validate(context);
9263
9423
  const { actions = [] } = this.strategySchemaService.get(context.strategyName);
9264
9424
  for (const actionName of actions) {
9265
- await this.actionConnectionService.ping(event, backtest, { actionName, ...context });
9425
+ await this.actionConnectionService.pingActive(event, backtest, { actionName, ...context });
9266
9426
  }
9267
9427
  };
9268
9428
  /**
@@ -10381,7 +10541,11 @@ class LiveLogicPrivateService {
10381
10541
  await functoolsKit.sleep(TICK_TTL);
10382
10542
  continue;
10383
10543
  }
10384
- // Yield opened, closed results
10544
+ if (result.action === "waiting") {
10545
+ await functoolsKit.sleep(TICK_TTL);
10546
+ continue;
10547
+ }
10548
+ // Yield opened, closed, cancelled results
10385
10549
  yield result;
10386
10550
  // Check if strategy should stop after signal is closed
10387
10551
  if (result.action === "closed") {
@@ -12316,6 +12480,12 @@ var _a$1, _b$1;
12316
12480
  const MARKDOWN_METHOD_NAME_ENABLE = "MarkdownUtils.enable";
12317
12481
  const MARKDOWN_METHOD_NAME_DISABLE = "MarkdownUtils.disable";
12318
12482
  const MARKDOWN_METHOD_NAME_USE_ADAPTER = "MarkdownAdapter.useMarkdownAdapter";
12483
+ const MARKDOWN_METHOD_NAME_FILE_DUMP = "MarkdownFileAdapter.dump";
12484
+ const MARKDOWN_METHOD_NAME_FOLDER_DUMP = "MarkdownFolderAdapter.dump";
12485
+ const MARKDOWN_METHOD_NAME_WRITE_DATA = "MarkdownAdapter.writeData";
12486
+ const MARKDOWN_METHOD_NAME_USE_MD = "MarkdownAdapter.useMd";
12487
+ const MARKDOWN_METHOD_NAME_USE_JSONL = "MarkdownAdapter.useJsonl";
12488
+ const MARKDOWN_METHOD_NAME_USE_DUMMY = "MarkdownAdapter.useDummy";
12319
12489
  const WAIT_FOR_INIT_SYMBOL$1 = Symbol("wait-for-init");
12320
12490
  const WRITE_SAFE_SYMBOL$1 = Symbol("write-safe");
12321
12491
  /**
@@ -12409,7 +12579,7 @@ class MarkdownFileBase {
12409
12579
  * @throws Error if stream not initialized or write timeout exceeded
12410
12580
  */
12411
12581
  async dump(data, options) {
12412
- backtest$1.loggerService.debug("MarkdownFileAdapter.dump", {
12582
+ backtest$1.loggerService.debug(MARKDOWN_METHOD_NAME_FILE_DUMP, {
12413
12583
  markdownName: this.markdownName,
12414
12584
  options,
12415
12585
  });
@@ -12491,7 +12661,7 @@ class MarkdownFolderBase {
12491
12661
  * @throws Error if directory creation or file write fails
12492
12662
  */
12493
12663
  async dump(content, options) {
12494
- backtest$1.loggerService.debug("MarkdownFolderAdapter.dump", {
12664
+ backtest$1.loggerService.debug(MARKDOWN_METHOD_NAME_FOLDER_DUMP, {
12495
12665
  markdownName: this.markdownName,
12496
12666
  options,
12497
12667
  });
@@ -12731,7 +12901,7 @@ class MarkdownAdapter extends MarkdownUtils {
12731
12901
  * @internal - Use service-specific dump methods instead (e.g., Backtest.dump)
12732
12902
  */
12733
12903
  async writeData(markdownName, content, options) {
12734
- backtest$1.loggerService.debug("MarkdownAdapter.writeData", {
12904
+ backtest$1.loggerService.debug(MARKDOWN_METHOD_NAME_WRITE_DATA, {
12735
12905
  markdownName,
12736
12906
  options,
12737
12907
  });
@@ -12746,7 +12916,7 @@ class MarkdownAdapter extends MarkdownUtils {
12746
12916
  * Each dump creates a separate .md file.
12747
12917
  */
12748
12918
  useMd() {
12749
- backtest$1.loggerService.debug("MarkdownAdapter.useMd");
12919
+ backtest$1.loggerService.debug(MARKDOWN_METHOD_NAME_USE_MD);
12750
12920
  this.useMarkdownAdapter(MarkdownFolderBase);
12751
12921
  }
12752
12922
  /**
@@ -12755,7 +12925,7 @@ class MarkdownAdapter extends MarkdownUtils {
12755
12925
  * All dumps append to a single .jsonl file per markdown type.
12756
12926
  */
12757
12927
  useJsonl() {
12758
- backtest$1.loggerService.debug("MarkdownAdapter.useJsonl");
12928
+ backtest$1.loggerService.debug(MARKDOWN_METHOD_NAME_USE_JSONL);
12759
12929
  this.useMarkdownAdapter(MarkdownFileBase);
12760
12930
  }
12761
12931
  /**
@@ -12763,7 +12933,7 @@ class MarkdownAdapter extends MarkdownUtils {
12763
12933
  * All future markdown writes will be no-ops.
12764
12934
  */
12765
12935
  useDummy() {
12766
- backtest$1.loggerService.debug("MarkdownAdapter.useDummy");
12936
+ backtest$1.loggerService.debug(MARKDOWN_METHOD_NAME_USE_DUMMY);
12767
12937
  this.useMarkdownAdapter(MarkdownDummy);
12768
12938
  }
12769
12939
  }
@@ -13426,6 +13596,98 @@ let ReportStorage$5 = class ReportStorage {
13426
13596
  this._eventList.pop();
13427
13597
  }
13428
13598
  }
13599
+ /**
13600
+ * Adds a scheduled event to the storage.
13601
+ *
13602
+ * @param data - Scheduled tick result
13603
+ */
13604
+ addScheduledEvent(data) {
13605
+ this._eventList.unshift({
13606
+ timestamp: data.signal.scheduledAt,
13607
+ action: "scheduled",
13608
+ symbol: data.signal.symbol,
13609
+ signalId: data.signal.id,
13610
+ position: data.signal.position,
13611
+ note: data.signal.note,
13612
+ currentPrice: data.currentPrice,
13613
+ priceOpen: data.signal.priceOpen,
13614
+ priceTakeProfit: data.signal.priceTakeProfit,
13615
+ priceStopLoss: data.signal.priceStopLoss,
13616
+ originalPriceTakeProfit: data.signal.originalPriceTakeProfit,
13617
+ originalPriceStopLoss: data.signal.originalPriceStopLoss,
13618
+ totalExecuted: data.signal.totalExecuted,
13619
+ });
13620
+ // Trim queue if exceeded MAX_EVENTS
13621
+ if (this._eventList.length > MAX_EVENTS$6) {
13622
+ this._eventList.pop();
13623
+ }
13624
+ }
13625
+ /**
13626
+ * Adds a waiting event to the storage.
13627
+ * Replaces the last waiting event with the same signalId.
13628
+ *
13629
+ * @param data - Waiting tick result
13630
+ */
13631
+ addWaitingEvent(data) {
13632
+ const newEvent = {
13633
+ timestamp: Date.now(),
13634
+ action: "waiting",
13635
+ symbol: data.signal.symbol,
13636
+ signalId: data.signal.id,
13637
+ position: data.signal.position,
13638
+ note: data.signal.note,
13639
+ currentPrice: data.currentPrice,
13640
+ priceOpen: data.signal.priceOpen,
13641
+ priceTakeProfit: data.signal.priceTakeProfit,
13642
+ priceStopLoss: data.signal.priceStopLoss,
13643
+ originalPriceTakeProfit: data.signal.originalPriceTakeProfit,
13644
+ originalPriceStopLoss: data.signal.originalPriceStopLoss,
13645
+ totalExecuted: data.signal.totalExecuted,
13646
+ percentTp: data.percentTp,
13647
+ percentSl: data.percentSl,
13648
+ pnl: data.pnl.pnlPercentage,
13649
+ };
13650
+ // Find the last waiting event with the same signalId
13651
+ const lastWaitingIndex = this._eventList.findLastIndex((event) => event.action === "waiting" && event.signalId === data.signal.id);
13652
+ // Replace the last waiting event with the same signalId
13653
+ if (lastWaitingIndex !== -1) {
13654
+ this._eventList[lastWaitingIndex] = newEvent;
13655
+ return;
13656
+ }
13657
+ // If no previous waiting event found, add new event
13658
+ this._eventList.unshift(newEvent);
13659
+ // Trim queue if exceeded MAX_EVENTS
13660
+ if (this._eventList.length > MAX_EVENTS$6) {
13661
+ this._eventList.pop();
13662
+ }
13663
+ }
13664
+ /**
13665
+ * Adds a cancelled event to the storage.
13666
+ *
13667
+ * @param data - Cancelled tick result
13668
+ */
13669
+ addCancelledEvent(data) {
13670
+ this._eventList.unshift({
13671
+ timestamp: data.closeTimestamp,
13672
+ action: "cancelled",
13673
+ symbol: data.signal.symbol,
13674
+ signalId: data.signal.id,
13675
+ position: data.signal.position,
13676
+ note: data.signal.note,
13677
+ currentPrice: data.currentPrice,
13678
+ priceOpen: data.signal.priceOpen,
13679
+ priceTakeProfit: data.signal.priceTakeProfit,
13680
+ priceStopLoss: data.signal.priceStopLoss,
13681
+ originalPriceTakeProfit: data.signal.originalPriceTakeProfit,
13682
+ originalPriceStopLoss: data.signal.originalPriceStopLoss,
13683
+ totalExecuted: data.signal.totalExecuted,
13684
+ cancelReason: data.reason,
13685
+ });
13686
+ // Trim queue if exceeded MAX_EVENTS
13687
+ if (this._eventList.length > MAX_EVENTS$6) {
13688
+ this._eventList.pop();
13689
+ }
13690
+ }
13429
13691
  /**
13430
13692
  * Calculates statistical data from live trading events (Controller).
13431
13693
  * Returns null for any unsafe numeric values (NaN, Infinity, etc).
@@ -13683,6 +13945,12 @@ class LiveMarkdownService {
13683
13945
  if (data.action === "idle") {
13684
13946
  storage.addIdleEvent(data.currentPrice);
13685
13947
  }
13948
+ else if (data.action === "scheduled") {
13949
+ storage.addScheduledEvent(data);
13950
+ }
13951
+ else if (data.action === "waiting") {
13952
+ storage.addWaitingEvent(data);
13953
+ }
13686
13954
  else if (data.action === "opened") {
13687
13955
  storage.addOpenedEvent(data);
13688
13956
  }
@@ -13692,6 +13960,9 @@ class LiveMarkdownService {
13692
13960
  else if (data.action === "closed") {
13693
13961
  storage.addClosedEvent(data);
13694
13962
  }
13963
+ else if (data.action === "cancelled") {
13964
+ storage.addCancelledEvent(data);
13965
+ }
13695
13966
  };
13696
13967
  /**
13697
13968
  * Gets statistical data from all live trading events for a symbol-strategy pair.
@@ -18118,7 +18389,7 @@ const CREATE_COMMIT_PROFIT_FN = (self) => async (symbol, strategyName, exchangeN
18118
18389
  timestamp,
18119
18390
  };
18120
18391
  await partialProfitSubject.next(event);
18121
- await self.actionCoreService.partialProfit(backtest, event, { strategyName, exchangeName, frameName });
18392
+ await self.actionCoreService.partialProfitAvailable(backtest, event, { strategyName, exchangeName, frameName });
18122
18393
  };
18123
18394
  /**
18124
18395
  * Creates a callback function for emitting loss events to partialLossSubject.
@@ -18142,7 +18413,7 @@ const CREATE_COMMIT_LOSS_FN = (self) => async (symbol, strategyName, exchangeNam
18142
18413
  timestamp,
18143
18414
  };
18144
18415
  await partialLossSubject.next(event);
18145
- await self.actionCoreService.partialLoss(backtest, event, { strategyName, exchangeName, frameName });
18416
+ await self.actionCoreService.partialLossAvailable(backtest, event, { strategyName, exchangeName, frameName });
18146
18417
  };
18147
18418
  /**
18148
18419
  * Connection service for partial profit/loss tracking.
@@ -19291,7 +19562,7 @@ const CREATE_COMMIT_BREAKEVEN_FN = (self) => async (symbol, strategyName, exchan
19291
19562
  timestamp,
19292
19563
  };
19293
19564
  await breakevenSubject.next(event);
19294
- await self.actionCoreService.breakeven(backtest, event, { strategyName, exchangeName, frameName });
19565
+ await self.actionCoreService.breakevenAvailable(backtest, event, { strategyName, exchangeName, frameName });
19295
19566
  };
19296
19567
  /**
19297
19568
  * Connection service for breakeven tracking.
@@ -21376,6 +21647,43 @@ class LiveReportService {
21376
21647
  if (data.action === "idle") {
21377
21648
  await Report.writeData("live", baseEvent, searchOptions);
21378
21649
  }
21650
+ else if (data.action === "scheduled") {
21651
+ await Report.writeData("live", {
21652
+ ...baseEvent,
21653
+ signalId: data.signal?.id,
21654
+ position: data.signal?.position,
21655
+ note: data.signal?.note,
21656
+ priceOpen: data.signal?.priceOpen,
21657
+ priceTakeProfit: data.signal?.priceTakeProfit,
21658
+ priceStopLoss: data.signal?.priceStopLoss,
21659
+ originalPriceTakeProfit: data.signal?.originalPriceTakeProfit,
21660
+ originalPriceStopLoss: data.signal?.originalPriceStopLoss,
21661
+ totalExecuted: data.signal?.totalExecuted,
21662
+ scheduledAt: data.signal?.scheduledAt,
21663
+ minuteEstimatedTime: data.signal?.minuteEstimatedTime,
21664
+ }, { ...searchOptions, signalId: data.signal?.id });
21665
+ }
21666
+ else if (data.action === "waiting") {
21667
+ await Report.writeData("live", {
21668
+ ...baseEvent,
21669
+ signalId: data.signal?.id,
21670
+ position: data.signal?.position,
21671
+ note: data.signal?.note,
21672
+ priceOpen: data.signal?.priceOpen,
21673
+ priceTakeProfit: data.signal?.priceTakeProfit,
21674
+ priceStopLoss: data.signal?.priceStopLoss,
21675
+ originalPriceTakeProfit: data.signal?.originalPriceTakeProfit,
21676
+ originalPriceStopLoss: data.signal?.originalPriceStopLoss,
21677
+ totalExecuted: data.signal?.totalExecuted,
21678
+ scheduledAt: data.signal?.scheduledAt,
21679
+ minuteEstimatedTime: data.signal?.minuteEstimatedTime,
21680
+ percentTp: data.percentTp,
21681
+ percentSl: data.percentSl,
21682
+ pnl: data.pnl.pnlPercentage,
21683
+ pnlPriceOpen: data.pnl.priceOpen,
21684
+ pnlPriceClose: data.pnl.priceClose,
21685
+ }, { ...searchOptions, signalId: data.signal?.id });
21686
+ }
21379
21687
  else if (data.action === "opened") {
21380
21688
  await Report.writeData("live", {
21381
21689
  ...baseEvent,
@@ -21442,6 +21750,24 @@ class LiveReportService {
21442
21750
  closeTime: data.closeTimestamp,
21443
21751
  }, { ...searchOptions, signalId: data.signal?.id });
21444
21752
  }
21753
+ else if (data.action === "cancelled") {
21754
+ await Report.writeData("live", {
21755
+ ...baseEvent,
21756
+ signalId: data.signal?.id,
21757
+ position: data.signal?.position,
21758
+ note: data.signal?.note,
21759
+ priceOpen: data.signal?.priceOpen,
21760
+ priceTakeProfit: data.signal?.priceTakeProfit,
21761
+ priceStopLoss: data.signal?.priceStopLoss,
21762
+ originalPriceTakeProfit: data.signal?.originalPriceTakeProfit,
21763
+ originalPriceStopLoss: data.signal?.originalPriceStopLoss,
21764
+ totalExecuted: data.signal?.totalExecuted,
21765
+ scheduledAt: data.signal?.scheduledAt,
21766
+ minuteEstimatedTime: data.signal?.minuteEstimatedTime,
21767
+ cancelReason: data.reason,
21768
+ closeTime: data.closeTimestamp,
21769
+ }, { ...searchOptions, signalId: data.signal?.id });
21770
+ }
21445
21771
  };
21446
21772
  /**
21447
21773
  * Subscribes to live signal emitter to receive tick events.
@@ -22631,6 +22957,27 @@ const backtest = {
22631
22957
  init();
22632
22958
  var backtest$1 = backtest;
22633
22959
 
22960
+ const GET_TIMEFRAME_METHOD_NAME = "get.getBacktestTimeframe";
22961
+ /**
22962
+ * Retrieves current backtest timeframe for given symbol.
22963
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
22964
+ * @returns Promise resolving to array of Date objects representing tick timestamps
22965
+ * @throws Error if called outside of backtest execution context
22966
+ */
22967
+ async function getBacktestTimeframe(symbol) {
22968
+ backtest$1.loggerService.info(GET_TIMEFRAME_METHOD_NAME, { symbol });
22969
+ if (!ExecutionContextService.hasContext()) {
22970
+ throw new Error("getBacktestTimeframe requires an execution context");
22971
+ }
22972
+ if (!MethodContextService.hasContext()) {
22973
+ throw new Error("getBacktestTimeframe requires a method context");
22974
+ }
22975
+ if (!backtest$1.executionContextService.context.backtest) {
22976
+ throw new Error("getBacktestTimeframe can only be used during backtest execution");
22977
+ }
22978
+ return await backtest$1.frameCoreService.getTimeframe(symbol, backtest$1.methodContextService.context.frameName);
22979
+ }
22980
+
22634
22981
  const METHOD_NAME = "validate.validate";
22635
22982
  /**
22636
22983
  * Retrieves all registered exchanges as a map
@@ -22826,12 +23173,197 @@ async function validate(args = {}) {
22826
23173
  return await validateInternal(args);
22827
23174
  }
22828
23175
 
23176
+ const GET_STRATEGY_METHOD_NAME = "get.getStrategySchema";
23177
+ const GET_EXCHANGE_METHOD_NAME = "get.getExchangeSchema";
23178
+ const GET_FRAME_METHOD_NAME = "get.getFrameSchema";
23179
+ const GET_WALKER_METHOD_NAME = "get.getWalkerSchema";
23180
+ const GET_SIZING_METHOD_NAME = "get.getSizingSchema";
23181
+ const GET_RISK_METHOD_NAME = "get.getRiskSchema";
23182
+ const GET_OPTIMIZER_METHOD_NAME = "get.getOptimizerSchema";
23183
+ const GET_ACTION_METHOD_NAME = "get.getActionSchema";
23184
+ /**
23185
+ * Retrieves a registered strategy schema by name.
23186
+ *
23187
+ * @param strategyName - Unique strategy identifier
23188
+ * @returns The strategy schema configuration object
23189
+ * @throws Error if strategy is not registered
23190
+ *
23191
+ * @example
23192
+ * ```typescript
23193
+ * const strategy = getStrategy("my-strategy");
23194
+ * console.log(strategy.interval); // "5m"
23195
+ * console.log(strategy.getSignal); // async function
23196
+ * ```
23197
+ */
23198
+ function getStrategySchema(strategyName) {
23199
+ backtest$1.loggerService.log(GET_STRATEGY_METHOD_NAME, {
23200
+ strategyName,
23201
+ });
23202
+ backtest$1.strategyValidationService.validate(strategyName, GET_STRATEGY_METHOD_NAME);
23203
+ return backtest$1.strategySchemaService.get(strategyName);
23204
+ }
23205
+ /**
23206
+ * Retrieves a registered exchange schema by name.
23207
+ *
23208
+ * @param exchangeName - Unique exchange identifier
23209
+ * @returns The exchange schema configuration object
23210
+ * @throws Error if exchange is not registered
23211
+ *
23212
+ * @example
23213
+ * ```typescript
23214
+ * const exchange = getExchange("binance");
23215
+ * console.log(exchange.getCandles); // async function
23216
+ * console.log(exchange.formatPrice); // async function
23217
+ * ```
23218
+ */
23219
+ function getExchangeSchema(exchangeName) {
23220
+ backtest$1.loggerService.log(GET_EXCHANGE_METHOD_NAME, {
23221
+ exchangeName,
23222
+ });
23223
+ backtest$1.exchangeValidationService.validate(exchangeName, GET_EXCHANGE_METHOD_NAME);
23224
+ return backtest$1.exchangeSchemaService.get(exchangeName);
23225
+ }
23226
+ /**
23227
+ * Retrieves a registered frame schema by name.
23228
+ *
23229
+ * @param frameName - Unique frame identifier
23230
+ * @returns The frame schema configuration object
23231
+ * @throws Error if frame is not registered
23232
+ *
23233
+ * @example
23234
+ * ```typescript
23235
+ * const frame = getFrame("1d-backtest");
23236
+ * console.log(frame.interval); // "1m"
23237
+ * console.log(frame.startDate); // Date object
23238
+ * console.log(frame.endDate); // Date object
23239
+ * ```
23240
+ */
23241
+ function getFrameSchema(frameName) {
23242
+ backtest$1.loggerService.log(GET_FRAME_METHOD_NAME, {
23243
+ frameName,
23244
+ });
23245
+ backtest$1.frameValidationService.validate(frameName, GET_FRAME_METHOD_NAME);
23246
+ return backtest$1.frameSchemaService.get(frameName);
23247
+ }
23248
+ /**
23249
+ * Retrieves a registered walker schema by name.
23250
+ *
23251
+ * @param walkerName - Unique walker identifier
23252
+ * @returns The walker schema configuration object
23253
+ * @throws Error if walker is not registered
23254
+ *
23255
+ * @example
23256
+ * ```typescript
23257
+ * const walker = getWalker("llm-prompt-optimizer");
23258
+ * console.log(walker.exchangeName); // "binance"
23259
+ * console.log(walker.frameName); // "1d-backtest"
23260
+ * console.log(walker.strategies); // ["my-strategy-v1", "my-strategy-v2"]
23261
+ * console.log(walker.metric); // "sharpeRatio"
23262
+ * ```
23263
+ */
23264
+ function getWalkerSchema(walkerName) {
23265
+ backtest$1.loggerService.log(GET_WALKER_METHOD_NAME, {
23266
+ walkerName,
23267
+ });
23268
+ backtest$1.walkerValidationService.validate(walkerName, GET_WALKER_METHOD_NAME);
23269
+ return backtest$1.walkerSchemaService.get(walkerName);
23270
+ }
23271
+ /**
23272
+ * Retrieves a registered sizing schema by name.
23273
+ *
23274
+ * @param sizingName - Unique sizing identifier
23275
+ * @returns The sizing schema configuration object
23276
+ * @throws Error if sizing is not registered
23277
+ *
23278
+ * @example
23279
+ * ```typescript
23280
+ * const sizing = getSizing("conservative");
23281
+ * console.log(sizing.method); // "fixed-percentage"
23282
+ * console.log(sizing.riskPercentage); // 1
23283
+ * console.log(sizing.maxPositionPercentage); // 10
23284
+ * ```
23285
+ */
23286
+ function getSizingSchema(sizingName) {
23287
+ backtest$1.loggerService.log(GET_SIZING_METHOD_NAME, {
23288
+ sizingName,
23289
+ });
23290
+ backtest$1.sizingValidationService.validate(sizingName, GET_SIZING_METHOD_NAME);
23291
+ return backtest$1.sizingSchemaService.get(sizingName);
23292
+ }
23293
+ /**
23294
+ * Retrieves a registered risk schema by name.
23295
+ *
23296
+ * @param riskName - Unique risk identifier
23297
+ * @returns The risk schema configuration object
23298
+ * @throws Error if risk is not registered
23299
+ *
23300
+ * @example
23301
+ * ```typescript
23302
+ * const risk = getRisk("conservative");
23303
+ * console.log(risk.maxConcurrentPositions); // 5
23304
+ * console.log(risk.validations); // Array of validation functions
23305
+ * ```
23306
+ */
23307
+ function getRiskSchema(riskName) {
23308
+ backtest$1.loggerService.log(GET_RISK_METHOD_NAME, {
23309
+ riskName,
23310
+ });
23311
+ backtest$1.riskValidationService.validate(riskName, GET_RISK_METHOD_NAME);
23312
+ return backtest$1.riskSchemaService.get(riskName);
23313
+ }
23314
+ /**
23315
+ * Retrieves a registered optimizer schema by name.
23316
+ *
23317
+ * @param optimizerName - Unique optimizer identifier
23318
+ * @returns The optimizer schema configuration object
23319
+ * @throws Error if optimizer is not registered
23320
+ *
23321
+ * @example
23322
+ * ```typescript
23323
+ * const optimizer = getOptimizer("llm-strategy-generator");
23324
+ * console.log(optimizer.rangeTrain); // Array of training ranges
23325
+ * console.log(optimizer.rangeTest); // Testing range
23326
+ * console.log(optimizer.source); // Array of data sources
23327
+ * console.log(optimizer.getPrompt); // async function
23328
+ * ```
23329
+ */
23330
+ function getOptimizerSchema(optimizerName) {
23331
+ backtest$1.loggerService.log(GET_OPTIMIZER_METHOD_NAME, {
23332
+ optimizerName,
23333
+ });
23334
+ backtest$1.optimizerValidationService.validate(optimizerName, GET_OPTIMIZER_METHOD_NAME);
23335
+ return backtest$1.optimizerSchemaService.get(optimizerName);
23336
+ }
23337
+ /**
23338
+ * Retrieves a registered action schema by name.
23339
+ *
23340
+ * @param actionName - Unique action identifier
23341
+ * @returns The action schema configuration object
23342
+ * @throws Error if action is not registered
23343
+ *
23344
+ * @example
23345
+ * ```typescript
23346
+ * const action = getAction("telegram-notifier");
23347
+ * console.log(action.handler); // Class constructor or object
23348
+ * console.log(action.callbacks); // Optional lifecycle callbacks
23349
+ * ```
23350
+ */
23351
+ function getActionSchema(actionName) {
23352
+ backtest$1.loggerService.log(GET_ACTION_METHOD_NAME, {
23353
+ actionName,
23354
+ });
23355
+ backtest$1.actionValidationService.validate(actionName, GET_ACTION_METHOD_NAME);
23356
+ return backtest$1.actionSchemaService.get(actionName);
23357
+ }
23358
+
22829
23359
  const GET_CANDLES_METHOD_NAME = "exchange.getCandles";
22830
23360
  const GET_AVERAGE_PRICE_METHOD_NAME = "exchange.getAveragePrice";
22831
23361
  const FORMAT_PRICE_METHOD_NAME = "exchange.formatPrice";
22832
23362
  const FORMAT_QUANTITY_METHOD_NAME = "exchange.formatQuantity";
22833
23363
  const GET_DATE_METHOD_NAME = "exchange.getDate";
22834
23364
  const GET_MODE_METHOD_NAME = "exchange.getMode";
23365
+ const GET_SYMBOL_METHOD_NAME = "exchange.getSymbol";
23366
+ const GET_CONTEXT_METHOD_NAME = "exchange.getContext";
22835
23367
  const HAS_TRADE_CONTEXT_METHOD_NAME = "exchange.hasTradeContext";
22836
23368
  const GET_ORDER_BOOK_METHOD_NAME = "exchange.getOrderBook";
22837
23369
  /**
@@ -23014,6 +23546,48 @@ async function getMode() {
23014
23546
  const { backtest: bt } = backtest$1.executionContextService.context;
23015
23547
  return bt ? "backtest" : "live";
23016
23548
  }
23549
+ /**
23550
+ * Gets the current trading symbol from execution context.
23551
+ *
23552
+ * @returns Promise resolving to the current trading symbol (e.g., "BTCUSDT")
23553
+ * @throws Error if execution context is not active
23554
+ *
23555
+ * @example
23556
+ * ```typescript
23557
+ * const symbol = await getSymbol();
23558
+ * console.log(symbol); // "BTCUSDT"
23559
+ * ```
23560
+ */
23561
+ async function getSymbol() {
23562
+ backtest$1.loggerService.info(GET_SYMBOL_METHOD_NAME);
23563
+ if (!ExecutionContextService.hasContext()) {
23564
+ throw new Error("getSymbol requires an execution context");
23565
+ }
23566
+ const { symbol } = backtest$1.executionContextService.context;
23567
+ return symbol;
23568
+ }
23569
+ /**
23570
+ * Gets the current method context.
23571
+ *
23572
+ * Returns the context object from the method context service, which contains
23573
+ * information about the current method execution environment.
23574
+ *
23575
+ * @returns Promise resolving to the current method context object
23576
+ * @throws Error if method context is not active
23577
+ *
23578
+ * @example
23579
+ * ```typescript
23580
+ * const context = await getContext();
23581
+ * console.log(context); // { ...method context data... }
23582
+ * ```
23583
+ */
23584
+ async function getContext() {
23585
+ backtest$1.loggerService.info(GET_CONTEXT_METHOD_NAME);
23586
+ if (!MethodContextService.hasContext()) {
23587
+ throw new Error("getContext requires a method context");
23588
+ }
23589
+ return backtest$1.methodContextService.context;
23590
+ }
23017
23591
  /**
23018
23592
  * Fetches order book for a trading pair from the registered exchange.
23019
23593
  *
@@ -23050,52 +23624,12 @@ async function getOrderBook(symbol, depth) {
23050
23624
  return await backtest$1.exchangeConnectionService.getOrderBook(symbol, depth);
23051
23625
  }
23052
23626
 
23053
- const STOP_METHOD_NAME = "strategy.stop";
23054
- const CANCEL_METHOD_NAME = "strategy.cancel";
23055
- const PARTIAL_PROFIT_METHOD_NAME = "strategy.partialProfit";
23056
- const PARTIAL_LOSS_METHOD_NAME = "strategy.partialLoss";
23057
- const TRAILING_STOP_METHOD_NAME = "strategy.trailingStop";
23058
- const TRAILING_PROFIT_METHOD_NAME = "strategy.trailingTake";
23059
- const BREAKEVEN_METHOD_NAME = "strategy.breakeven";
23060
- /**
23061
- * Stops the strategy from generating new signals.
23062
- *
23063
- * Sets internal flag to prevent strategy from opening new signals.
23064
- * Current active signal (if any) will complete normally.
23065
- * Backtest/Live mode will stop at the next safe point (idle state or after signal closes).
23066
- *
23067
- * Automatically detects backtest/live mode from execution context.
23068
- *
23069
- * @param symbol - Trading pair symbol
23070
- * @param strategyName - Strategy name to stop
23071
- * @returns Promise that resolves when stop flag is set
23072
- *
23073
- * @example
23074
- * ```typescript
23075
- * import { stop } from "backtest-kit";
23076
- *
23077
- * // Stop strategy after some condition
23078
- * await stop("BTCUSDT", "my-strategy");
23079
- * ```
23080
- */
23081
- async function stop(symbol) {
23082
- backtest$1.loggerService.info(STOP_METHOD_NAME, {
23083
- symbol,
23084
- });
23085
- if (!ExecutionContextService.hasContext()) {
23086
- throw new Error("stop requires an execution context");
23087
- }
23088
- if (!MethodContextService.hasContext()) {
23089
- throw new Error("stop requires a method context");
23090
- }
23091
- const { backtest: isBacktest } = backtest$1.executionContextService.context;
23092
- const { exchangeName, frameName, strategyName } = backtest$1.methodContextService.context;
23093
- await backtest$1.strategyCoreService.stop(isBacktest, symbol, {
23094
- exchangeName,
23095
- frameName,
23096
- strategyName,
23097
- });
23098
- }
23627
+ const CANCEL_METHOD_NAME = "strategy.commitCancel";
23628
+ const PARTIAL_PROFIT_METHOD_NAME = "strategy.commitPartialProfit";
23629
+ const PARTIAL_LOSS_METHOD_NAME = "strategy.commitPartialLoss";
23630
+ const TRAILING_STOP_METHOD_NAME = "strategy.commitTrailingStop";
23631
+ const TRAILING_PROFIT_METHOD_NAME = "strategy.commitTrailingTake";
23632
+ const BREAKEVEN_METHOD_NAME = "strategy.commitBreakeven";
23099
23633
  /**
23100
23634
  * Cancels the scheduled signal without stopping the strategy.
23101
23635
  *
@@ -23118,7 +23652,7 @@ async function stop(symbol) {
23118
23652
  * await cancel("BTCUSDT", "my-strategy", "manual-cancel-001");
23119
23653
  * ```
23120
23654
  */
23121
- async function cancel(symbol, cancelId) {
23655
+ async function commitCancel(symbol, cancelId) {
23122
23656
  backtest$1.loggerService.info(CANCEL_METHOD_NAME, {
23123
23657
  symbol,
23124
23658
  cancelId,
@@ -23160,7 +23694,7 @@ async function cancel(symbol, cancelId) {
23160
23694
  * }
23161
23695
  * ```
23162
23696
  */
23163
- async function partialProfit(symbol, percentToClose) {
23697
+ async function commitPartialProfit(symbol, percentToClose) {
23164
23698
  backtest$1.loggerService.info(PARTIAL_PROFIT_METHOD_NAME, {
23165
23699
  symbol,
23166
23700
  percentToClose,
@@ -23203,7 +23737,7 @@ async function partialProfit(symbol, percentToClose) {
23203
23737
  * }
23204
23738
  * ```
23205
23739
  */
23206
- async function partialLoss(symbol, percentToClose) {
23740
+ async function commitPartialLoss(symbol, percentToClose) {
23207
23741
  backtest$1.loggerService.info(PARTIAL_LOSS_METHOD_NAME, {
23208
23742
  symbol,
23209
23743
  percentToClose,
@@ -23262,7 +23796,7 @@ async function partialLoss(symbol, percentToClose) {
23262
23796
  * // success3 = true (ACCEPTED: newDistance = 10% - 7% = 3%, newSL = 97 > 95, better protection)
23263
23797
  * ```
23264
23798
  */
23265
- async function trailingStop(symbol, percentShift, currentPrice) {
23799
+ async function commitTrailingStop(symbol, percentShift, currentPrice) {
23266
23800
  backtest$1.loggerService.info(TRAILING_STOP_METHOD_NAME, {
23267
23801
  symbol,
23268
23802
  percentShift,
@@ -23321,7 +23855,7 @@ async function trailingStop(symbol, percentShift, currentPrice) {
23321
23855
  * // success3 = true (ACCEPTED: newDistance = 10% - 5% = 5%, newTP = 105 < 107, more conservative)
23322
23856
  * ```
23323
23857
  */
23324
- async function trailingTake(symbol, percentShift, currentPrice) {
23858
+ async function commitTrailingTake(symbol, percentShift, currentPrice) {
23325
23859
  backtest$1.loggerService.info(TRAILING_PROFIT_METHOD_NAME, {
23326
23860
  symbol,
23327
23861
  percentShift,
@@ -23362,7 +23896,7 @@ async function trailingTake(symbol, percentShift, currentPrice) {
23362
23896
  * }
23363
23897
  * ```
23364
23898
  */
23365
- async function breakeven(symbol) {
23899
+ async function commitBreakeven(symbol) {
23366
23900
  backtest$1.loggerService.info(BREAKEVEN_METHOD_NAME, {
23367
23901
  symbol,
23368
23902
  });
@@ -23378,6 +23912,47 @@ async function breakeven(symbol) {
23378
23912
  return await backtest$1.strategyCoreService.breakeven(isBacktest, symbol, currentPrice, { exchangeName, frameName, strategyName });
23379
23913
  }
23380
23914
 
23915
+ const STOP_METHOD_NAME = "control.stop";
23916
+ /**
23917
+ * Stops the strategy from generating new signals.
23918
+ *
23919
+ * Sets internal flag to prevent strategy from opening new signals.
23920
+ * Current active signal (if any) will complete normally.
23921
+ * Backtest/Live mode will stop at the next safe point (idle state or after signal closes).
23922
+ *
23923
+ * Automatically detects backtest/live mode from execution context.
23924
+ *
23925
+ * @param symbol - Trading pair symbol
23926
+ * @param strategyName - Strategy name to stop
23927
+ * @returns Promise that resolves when stop flag is set
23928
+ *
23929
+ * @example
23930
+ * ```typescript
23931
+ * import { stop } from "backtest-kit";
23932
+ *
23933
+ * // Stop strategy after some condition
23934
+ * await stop("BTCUSDT", "my-strategy");
23935
+ * ```
23936
+ */
23937
+ async function stop(symbol) {
23938
+ backtest$1.loggerService.info(STOP_METHOD_NAME, {
23939
+ symbol,
23940
+ });
23941
+ if (!ExecutionContextService.hasContext()) {
23942
+ throw new Error("stop requires an execution context");
23943
+ }
23944
+ if (!MethodContextService.hasContext()) {
23945
+ throw new Error("stop requires a method context");
23946
+ }
23947
+ const { backtest: isBacktest } = backtest$1.executionContextService.context;
23948
+ const { exchangeName, frameName, strategyName } = backtest$1.methodContextService.context;
23949
+ await backtest$1.strategyCoreService.stop(isBacktest, symbol, {
23950
+ exchangeName,
23951
+ frameName,
23952
+ strategyName,
23953
+ });
23954
+ }
23955
+
23381
23956
  /**
23382
23957
  * Sets custom logger implementation for the framework.
23383
23958
  *
@@ -23528,14 +24103,14 @@ function getDefaultColumns() {
23528
24103
  return DEFAULT_COLUMNS;
23529
24104
  }
23530
24105
 
23531
- const ADD_STRATEGY_METHOD_NAME = "add.addStrategy";
23532
- const ADD_EXCHANGE_METHOD_NAME = "add.addExchange";
23533
- const ADD_FRAME_METHOD_NAME = "add.addFrame";
23534
- const ADD_WALKER_METHOD_NAME = "add.addWalker";
23535
- const ADD_SIZING_METHOD_NAME = "add.addSizing";
23536
- const ADD_RISK_METHOD_NAME = "add.addRisk";
23537
- const ADD_OPTIMIZER_METHOD_NAME = "add.addOptimizer";
23538
- const ADD_ACTION_METHOD_NAME = "add.addAction";
24106
+ const ADD_STRATEGY_METHOD_NAME = "add.addStrategySchema";
24107
+ const ADD_EXCHANGE_METHOD_NAME = "add.addExchangeSchema";
24108
+ const ADD_FRAME_METHOD_NAME = "add.addFrameSchema";
24109
+ const ADD_WALKER_METHOD_NAME = "add.addWalkerSchema";
24110
+ const ADD_SIZING_METHOD_NAME = "add.addSizingSchema";
24111
+ const ADD_RISK_METHOD_NAME = "add.addRiskSchema";
24112
+ const ADD_OPTIMIZER_METHOD_NAME = "add.addOptimizerSchema";
24113
+ const ADD_ACTION_METHOD_NAME = "add.addActionSchema";
23539
24114
  /**
23540
24115
  * Registers a trading strategy in the framework.
23541
24116
  *
@@ -23570,7 +24145,7 @@ const ADD_ACTION_METHOD_NAME = "add.addAction";
23570
24145
  * });
23571
24146
  * ```
23572
24147
  */
23573
- function addStrategy(strategySchema) {
24148
+ function addStrategySchema(strategySchema) {
23574
24149
  backtest$1.loggerService.info(ADD_STRATEGY_METHOD_NAME, {
23575
24150
  strategySchema,
23576
24151
  });
@@ -23612,7 +24187,7 @@ function addStrategy(strategySchema) {
23612
24187
  * });
23613
24188
  * ```
23614
24189
  */
23615
- function addExchange(exchangeSchema) {
24190
+ function addExchangeSchema(exchangeSchema) {
23616
24191
  backtest$1.loggerService.info(ADD_EXCHANGE_METHOD_NAME, {
23617
24192
  exchangeSchema,
23618
24193
  });
@@ -23649,7 +24224,7 @@ function addExchange(exchangeSchema) {
23649
24224
  * });
23650
24225
  * ```
23651
24226
  */
23652
- function addFrame(frameSchema) {
24227
+ function addFrameSchema(frameSchema) {
23653
24228
  backtest$1.loggerService.info(ADD_FRAME_METHOD_NAME, {
23654
24229
  frameSchema,
23655
24230
  });
@@ -23693,7 +24268,7 @@ function addFrame(frameSchema) {
23693
24268
  * });
23694
24269
  * ```
23695
24270
  */
23696
- function addWalker(walkerSchema) {
24271
+ function addWalkerSchema(walkerSchema) {
23697
24272
  backtest$1.loggerService.info(ADD_WALKER_METHOD_NAME, {
23698
24273
  walkerSchema,
23699
24274
  });
@@ -23752,7 +24327,7 @@ function addWalker(walkerSchema) {
23752
24327
  * });
23753
24328
  * ```
23754
24329
  */
23755
- function addSizing(sizingSchema) {
24330
+ function addSizingSchema(sizingSchema) {
23756
24331
  backtest$1.loggerService.info(ADD_SIZING_METHOD_NAME, {
23757
24332
  sizingSchema,
23758
24333
  });
@@ -23820,7 +24395,7 @@ function addSizing(sizingSchema) {
23820
24395
  * });
23821
24396
  * ```
23822
24397
  */
23823
- function addRisk(riskSchema) {
24398
+ function addRiskSchema(riskSchema) {
23824
24399
  backtest$1.loggerService.info(ADD_RISK_METHOD_NAME, {
23825
24400
  riskSchema,
23826
24401
  });
@@ -23914,7 +24489,7 @@ function addRisk(riskSchema) {
23914
24489
  * });
23915
24490
  * ```
23916
24491
  */
23917
- function addOptimizer(optimizerSchema) {
24492
+ function addOptimizerSchema(optimizerSchema) {
23918
24493
  backtest$1.loggerService.info(ADD_OPTIMIZER_METHOD_NAME, {
23919
24494
  optimizerSchema,
23920
24495
  });
@@ -23989,7 +24564,7 @@ function addOptimizer(optimizerSchema) {
23989
24564
  * });
23990
24565
  * ```
23991
24566
  */
23992
- function addAction(actionSchema) {
24567
+ function addActionSchema(actionSchema) {
23993
24568
  backtest$1.loggerService.info(ADD_ACTION_METHOD_NAME, {
23994
24569
  actionSchema,
23995
24570
  });
@@ -23997,14 +24572,14 @@ function addAction(actionSchema) {
23997
24572
  backtest$1.actionSchemaService.register(actionSchema.actionName, actionSchema);
23998
24573
  }
23999
24574
 
24000
- const METHOD_NAME_OVERRIDE_STRATEGY = "function.override.overrideStrategy";
24001
- const METHOD_NAME_OVERRIDE_EXCHANGE = "function.override.overrideExchange";
24002
- const METHOD_NAME_OVERRIDE_FRAME = "function.override.overrideFrame";
24003
- const METHOD_NAME_OVERRIDE_WALKER = "function.override.overrideWalker";
24004
- const METHOD_NAME_OVERRIDE_SIZING = "function.override.overrideSizing";
24005
- const METHOD_NAME_OVERRIDE_RISK = "function.override.overrideRisk";
24006
- const METHOD_NAME_OVERRIDE_OPTIMIZER = "function.override.overrideOptimizer";
24007
- const METHOD_NAME_OVERRIDE_ACTION = "function.override.overrideAction";
24575
+ const METHOD_NAME_OVERRIDE_STRATEGY = "function.override.overrideStrategySchema";
24576
+ const METHOD_NAME_OVERRIDE_EXCHANGE = "function.override.overrideExchangeSchema";
24577
+ const METHOD_NAME_OVERRIDE_FRAME = "function.override.overrideFrameSchema";
24578
+ const METHOD_NAME_OVERRIDE_WALKER = "function.override.overrideWalkerSchema";
24579
+ const METHOD_NAME_OVERRIDE_SIZING = "function.override.overrideSizingSchema";
24580
+ const METHOD_NAME_OVERRIDE_RISK = "function.override.overrideRiskSchema";
24581
+ const METHOD_NAME_OVERRIDE_OPTIMIZER = "function.override.overrideOptimizerSchema";
24582
+ const METHOD_NAME_OVERRIDE_ACTION = "function.override.overrideActionSchema";
24008
24583
  /**
24009
24584
  * Overrides an existing trading strategy in the framework.
24010
24585
  *
@@ -24025,7 +24600,7 @@ const METHOD_NAME_OVERRIDE_ACTION = "function.override.overrideAction";
24025
24600
  * });
24026
24601
  * ```
24027
24602
  */
24028
- async function overrideStrategy(strategySchema) {
24603
+ async function overrideStrategySchema(strategySchema) {
24029
24604
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_STRATEGY, {
24030
24605
  strategySchema,
24031
24606
  });
@@ -24053,7 +24628,7 @@ async function overrideStrategy(strategySchema) {
24053
24628
  * });
24054
24629
  * ```
24055
24630
  */
24056
- async function overrideExchange(exchangeSchema) {
24631
+ async function overrideExchangeSchema(exchangeSchema) {
24057
24632
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_EXCHANGE, {
24058
24633
  exchangeSchema,
24059
24634
  });
@@ -24081,7 +24656,7 @@ async function overrideExchange(exchangeSchema) {
24081
24656
  * });
24082
24657
  * ```
24083
24658
  */
24084
- async function overrideFrame(frameSchema) {
24659
+ async function overrideFrameSchema(frameSchema) {
24085
24660
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_FRAME, {
24086
24661
  frameSchema,
24087
24662
  });
@@ -24110,7 +24685,7 @@ async function overrideFrame(frameSchema) {
24110
24685
  * });
24111
24686
  * ```
24112
24687
  */
24113
- async function overrideWalker(walkerSchema) {
24688
+ async function overrideWalkerSchema(walkerSchema) {
24114
24689
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_WALKER, {
24115
24690
  walkerSchema,
24116
24691
  });
@@ -24142,7 +24717,7 @@ async function overrideWalker(walkerSchema) {
24142
24717
  * });
24143
24718
  * ```
24144
24719
  */
24145
- async function overrideSizing(sizingSchema) {
24720
+ async function overrideSizingSchema(sizingSchema) {
24146
24721
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_SIZING, {
24147
24722
  sizingSchema,
24148
24723
  });
@@ -24169,7 +24744,7 @@ async function overrideSizing(sizingSchema) {
24169
24744
  * });
24170
24745
  * ```
24171
24746
  */
24172
- async function overrideRisk(riskSchema) {
24747
+ async function overrideRiskSchema(riskSchema) {
24173
24748
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_RISK, {
24174
24749
  riskSchema,
24175
24750
  });
@@ -24203,7 +24778,7 @@ async function overrideRisk(riskSchema) {
24203
24778
  * });
24204
24779
  * ```
24205
24780
  */
24206
- async function overrideOptimizer(optimizerSchema) {
24781
+ async function overrideOptimizerSchema(optimizerSchema) {
24207
24782
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_OPTIMIZER, {
24208
24783
  optimizerSchema,
24209
24784
  });
@@ -24270,7 +24845,7 @@ async function overrideOptimizer(optimizerSchema) {
24270
24845
  * });
24271
24846
  * ```
24272
24847
  */
24273
- async function overrideAction(actionSchema) {
24848
+ async function overrideActionSchema(actionSchema) {
24274
24849
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_ACTION, {
24275
24850
  actionSchema,
24276
24851
  });
@@ -24278,13 +24853,13 @@ async function overrideAction(actionSchema) {
24278
24853
  return backtest$1.actionSchemaService.override(actionSchema.actionName, actionSchema);
24279
24854
  }
24280
24855
 
24281
- const LIST_EXCHANGES_METHOD_NAME = "list.listExchanges";
24282
- const LIST_STRATEGIES_METHOD_NAME = "list.listStrategies";
24283
- const LIST_FRAMES_METHOD_NAME = "list.listFrames";
24284
- const LIST_WALKERS_METHOD_NAME = "list.listWalkers";
24285
- const LIST_SIZINGS_METHOD_NAME = "list.listSizings";
24286
- const LIST_RISKS_METHOD_NAME = "list.listRisks";
24287
- const LIST_OPTIMIZERS_METHOD_NAME = "list.listOptimizers";
24856
+ const LIST_EXCHANGES_METHOD_NAME = "list.listExchangeSchema";
24857
+ const LIST_STRATEGIES_METHOD_NAME = "list.listStrategySchema";
24858
+ const LIST_FRAMES_METHOD_NAME = "list.listFrameSchema";
24859
+ const LIST_WALKERS_METHOD_NAME = "list.listWalkerSchema";
24860
+ const LIST_SIZINGS_METHOD_NAME = "list.listSizingSchema";
24861
+ const LIST_RISKS_METHOD_NAME = "list.listRiskSchema";
24862
+ const LIST_OPTIMIZERS_METHOD_NAME = "list.listOptimizerSchema";
24288
24863
  /**
24289
24864
  * Returns a list of all registered exchange schemas.
24290
24865
  *
@@ -24310,7 +24885,7 @@ const LIST_OPTIMIZERS_METHOD_NAME = "list.listOptimizers";
24310
24885
  * // [{ exchangeName: "binance", note: "Binance cryptocurrency exchange", ... }]
24311
24886
  * ```
24312
24887
  */
24313
- async function listExchanges() {
24888
+ async function listExchangeSchema() {
24314
24889
  backtest$1.loggerService.log(LIST_EXCHANGES_METHOD_NAME);
24315
24890
  return await backtest$1.exchangeValidationService.list();
24316
24891
  }
@@ -24344,7 +24919,7 @@ async function listExchanges() {
24344
24919
  * // [{ strategyName: "my-strategy", note: "Simple moving average...", ... }]
24345
24920
  * ```
24346
24921
  */
24347
- async function listStrategies() {
24922
+ async function listStrategySchema() {
24348
24923
  backtest$1.loggerService.log(LIST_STRATEGIES_METHOD_NAME);
24349
24924
  return await backtest$1.strategyValidationService.list();
24350
24925
  }
@@ -24373,7 +24948,7 @@ async function listStrategies() {
24373
24948
  * // [{ frameName: "1d-backtest", note: "One day backtest...", ... }]
24374
24949
  * ```
24375
24950
  */
24376
- async function listFrames() {
24951
+ async function listFrameSchema() {
24377
24952
  backtest$1.loggerService.log(LIST_FRAMES_METHOD_NAME);
24378
24953
  return await backtest$1.frameValidationService.list();
24379
24954
  }
@@ -24403,7 +24978,7 @@ async function listFrames() {
24403
24978
  * // [{ walkerName: "llm-prompt-optimizer", note: "Compare LLM...", ... }]
24404
24979
  * ```
24405
24980
  */
24406
- async function listWalkers() {
24981
+ async function listWalkerSchema() {
24407
24982
  backtest$1.loggerService.log(LIST_WALKERS_METHOD_NAME);
24408
24983
  return await backtest$1.walkerValidationService.list();
24409
24984
  }
@@ -24442,7 +25017,7 @@ async function listWalkers() {
24442
25017
  * // ]
24443
25018
  * ```
24444
25019
  */
24445
- async function listSizings() {
25020
+ async function listSizingSchema() {
24446
25021
  backtest$1.loggerService.log(LIST_SIZINGS_METHOD_NAME);
24447
25022
  return await backtest$1.sizingValidationService.list();
24448
25023
  }
@@ -24478,7 +25053,7 @@ async function listSizings() {
24478
25053
  * // ]
24479
25054
  * ```
24480
25055
  */
24481
- async function listRisks() {
25056
+ async function listRiskSchema() {
24482
25057
  backtest$1.loggerService.log(LIST_RISKS_METHOD_NAME);
24483
25058
  return await backtest$1.riskValidationService.list();
24484
25059
  }
@@ -24518,7 +25093,7 @@ async function listRisks() {
24518
25093
  * // [{ optimizerName: "llm-strategy-generator", note: "Generates...", ... }]
24519
25094
  * ```
24520
25095
  */
24521
- async function listOptimizers() {
25096
+ async function listOptimizerSchema() {
24522
25097
  backtest$1.loggerService.log(LIST_OPTIMIZERS_METHOD_NAME);
24523
25098
  return await backtest$1.optimizerValidationService.list();
24524
25099
  }
@@ -24553,8 +25128,10 @@ const LISTEN_BREAKEVEN_METHOD_NAME = "event.listenBreakeven";
24553
25128
  const LISTEN_BREAKEVEN_ONCE_METHOD_NAME = "event.listenBreakevenOnce";
24554
25129
  const LISTEN_RISK_METHOD_NAME = "event.listenRisk";
24555
25130
  const LISTEN_RISK_ONCE_METHOD_NAME = "event.listenRiskOnce";
24556
- const LISTEN_PING_METHOD_NAME = "event.listenPing";
24557
- const LISTEN_PING_ONCE_METHOD_NAME = "event.listenPingOnce";
25131
+ const LISTEN_SCHEDULE_PING_METHOD_NAME = "event.listenSchedulePing";
25132
+ const LISTEN_SCHEDULE_PING_ONCE_METHOD_NAME = "event.listenSchedulePingOnce";
25133
+ const LISTEN_ACTIVE_PING_METHOD_NAME = "event.listenActivePing";
25134
+ const LISTEN_ACTIVE_PING_ONCE_METHOD_NAME = "event.listenActivePingOnce";
24558
25135
  /**
24559
25136
  * Subscribes to all signal events with queued async processing.
24560
25137
  *
@@ -25253,7 +25830,7 @@ function listenValidation(fn) {
25253
25830
  * unsubscribe();
25254
25831
  * ```
25255
25832
  */
25256
- function listenPartialProfit(fn) {
25833
+ function listenPartialProfitAvailable(fn) {
25257
25834
  backtest$1.loggerService.log(LISTEN_PARTIAL_PROFIT_METHOD_NAME);
25258
25835
  return partialProfitSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
25259
25836
  }
@@ -25287,7 +25864,7 @@ function listenPartialProfit(fn) {
25287
25864
  * cancel();
25288
25865
  * ```
25289
25866
  */
25290
- function listenPartialProfitOnce(filterFn, fn) {
25867
+ function listenPartialProfitAvailableOnce(filterFn, fn) {
25291
25868
  backtest$1.loggerService.log(LISTEN_PARTIAL_PROFIT_ONCE_METHOD_NAME);
25292
25869
  return partialProfitSubject.filter(filterFn).once(fn);
25293
25870
  }
@@ -25315,7 +25892,7 @@ function listenPartialProfitOnce(filterFn, fn) {
25315
25892
  * unsubscribe();
25316
25893
  * ```
25317
25894
  */
25318
- function listenPartialLoss(fn) {
25895
+ function listenPartialLossAvailable(fn) {
25319
25896
  backtest$1.loggerService.log(LISTEN_PARTIAL_LOSS_METHOD_NAME);
25320
25897
  return partialLossSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
25321
25898
  }
@@ -25349,7 +25926,7 @@ function listenPartialLoss(fn) {
25349
25926
  * cancel();
25350
25927
  * ```
25351
25928
  */
25352
- function listenPartialLossOnce(filterFn, fn) {
25929
+ function listenPartialLossAvailableOnce(filterFn, fn) {
25353
25930
  backtest$1.loggerService.log(LISTEN_PARTIAL_LOSS_ONCE_METHOD_NAME);
25354
25931
  return partialLossSubject.filter(filterFn).once(fn);
25355
25932
  }
@@ -25379,7 +25956,7 @@ function listenPartialLossOnce(filterFn, fn) {
25379
25956
  * unsubscribe();
25380
25957
  * ```
25381
25958
  */
25382
- function listenBreakeven(fn) {
25959
+ function listenBreakevenAvailable(fn) {
25383
25960
  backtest$1.loggerService.log(LISTEN_BREAKEVEN_METHOD_NAME);
25384
25961
  return breakevenSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
25385
25962
  }
@@ -25413,7 +25990,7 @@ function listenBreakeven(fn) {
25413
25990
  * cancel();
25414
25991
  * ```
25415
25992
  */
25416
- function listenBreakevenOnce(filterFn, fn) {
25993
+ function listenBreakevenAvailableOnce(filterFn, fn) {
25417
25994
  backtest$1.loggerService.log(LISTEN_BREAKEVEN_ONCE_METHOD_NAME);
25418
25995
  return breakevenSubject.filter(filterFn).once(fn);
25419
25996
  }
@@ -25509,9 +26086,9 @@ function listenRiskOnce(filterFn, fn) {
25509
26086
  * unsubscribe();
25510
26087
  * ```
25511
26088
  */
25512
- function listenPing(fn) {
25513
- backtest$1.loggerService.log(LISTEN_PING_METHOD_NAME);
25514
- return pingSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
26089
+ function listenSchedulePing(fn) {
26090
+ backtest$1.loggerService.log(LISTEN_SCHEDULE_PING_METHOD_NAME);
26091
+ return schedulePingSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
25515
26092
  }
25516
26093
  /**
25517
26094
  * Subscribes to filtered ping events with one-time execution.
@@ -25543,9 +26120,74 @@ function listenPing(fn) {
25543
26120
  * cancel();
25544
26121
  * ```
25545
26122
  */
25546
- function listenPingOnce(filterFn, fn) {
25547
- backtest$1.loggerService.log(LISTEN_PING_ONCE_METHOD_NAME);
25548
- return pingSubject.filter(filterFn).once(fn);
26123
+ function listenSchedulePingOnce(filterFn, fn) {
26124
+ backtest$1.loggerService.log(LISTEN_SCHEDULE_PING_ONCE_METHOD_NAME);
26125
+ return schedulePingSubject.filter(filterFn).once(fn);
26126
+ }
26127
+ /**
26128
+ * Subscribes to active ping events with queued async processing.
26129
+ *
26130
+ * Listens for active pending signal monitoring events emitted every minute.
26131
+ * Useful for tracking active signal lifecycle and implementing dynamic management logic.
26132
+ *
26133
+ * Events are processed sequentially in order received, even if callback is async.
26134
+ * Uses queued wrapper to prevent concurrent execution of the callback.
26135
+ *
26136
+ * @param fn - Callback function to handle active ping events
26137
+ * @returns Unsubscribe function to stop listening
26138
+ *
26139
+ * @example
26140
+ * ```typescript
26141
+ * import { listenActivePing } from "./function/event";
26142
+ *
26143
+ * const unsubscribe = listenActivePing((event) => {
26144
+ * console.log(`[${event.backtest ? "Backtest" : "Live"}] Active Ping`);
26145
+ * console.log(`Symbol: ${event.symbol}, Strategy: ${event.strategyName}`);
26146
+ * console.log(`Signal ID: ${event.data.id}, Position: ${event.data.position}`);
26147
+ * console.log(`Timestamp: ${new Date(event.timestamp).toISOString()}`);
26148
+ * });
26149
+ *
26150
+ * // Later: stop listening
26151
+ * unsubscribe();
26152
+ * ```
26153
+ */
26154
+ function listenActivePing(fn) {
26155
+ backtest$1.loggerService.log(LISTEN_ACTIVE_PING_METHOD_NAME);
26156
+ return activePingSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
26157
+ }
26158
+ /**
26159
+ * Subscribes to filtered active ping events with one-time execution.
26160
+ *
26161
+ * Listens for events matching the filter predicate, then executes callback once
26162
+ * and automatically unsubscribes. Useful for waiting for specific active ping conditions.
26163
+ *
26164
+ * @param filterFn - Predicate to filter which events trigger the callback
26165
+ * @param fn - Callback function to handle the filtered event (called only once)
26166
+ * @returns Unsubscribe function to cancel the listener before it fires
26167
+ *
26168
+ * @example
26169
+ * ```typescript
26170
+ * import { listenActivePingOnce } from "./function/event";
26171
+ *
26172
+ * // Wait for first active ping on BTCUSDT
26173
+ * listenActivePingOnce(
26174
+ * (event) => event.symbol === "BTCUSDT",
26175
+ * (event) => console.log("First BTCUSDT active ping received")
26176
+ * );
26177
+ *
26178
+ * // Wait for active ping in backtest mode
26179
+ * const cancel = listenActivePingOnce(
26180
+ * (event) => event.backtest === true,
26181
+ * (event) => console.log("Backtest active ping received at", new Date(event.timestamp))
26182
+ * );
26183
+ *
26184
+ * // Cancel if needed before event fires
26185
+ * cancel();
26186
+ * ```
26187
+ */
26188
+ function listenActivePingOnce(filterFn, fn) {
26189
+ backtest$1.loggerService.log(LISTEN_ACTIVE_PING_ONCE_METHOD_NAME);
26190
+ return activePingSubject.filter(filterFn).once(fn);
25549
26191
  }
25550
26192
 
25551
26193
  const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
@@ -25615,7 +26257,7 @@ const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
25615
26257
  * // ./dump/strategy/{uuid}/06_llm_output.md (final signal)
25616
26258
  * ```
25617
26259
  */
25618
- async function dumpSignal(signalId, history, signal, outputDir = "./dump/strategy") {
26260
+ async function dumpSignalData(signalId, history, signal, outputDir = "./dump/strategy") {
25619
26261
  backtest$1.loggerService.info(DUMP_SIGNAL_METHOD_NAME, {
25620
26262
  signalId,
25621
26263
  history,
@@ -25635,11 +26277,12 @@ const BACKTEST_METHOD_NAME_GET_STATUS = "BacktestUtils.getStatus";
25635
26277
  const BACKTEST_METHOD_NAME_GET_PENDING_SIGNAL = "BacktestUtils.getPendingSignal";
25636
26278
  const BACKTEST_METHOD_NAME_GET_SCHEDULED_SIGNAL = "BacktestUtils.getScheduledSignal";
25637
26279
  const BACKTEST_METHOD_NAME_GET_BREAKEVEN = "BacktestUtils.getBreakeven";
25638
- const BACKTEST_METHOD_NAME_CANCEL = "BacktestUtils.cancel";
25639
- const BACKTEST_METHOD_NAME_PARTIAL_PROFIT = "BacktestUtils.partialProfit";
25640
- const BACKTEST_METHOD_NAME_PARTIAL_LOSS = "BacktestUtils.partialLoss";
25641
- const BACKTEST_METHOD_NAME_TRAILING_STOP = "BacktestUtils.trailingStop";
25642
- const BACKTEST_METHOD_NAME_TRAILING_PROFIT = "BacktestUtils.trailingTake";
26280
+ const BACKTEST_METHOD_NAME_BREAKEVEN = "Backtest.commitBreakeven";
26281
+ const BACKTEST_METHOD_NAME_CANCEL = "BacktestUtils.commitCancel";
26282
+ const BACKTEST_METHOD_NAME_PARTIAL_PROFIT = "BacktestUtils.commitPartialProfit";
26283
+ const BACKTEST_METHOD_NAME_PARTIAL_LOSS = "BacktestUtils.commitPartialLoss";
26284
+ const BACKTEST_METHOD_NAME_TRAILING_STOP = "BacktestUtils.commitTrailingStop";
26285
+ const BACKTEST_METHOD_NAME_TRAILING_PROFIT = "BacktestUtils.commitTrailingTake";
25643
26286
  const BACKTEST_METHOD_NAME_GET_DATA = "BacktestUtils.getData";
25644
26287
  /**
25645
26288
  * Internal task function that runs backtest and handles completion.
@@ -26163,14 +26806,14 @@ class BacktestUtils {
26163
26806
  * @example
26164
26807
  * ```typescript
26165
26808
  * // Cancel scheduled signal with custom ID
26166
- * await Backtest.cancel("BTCUSDT", "my-strategy", {
26809
+ * await Backtest.commitCancel("BTCUSDT", "my-strategy", {
26167
26810
  * exchangeName: "binance",
26168
26811
  * frameName: "frame1",
26169
26812
  * strategyName: "my-strategy"
26170
26813
  * }, "manual-cancel-001");
26171
26814
  * ```
26172
26815
  */
26173
- this.cancel = async (symbol, context, cancelId) => {
26816
+ this.commitCancel = async (symbol, context, cancelId) => {
26174
26817
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_CANCEL, {
26175
26818
  symbol,
26176
26819
  context,
@@ -26208,7 +26851,7 @@ class BacktestUtils {
26208
26851
  * @example
26209
26852
  * ```typescript
26210
26853
  * // Close 30% of LONG position at profit
26211
- * const success = await Backtest.partialProfit("BTCUSDT", 30, 45000, {
26854
+ * const success = await Backtest.commitPartialProfit("BTCUSDT", 30, 45000, {
26212
26855
  * exchangeName: "binance",
26213
26856
  * frameName: "frame1",
26214
26857
  * strategyName: "my-strategy"
@@ -26218,7 +26861,7 @@ class BacktestUtils {
26218
26861
  * }
26219
26862
  * ```
26220
26863
  */
26221
- this.partialProfit = async (symbol, percentToClose, currentPrice, context) => {
26864
+ this.commitPartialProfit = async (symbol, percentToClose, currentPrice, context) => {
26222
26865
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_PARTIAL_PROFIT, {
26223
26866
  symbol,
26224
26867
  percentToClose,
@@ -26257,7 +26900,7 @@ class BacktestUtils {
26257
26900
  * @example
26258
26901
  * ```typescript
26259
26902
  * // Close 40% of LONG position at loss
26260
- * const success = await Backtest.partialLoss("BTCUSDT", 40, 38000, {
26903
+ * const success = await Backtest.commitPartialLoss("BTCUSDT", 40, 38000, {
26261
26904
  * exchangeName: "binance",
26262
26905
  * frameName: "frame1",
26263
26906
  * strategyName: "my-strategy"
@@ -26267,7 +26910,7 @@ class BacktestUtils {
26267
26910
  * }
26268
26911
  * ```
26269
26912
  */
26270
- this.partialLoss = async (symbol, percentToClose, currentPrice, context) => {
26913
+ this.commitPartialLoss = async (symbol, percentToClose, currentPrice, context) => {
26271
26914
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_PARTIAL_LOSS, {
26272
26915
  symbol,
26273
26916
  percentToClose,
@@ -26315,7 +26958,7 @@ class BacktestUtils {
26315
26958
  * // LONG: entry=100, originalSL=90, distance=10%, currentPrice=102
26316
26959
  *
26317
26960
  * // First call: tighten by 5%
26318
- * await Backtest.trailingStop("BTCUSDT", -5, 102, {
26961
+ * await Backtest.commitTrailingStop("BTCUSDT", -5, 102, {
26319
26962
  * exchangeName: "binance",
26320
26963
  * frameName: "frame1",
26321
26964
  * strategyName: "my-strategy"
@@ -26323,15 +26966,15 @@ class BacktestUtils {
26323
26966
  * // newDistance = 10% - 5% = 5%, newSL = 95
26324
26967
  *
26325
26968
  * // Second call: try weaker protection (smaller percentShift)
26326
- * await Backtest.trailingStop("BTCUSDT", -3, 102, context);
26969
+ * await Backtest.commitTrailingStop("BTCUSDT", -3, 102, context);
26327
26970
  * // SKIPPED: newSL=97 < 95 (worse protection, larger % absorbs smaller)
26328
26971
  *
26329
26972
  * // Third call: stronger protection (larger percentShift)
26330
- * await Backtest.trailingStop("BTCUSDT", -7, 102, context);
26973
+ * await Backtest.commitTrailingStop("BTCUSDT", -7, 102, context);
26331
26974
  * // ACCEPTED: newDistance = 10% - 7% = 3%, newSL = 97 > 95 (better protection)
26332
26975
  * ```
26333
26976
  */
26334
- this.trailingStop = async (symbol, percentShift, currentPrice, context) => {
26977
+ this.commitTrailingStop = async (symbol, percentShift, currentPrice, context) => {
26335
26978
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_TRAILING_STOP, {
26336
26979
  symbol,
26337
26980
  percentShift,
@@ -26379,7 +27022,7 @@ class BacktestUtils {
26379
27022
  * // LONG: entry=100, originalTP=110, distance=10%, currentPrice=102
26380
27023
  *
26381
27024
  * // First call: bring TP closer by 3%
26382
- * await Backtest.trailingTake("BTCUSDT", -3, 102, {
27025
+ * await Backtest.commitTrailingTake("BTCUSDT", -3, 102, {
26383
27026
  * exchangeName: "binance",
26384
27027
  * frameName: "frame1",
26385
27028
  * strategyName: "my-strategy"
@@ -26387,15 +27030,15 @@ class BacktestUtils {
26387
27030
  * // newDistance = 10% - 3% = 7%, newTP = 107
26388
27031
  *
26389
27032
  * // Second call: try to move TP further (less conservative)
26390
- * await Backtest.trailingTake("BTCUSDT", 2, 102, context);
27033
+ * await Backtest.commitTrailingTake("BTCUSDT", 2, 102, context);
26391
27034
  * // SKIPPED: newTP=112 > 107 (less conservative, larger % absorbs smaller)
26392
27035
  *
26393
27036
  * // Third call: even more conservative
26394
- * await Backtest.trailingTake("BTCUSDT", -5, 102, context);
27037
+ * await Backtest.commitTrailingTake("BTCUSDT", -5, 102, context);
26395
27038
  * // ACCEPTED: newDistance = 10% - 5% = 5%, newTP = 105 < 107 (more conservative)
26396
27039
  * ```
26397
27040
  */
26398
- this.trailingTake = async (symbol, percentShift, currentPrice, context) => {
27041
+ this.commitTrailingTake = async (symbol, percentShift, currentPrice, context) => {
26399
27042
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_TRAILING_PROFIT, {
26400
27043
  symbol,
26401
27044
  percentShift,
@@ -26428,7 +27071,7 @@ class BacktestUtils {
26428
27071
  *
26429
27072
  * @example
26430
27073
  * ```typescript
26431
- * const moved = await Backtest.breakeven(
27074
+ * const moved = await Backtest.commitBreakeven(
26432
27075
  * "BTCUSDT",
26433
27076
  * 112,
26434
27077
  * { strategyName: "my-strategy", exchangeName: "binance", frameName: "1h" }
@@ -26436,22 +27079,22 @@ class BacktestUtils {
26436
27079
  * console.log(moved); // true (SL moved to entry price)
26437
27080
  * ```
26438
27081
  */
26439
- this.breakeven = async (symbol, currentPrice, context) => {
26440
- backtest$1.loggerService.info("Backtest.breakeven", {
27082
+ this.commitBreakeven = async (symbol, currentPrice, context) => {
27083
+ backtest$1.loggerService.info(BACKTEST_METHOD_NAME_BREAKEVEN, {
26441
27084
  symbol,
26442
27085
  currentPrice,
26443
27086
  context,
26444
27087
  });
26445
- backtest$1.strategyValidationService.validate(context.strategyName, "Backtest.breakeven");
26446
- backtest$1.exchangeValidationService.validate(context.exchangeName, "Backtest.breakeven");
27088
+ backtest$1.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_BREAKEVEN);
27089
+ backtest$1.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_BREAKEVEN);
26447
27090
  {
26448
27091
  const { riskName, riskList, actions } = backtest$1.strategySchemaService.get(context.strategyName);
26449
27092
  riskName &&
26450
- backtest$1.riskValidationService.validate(riskName, "Backtest.breakeven");
27093
+ backtest$1.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BREAKEVEN);
26451
27094
  riskList &&
26452
- riskList.forEach((riskName) => backtest$1.riskValidationService.validate(riskName, "Backtest.breakeven"));
27095
+ riskList.forEach((riskName) => backtest$1.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BREAKEVEN));
26453
27096
  actions &&
26454
- actions.forEach((actionName) => backtest$1.actionValidationService.validate(actionName, "Backtest.breakeven"));
27097
+ actions.forEach((actionName) => backtest$1.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_BREAKEVEN));
26455
27098
  }
26456
27099
  return await backtest$1.strategyCoreService.breakeven(true, symbol, currentPrice, context);
26457
27100
  };
@@ -26623,11 +27266,12 @@ const LIVE_METHOD_NAME_GET_STATUS = "LiveUtils.getStatus";
26623
27266
  const LIVE_METHOD_NAME_GET_PENDING_SIGNAL = "LiveUtils.getPendingSignal";
26624
27267
  const LIVE_METHOD_NAME_GET_SCHEDULED_SIGNAL = "LiveUtils.getScheduledSignal";
26625
27268
  const LIVE_METHOD_NAME_GET_BREAKEVEN = "LiveUtils.getBreakeven";
26626
- const LIVE_METHOD_NAME_CANCEL = "LiveUtils.cancel";
26627
- const LIVE_METHOD_NAME_PARTIAL_PROFIT = "LiveUtils.partialProfit";
26628
- const LIVE_METHOD_NAME_PARTIAL_LOSS = "LiveUtils.partialLoss";
26629
- const LIVE_METHOD_NAME_TRAILING_STOP = "LiveUtils.trailingStop";
26630
- const LIVE_METHOD_NAME_TRAILING_PROFIT = "LiveUtils.trailingTake";
27269
+ const LIVE_METHOD_NAME_BREAKEVEN = "Live.commitBreakeven";
27270
+ const LIVE_METHOD_NAME_CANCEL = "LiveUtils.commitCancel";
27271
+ const LIVE_METHOD_NAME_PARTIAL_PROFIT = "LiveUtils.commitPartialProfit";
27272
+ const LIVE_METHOD_NAME_PARTIAL_LOSS = "LiveUtils.commitPartialLoss";
27273
+ const LIVE_METHOD_NAME_TRAILING_STOP = "LiveUtils.commitTrailingStop";
27274
+ const LIVE_METHOD_NAME_TRAILING_PROFIT = "LiveUtils.commitTrailingTake";
26631
27275
  /**
26632
27276
  * Internal task function that runs live trading and handles completion.
26633
27277
  * Consumes live trading results and updates instance state flags.
@@ -27117,14 +27761,14 @@ class LiveUtils {
27117
27761
  * @example
27118
27762
  * ```typescript
27119
27763
  * // Cancel scheduled signal in live trading with custom ID
27120
- * await Live.cancel("BTCUSDT", "my-strategy", {
27764
+ * await Live.commitCancel("BTCUSDT", "my-strategy", {
27121
27765
  * exchangeName: "binance",
27122
27766
  * frameName: "",
27123
27767
  * strategyName: "my-strategy"
27124
27768
  * }, "manual-cancel-001");
27125
27769
  * ```
27126
27770
  */
27127
- this.cancel = async (symbol, context, cancelId) => {
27771
+ this.commitCancel = async (symbol, context, cancelId) => {
27128
27772
  backtest$1.loggerService.info(LIVE_METHOD_NAME_CANCEL, {
27129
27773
  symbol,
27130
27774
  context,
@@ -27163,7 +27807,7 @@ class LiveUtils {
27163
27807
  * @example
27164
27808
  * ```typescript
27165
27809
  * // Close 30% of LONG position at profit
27166
- * const success = await Live.partialProfit("BTCUSDT", 30, 45000, {
27810
+ * const success = await Live.commitPartialProfit("BTCUSDT", 30, 45000, {
27167
27811
  * exchangeName: "binance",
27168
27812
  * strategyName: "my-strategy"
27169
27813
  * });
@@ -27172,7 +27816,7 @@ class LiveUtils {
27172
27816
  * }
27173
27817
  * ```
27174
27818
  */
27175
- this.partialProfit = async (symbol, percentToClose, currentPrice, context) => {
27819
+ this.commitPartialProfit = async (symbol, percentToClose, currentPrice, context) => {
27176
27820
  backtest$1.loggerService.info(LIVE_METHOD_NAME_PARTIAL_PROFIT, {
27177
27821
  symbol,
27178
27822
  percentToClose,
@@ -27212,7 +27856,7 @@ class LiveUtils {
27212
27856
  * @example
27213
27857
  * ```typescript
27214
27858
  * // Close 40% of LONG position at loss
27215
- * const success = await Live.partialLoss("BTCUSDT", 40, 38000, {
27859
+ * const success = await Live.commitPartialLoss("BTCUSDT", 40, 38000, {
27216
27860
  * exchangeName: "binance",
27217
27861
  * strategyName: "my-strategy"
27218
27862
  * });
@@ -27221,7 +27865,7 @@ class LiveUtils {
27221
27865
  * }
27222
27866
  * ```
27223
27867
  */
27224
- this.partialLoss = async (symbol, percentToClose, currentPrice, context) => {
27868
+ this.commitPartialLoss = async (symbol, percentToClose, currentPrice, context) => {
27225
27869
  backtest$1.loggerService.info(LIVE_METHOD_NAME_PARTIAL_LOSS, {
27226
27870
  symbol,
27227
27871
  percentToClose,
@@ -27270,22 +27914,22 @@ class LiveUtils {
27270
27914
  * // LONG: entry=100, originalSL=90, distance=10%, currentPrice=102
27271
27915
  *
27272
27916
  * // First call: tighten by 5%
27273
- * const success1 = await Live.trailingStop("BTCUSDT", -5, 102, {
27917
+ * const success1 = await Live.commitTrailingStop("BTCUSDT", -5, 102, {
27274
27918
  * exchangeName: "binance",
27275
27919
  * strategyName: "my-strategy"
27276
27920
  * });
27277
27921
  * // success1 = true, newDistance = 10% - 5% = 5%, newSL = 95
27278
27922
  *
27279
27923
  * // Second call: try weaker protection (smaller percentShift)
27280
- * const success2 = await Live.trailingStop("BTCUSDT", -3, 102, context);
27924
+ * const success2 = await Live.commitTrailingStop("BTCUSDT", -3, 102, context);
27281
27925
  * // success2 = false (SKIPPED: newSL=97 < 95, worse protection, larger % absorbs smaller)
27282
27926
  *
27283
27927
  * // Third call: stronger protection (larger percentShift)
27284
- * const success3 = await Live.trailingStop("BTCUSDT", -7, 102, context);
27928
+ * const success3 = await Live.commitTrailingStop("BTCUSDT", -7, 102, context);
27285
27929
  * // success3 = true (ACCEPTED: newDistance = 10% - 7% = 3%, newSL = 97 > 95, better protection)
27286
27930
  * ```
27287
27931
  */
27288
- this.trailingStop = async (symbol, percentShift, currentPrice, context) => {
27932
+ this.commitTrailingStop = async (symbol, percentShift, currentPrice, context) => {
27289
27933
  backtest$1.loggerService.info(LIVE_METHOD_NAME_TRAILING_STOP, {
27290
27934
  symbol,
27291
27935
  percentShift,
@@ -27334,22 +27978,22 @@ class LiveUtils {
27334
27978
  * // LONG: entry=100, originalTP=110, distance=10%, currentPrice=102
27335
27979
  *
27336
27980
  * // First call: bring TP closer by 3%
27337
- * const success1 = await Live.trailingTake("BTCUSDT", -3, 102, {
27981
+ * const success1 = await Live.commitTrailingTake("BTCUSDT", -3, 102, {
27338
27982
  * exchangeName: "binance",
27339
27983
  * strategyName: "my-strategy"
27340
27984
  * });
27341
27985
  * // success1 = true, newDistance = 10% - 3% = 7%, newTP = 107
27342
27986
  *
27343
27987
  * // Second call: try to move TP further (less conservative)
27344
- * const success2 = await Live.trailingTake("BTCUSDT", 2, 102, context);
27988
+ * const success2 = await Live.commitTrailingTake("BTCUSDT", 2, 102, context);
27345
27989
  * // success2 = false (SKIPPED: newTP=112 > 107, less conservative, larger % absorbs smaller)
27346
27990
  *
27347
27991
  * // Third call: even more conservative
27348
- * const success3 = await Live.trailingTake("BTCUSDT", -5, 102, context);
27992
+ * const success3 = await Live.commitTrailingTake("BTCUSDT", -5, 102, context);
27349
27993
  * // success3 = true (ACCEPTED: newDistance = 10% - 5% = 5%, newTP = 105 < 107, more conservative)
27350
27994
  * ```
27351
27995
  */
27352
- this.trailingTake = async (symbol, percentShift, currentPrice, context) => {
27996
+ this.commitTrailingTake = async (symbol, percentShift, currentPrice, context) => {
27353
27997
  backtest$1.loggerService.info(LIVE_METHOD_NAME_TRAILING_PROFIT, {
27354
27998
  symbol,
27355
27999
  percentShift,
@@ -27383,7 +28027,7 @@ class LiveUtils {
27383
28027
  *
27384
28028
  * @example
27385
28029
  * ```typescript
27386
- * const moved = await Live.breakeven(
28030
+ * const moved = await Live.commitBreakeven(
27387
28031
  * "BTCUSDT",
27388
28032
  * 112,
27389
28033
  * { strategyName: "my-strategy", exchangeName: "binance" }
@@ -27391,19 +28035,19 @@ class LiveUtils {
27391
28035
  * console.log(moved); // true (SL moved to entry price)
27392
28036
  * ```
27393
28037
  */
27394
- this.breakeven = async (symbol, currentPrice, context) => {
27395
- backtest$1.loggerService.info("Live.breakeven", {
28038
+ this.commitBreakeven = async (symbol, currentPrice, context) => {
28039
+ backtest$1.loggerService.info(LIVE_METHOD_NAME_BREAKEVEN, {
27396
28040
  symbol,
27397
28041
  currentPrice,
27398
28042
  context,
27399
28043
  });
27400
- backtest$1.strategyValidationService.validate(context.strategyName, "Live.breakeven");
27401
- backtest$1.exchangeValidationService.validate(context.exchangeName, "Live.breakeven");
28044
+ backtest$1.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_BREAKEVEN);
28045
+ backtest$1.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_BREAKEVEN);
27402
28046
  {
27403
28047
  const { riskName, riskList, actions } = backtest$1.strategySchemaService.get(context.strategyName);
27404
- riskName && backtest$1.riskValidationService.validate(riskName, "Live.breakeven");
27405
- riskList && riskList.forEach((riskName) => backtest$1.riskValidationService.validate(riskName, "Live.breakeven"));
27406
- actions && actions.forEach((actionName) => backtest$1.actionValidationService.validate(actionName, "Live.breakeven"));
28048
+ riskName && backtest$1.riskValidationService.validate(riskName, LIVE_METHOD_NAME_BREAKEVEN);
28049
+ riskList && riskList.forEach((riskName) => backtest$1.riskValidationService.validate(riskName, LIVE_METHOD_NAME_BREAKEVEN));
28050
+ actions && actions.forEach((actionName) => backtest$1.actionValidationService.validate(actionName, LIVE_METHOD_NAME_BREAKEVEN));
27407
28051
  }
27408
28052
  return await backtest$1.strategyCoreService.breakeven(false, symbol, currentPrice, {
27409
28053
  strategyName: context.strategyName,
@@ -29231,10 +29875,15 @@ class ExchangeInstance {
29231
29875
  const whenTimestamp = when.getTime();
29232
29876
  const sinceTimestamp = since.getTime();
29233
29877
  const filteredData = allData.filter((candle) => candle.timestamp >= sinceTimestamp && candle.timestamp <= whenTimestamp);
29234
- if (filteredData.length < limit) {
29235
- backtest$1.loggerService.warn(`ExchangeInstance Expected ${limit} candles, got ${filteredData.length}`);
29878
+ // Apply distinct by timestamp to remove duplicates
29879
+ const uniqueData = Array.from(new Map(filteredData.map((candle) => [candle.timestamp, candle])).values());
29880
+ if (filteredData.length !== uniqueData.length) {
29881
+ backtest$1.loggerService.warn(`ExchangeInstance Removed ${filteredData.length - uniqueData.length} duplicate candles by timestamp`);
29236
29882
  }
29237
- return filteredData;
29883
+ if (uniqueData.length < limit) {
29884
+ backtest$1.loggerService.warn(`ExchangeInstance Expected ${limit} candles, got ${uniqueData.length}`);
29885
+ }
29886
+ return uniqueData;
29238
29887
  };
29239
29888
  /**
29240
29889
  * Calculates VWAP (Volume Weighted Average Price) from last N 1m candles.
@@ -30413,10 +31062,11 @@ const METHOD_NAME_INIT = "ActionBase.init";
30413
31062
  const METHOD_NAME_EVENT = "ActionBase.event";
30414
31063
  const METHOD_NAME_SIGNAL_LIVE = "ActionBase.signalLive";
30415
31064
  const METHOD_NAME_SIGNAL_BACKTEST = "ActionBase.signalBacktest";
30416
- const METHOD_NAME_BREAKEVEN = "ActionBase.breakeven";
30417
- const METHOD_NAME_PARTIAL_PROFIT = "ActionBase.partialProfit";
30418
- const METHOD_NAME_PARTIAL_LOSS = "ActionBase.partialLoss";
30419
- const METHOD_NAME_PING = "ActionBase.ping";
31065
+ const METHOD_NAME_BREAKEVEN_AVAILABLE = "ActionBase.breakevenAvailable";
31066
+ const METHOD_NAME_PARTIAL_PROFIT_AVAILABLE = "ActionBase.partialProfitAvailable";
31067
+ const METHOD_NAME_PARTIAL_LOSS_AVAILABLE = "ActionBase.partialLossAvailable";
31068
+ const METHOD_NAME_PING_SCHEDULED = "ActionBase.pingScheduled";
31069
+ const METHOD_NAME_PING_ACTIVE = "ActionBase.pingActive";
30420
31070
  const METHOD_NAME_RISK_REJECTION = "ActionBase.riskRejection";
30421
31071
  const METHOD_NAME_DISPOSE = "ActionBase.dispose";
30422
31072
  const DEFAULT_SOURCE = "default";
@@ -30447,10 +31097,11 @@ const DEFAULT_SOURCE = "default";
30447
31097
  * - signal() - Called on every tick/candle (all modes)
30448
31098
  * - signalLive() - Called only in live mode
30449
31099
  * - signalBacktest() - Called only in backtest mode
30450
- * - breakeven() - Called when SL moved to entry
30451
- * - partialProfit() - Called on profit milestones (10%, 20%, etc.)
30452
- * - partialLoss() - Called on loss milestones (-10%, -20%, etc.)
30453
- * - ping() - Called every minute during scheduled signal monitoring
31100
+ * - breakevenAvailable() - Called when SL moved to entry
31101
+ * - partialProfitAvailable() - Called on profit milestones (10%, 20%, etc.)
31102
+ * - partialLossAvailable() - Called on loss milestones (-10%, -20%, etc.)
31103
+ * - pingScheduled() - Called every minute during scheduled signal monitoring
31104
+ * - pingActive() - Called every minute during active pending signal monitoring
30454
31105
  * - riskRejection() - Called when signal rejected by risk management
30455
31106
  *
30456
31107
  * @example
@@ -30491,7 +31142,7 @@ const DEFAULT_SOURCE = "default";
30491
31142
  * }
30492
31143
  *
30493
31144
  * // Register the action
30494
- * addAction({
31145
+ * addActionSchema({
30495
31146
  * actionName: "telegram-notifier",
30496
31147
  * handler: TelegramNotifier
30497
31148
  * });
@@ -30533,11 +31184,13 @@ class ActionBase {
30533
31184
  * @param strategyName - Strategy identifier this action is attached to
30534
31185
  * @param frameName - Timeframe identifier this action is attached to
30535
31186
  * @param actionName - Action identifier
31187
+ * @param backtest - If running in backtest
30536
31188
  */
30537
- constructor(strategyName, frameName, actionName) {
31189
+ constructor(strategyName, frameName, actionName, backtest) {
30538
31190
  this.strategyName = strategyName;
30539
31191
  this.frameName = frameName;
30540
31192
  this.actionName = actionName;
31193
+ this.backtest = backtest;
30541
31194
  }
30542
31195
  /**
30543
31196
  * Initializes the action handler.
@@ -30661,7 +31314,7 @@ class ActionBase {
30661
31314
  * Called once per signal when price moves far enough to cover fees and slippage.
30662
31315
  * Breakeven threshold: (CC_PERCENT_SLIPPAGE + CC_PERCENT_FEE) * 2 + CC_BREAKEVEN_THRESHOLD
30663
31316
  *
30664
- * Triggered by: ActionCoreService.breakeven() via BreakevenConnectionService
31317
+ * Triggered by: ActionCoreService.breakevenAvailable() via BreakevenConnectionService
30665
31318
  * Source: breakevenSubject.next() in CREATE_COMMIT_BREAKEVEN_FN callback
30666
31319
  * Frequency: Once per signal when threshold reached
30667
31320
  *
@@ -30671,7 +31324,7 @@ class ActionBase {
30671
31324
  *
30672
31325
  * @example
30673
31326
  * ```typescript
30674
- * async breakeven(event: BreakevenContract) {
31327
+ * async breakevenAvailable(event: BreakevenContract) {
30675
31328
  * await this.telegram.send(
30676
31329
  * `[${event.strategyName}] Breakeven reached! ` +
30677
31330
  * `Signal: ${event.data.side} @ ${event.currentPrice}`
@@ -30679,8 +31332,8 @@ class ActionBase {
30679
31332
  * }
30680
31333
  * ```
30681
31334
  */
30682
- breakeven(event, source = DEFAULT_SOURCE) {
30683
- backtest$1.loggerService.info(METHOD_NAME_BREAKEVEN, {
31335
+ breakevenAvailable(event, source = DEFAULT_SOURCE) {
31336
+ backtest$1.loggerService.info(METHOD_NAME_BREAKEVEN_AVAILABLE, {
30684
31337
  event,
30685
31338
  source,
30686
31339
  });
@@ -30691,7 +31344,7 @@ class ActionBase {
30691
31344
  * Called once per profit level per signal (deduplicated).
30692
31345
  * Use to track profit milestones and adjust position management.
30693
31346
  *
30694
- * Triggered by: ActionCoreService.partialProfit() via PartialConnectionService
31347
+ * Triggered by: ActionCoreService.partialProfitAvailable() via PartialConnectionService
30695
31348
  * Source: partialProfitSubject.next() in CREATE_COMMIT_PROFIT_FN callback
30696
31349
  * Frequency: Once per profit level per signal
30697
31350
  *
@@ -30701,7 +31354,7 @@ class ActionBase {
30701
31354
  *
30702
31355
  * @example
30703
31356
  * ```typescript
30704
- * async partialProfit(event: PartialProfitContract) {
31357
+ * async partialProfitAvailable(event: PartialProfitContract) {
30705
31358
  * await this.telegram.send(
30706
31359
  * `[${event.strategyName}] Profit ${event.level}% reached! ` +
30707
31360
  * `Current price: ${event.currentPrice}`
@@ -30710,8 +31363,8 @@ class ActionBase {
30710
31363
  * }
30711
31364
  * ```
30712
31365
  */
30713
- partialProfit(event, source = DEFAULT_SOURCE) {
30714
- backtest$1.loggerService.info(METHOD_NAME_PARTIAL_PROFIT, {
31366
+ partialProfitAvailable(event, source = DEFAULT_SOURCE) {
31367
+ backtest$1.loggerService.info(METHOD_NAME_PARTIAL_PROFIT_AVAILABLE, {
30715
31368
  event,
30716
31369
  source,
30717
31370
  });
@@ -30722,7 +31375,7 @@ class ActionBase {
30722
31375
  * Called once per loss level per signal (deduplicated).
30723
31376
  * Use to track loss milestones and implement risk management actions.
30724
31377
  *
30725
- * Triggered by: ActionCoreService.partialLoss() via PartialConnectionService
31378
+ * Triggered by: ActionCoreService.partialLossAvailable() via PartialConnectionService
30726
31379
  * Source: partialLossSubject.next() in CREATE_COMMIT_LOSS_FN callback
30727
31380
  * Frequency: Once per loss level per signal
30728
31381
  *
@@ -30732,7 +31385,7 @@ class ActionBase {
30732
31385
  *
30733
31386
  * @example
30734
31387
  * ```typescript
30735
- * async partialLoss(event: PartialLossContract) {
31388
+ * async partialLossAvailable(event: PartialLossContract) {
30736
31389
  * await this.telegram.send(
30737
31390
  * `[${event.strategyName}] Loss ${event.level}% reached! ` +
30738
31391
  * `Current price: ${event.currentPrice}`
@@ -30741,37 +31394,66 @@ class ActionBase {
30741
31394
  * }
30742
31395
  * ```
30743
31396
  */
30744
- partialLoss(event, source = DEFAULT_SOURCE) {
30745
- backtest$1.loggerService.info(METHOD_NAME_PARTIAL_LOSS, {
31397
+ partialLossAvailable(event, source = DEFAULT_SOURCE) {
31398
+ backtest$1.loggerService.info(METHOD_NAME_PARTIAL_LOSS_AVAILABLE, {
30746
31399
  event,
30747
31400
  source,
30748
31401
  });
30749
31402
  }
30750
31403
  /**
30751
- * Handles ping events during scheduled signal monitoring.
31404
+ * Handles scheduled ping events during scheduled signal monitoring.
30752
31405
  *
30753
31406
  * Called every minute while a scheduled signal is waiting for activation.
30754
31407
  * Use to monitor pending signals and track wait time.
30755
31408
  *
30756
- * Triggered by: ActionCoreService.ping() via StrategyConnectionService
30757
- * Source: pingSubject.next() in CREATE_COMMIT_PING_FN callback
31409
+ * Triggered by: ActionCoreService.pingScheduled() via StrategyConnectionService
31410
+ * Source: schedulePingSubject.next() in CREATE_COMMIT_SCHEDULE_PING_FN callback
30758
31411
  * Frequency: Every minute while scheduled signal is waiting
30759
31412
  *
30760
- * Default implementation: Logs ping event.
31413
+ * Default implementation: Logs scheduled ping event.
30761
31414
  *
30762
31415
  * @param event - Scheduled signal monitoring data with symbol, strategy info, signal data, timestamp
30763
31416
  *
30764
31417
  * @example
30765
31418
  * ```typescript
30766
- * ping(event: PingContract) {
31419
+ * pingScheduled(event: SchedulePingContract) {
30767
31420
  * const waitTime = Date.now() - event.data.timestampScheduled;
30768
31421
  * const waitMinutes = Math.floor(waitTime / 60000);
30769
31422
  * console.log(`Scheduled signal waiting ${waitMinutes} minutes`);
30770
31423
  * }
30771
31424
  * ```
30772
31425
  */
30773
- ping(event, source = DEFAULT_SOURCE) {
30774
- backtest$1.loggerService.info(METHOD_NAME_PING, {
31426
+ pingScheduled(event, source = DEFAULT_SOURCE) {
31427
+ backtest$1.loggerService.info(METHOD_NAME_PING_SCHEDULED, {
31428
+ event,
31429
+ source,
31430
+ });
31431
+ }
31432
+ /**
31433
+ * Handles active ping events during active pending signal monitoring.
31434
+ *
31435
+ * Called every minute while a pending signal is active (position open).
31436
+ * Use to monitor active positions and track lifecycle.
31437
+ *
31438
+ * Triggered by: ActionCoreService.pingActive() via StrategyConnectionService
31439
+ * Source: activePingSubject.next() in CREATE_COMMIT_ACTIVE_PING_FN callback
31440
+ * Frequency: Every minute while pending signal is active
31441
+ *
31442
+ * Default implementation: Logs active ping event.
31443
+ *
31444
+ * @param event - Active pending signal monitoring data with symbol, strategy info, signal data, timestamp
31445
+ *
31446
+ * @example
31447
+ * ```typescript
31448
+ * pingActive(event: ActivePingContract) {
31449
+ * const holdTime = Date.now() - event.data.pendingAt;
31450
+ * const holdMinutes = Math.floor(holdTime / 60000);
31451
+ * console.log(`Active signal holding ${holdMinutes} minutes`);
31452
+ * }
31453
+ * ```
31454
+ */
31455
+ pingActive(event, source = DEFAULT_SOURCE) {
31456
+ backtest$1.loggerService.info(METHOD_NAME_PING_ACTIVE, {
30775
31457
  event,
30776
31458
  source,
30777
31459
  });
@@ -30919,42 +31601,59 @@ exports.ReportBase = ReportBase;
30919
31601
  exports.Risk = Risk;
30920
31602
  exports.Schedule = Schedule;
30921
31603
  exports.Walker = Walker;
30922
- exports.addAction = addAction;
30923
- exports.addExchange = addExchange;
30924
- exports.addFrame = addFrame;
30925
- exports.addOptimizer = addOptimizer;
30926
- exports.addRisk = addRisk;
30927
- exports.addSizing = addSizing;
30928
- exports.addStrategy = addStrategy;
30929
- exports.addWalker = addWalker;
30930
- exports.breakeven = breakeven;
30931
- exports.cancel = cancel;
30932
- exports.dumpSignal = dumpSignal;
31604
+ exports.addActionSchema = addActionSchema;
31605
+ exports.addExchangeSchema = addExchangeSchema;
31606
+ exports.addFrameSchema = addFrameSchema;
31607
+ exports.addOptimizerSchema = addOptimizerSchema;
31608
+ exports.addRiskSchema = addRiskSchema;
31609
+ exports.addSizingSchema = addSizingSchema;
31610
+ exports.addStrategySchema = addStrategySchema;
31611
+ exports.addWalkerSchema = addWalkerSchema;
31612
+ exports.commitBreakeven = commitBreakeven;
31613
+ exports.commitCancel = commitCancel;
31614
+ exports.commitPartialLoss = commitPartialLoss;
31615
+ exports.commitPartialProfit = commitPartialProfit;
31616
+ exports.commitTrailingStop = commitTrailingStop;
31617
+ exports.commitTrailingTake = commitTrailingTake;
31618
+ exports.dumpSignalData = dumpSignalData;
30933
31619
  exports.emitters = emitters;
30934
31620
  exports.formatPrice = formatPrice;
30935
31621
  exports.formatQuantity = formatQuantity;
30936
31622
  exports.get = get;
31623
+ exports.getActionSchema = getActionSchema;
30937
31624
  exports.getAveragePrice = getAveragePrice;
31625
+ exports.getBacktestTimeframe = getBacktestTimeframe;
30938
31626
  exports.getCandles = getCandles;
30939
31627
  exports.getColumns = getColumns;
30940
31628
  exports.getConfig = getConfig;
31629
+ exports.getContext = getContext;
30941
31630
  exports.getDate = getDate;
30942
31631
  exports.getDefaultColumns = getDefaultColumns;
30943
31632
  exports.getDefaultConfig = getDefaultConfig;
31633
+ exports.getExchangeSchema = getExchangeSchema;
31634
+ exports.getFrameSchema = getFrameSchema;
30944
31635
  exports.getMode = getMode;
31636
+ exports.getOptimizerSchema = getOptimizerSchema;
30945
31637
  exports.getOrderBook = getOrderBook;
31638
+ exports.getRiskSchema = getRiskSchema;
31639
+ exports.getSizingSchema = getSizingSchema;
31640
+ exports.getStrategySchema = getStrategySchema;
31641
+ exports.getSymbol = getSymbol;
31642
+ exports.getWalkerSchema = getWalkerSchema;
30946
31643
  exports.hasTradeContext = hasTradeContext;
30947
31644
  exports.lib = backtest;
30948
- exports.listExchanges = listExchanges;
30949
- exports.listFrames = listFrames;
30950
- exports.listOptimizers = listOptimizers;
30951
- exports.listRisks = listRisks;
30952
- exports.listSizings = listSizings;
30953
- exports.listStrategies = listStrategies;
30954
- exports.listWalkers = listWalkers;
31645
+ exports.listExchangeSchema = listExchangeSchema;
31646
+ exports.listFrameSchema = listFrameSchema;
31647
+ exports.listOptimizerSchema = listOptimizerSchema;
31648
+ exports.listRiskSchema = listRiskSchema;
31649
+ exports.listSizingSchema = listSizingSchema;
31650
+ exports.listStrategySchema = listStrategySchema;
31651
+ exports.listWalkerSchema = listWalkerSchema;
31652
+ exports.listenActivePing = listenActivePing;
31653
+ exports.listenActivePingOnce = listenActivePingOnce;
30955
31654
  exports.listenBacktestProgress = listenBacktestProgress;
30956
- exports.listenBreakeven = listenBreakeven;
30957
- exports.listenBreakevenOnce = listenBreakevenOnce;
31655
+ exports.listenBreakevenAvailable = listenBreakevenAvailable;
31656
+ exports.listenBreakevenAvailableOnce = listenBreakevenAvailableOnce;
30958
31657
  exports.listenDoneBacktest = listenDoneBacktest;
30959
31658
  exports.listenDoneBacktestOnce = listenDoneBacktestOnce;
30960
31659
  exports.listenDoneLive = listenDoneLive;
@@ -30964,15 +31663,15 @@ exports.listenDoneWalkerOnce = listenDoneWalkerOnce;
30964
31663
  exports.listenError = listenError;
30965
31664
  exports.listenExit = listenExit;
30966
31665
  exports.listenOptimizerProgress = listenOptimizerProgress;
30967
- exports.listenPartialLoss = listenPartialLoss;
30968
- exports.listenPartialLossOnce = listenPartialLossOnce;
30969
- exports.listenPartialProfit = listenPartialProfit;
30970
- exports.listenPartialProfitOnce = listenPartialProfitOnce;
31666
+ exports.listenPartialLossAvailable = listenPartialLossAvailable;
31667
+ exports.listenPartialLossAvailableOnce = listenPartialLossAvailableOnce;
31668
+ exports.listenPartialProfitAvailable = listenPartialProfitAvailable;
31669
+ exports.listenPartialProfitAvailableOnce = listenPartialProfitAvailableOnce;
30971
31670
  exports.listenPerformance = listenPerformance;
30972
- exports.listenPing = listenPing;
30973
- exports.listenPingOnce = listenPingOnce;
30974
31671
  exports.listenRisk = listenRisk;
30975
31672
  exports.listenRiskOnce = listenRiskOnce;
31673
+ exports.listenSchedulePing = listenSchedulePing;
31674
+ exports.listenSchedulePingOnce = listenSchedulePingOnce;
30976
31675
  exports.listenSignal = listenSignal;
30977
31676
  exports.listenSignalBacktest = listenSignalBacktest;
30978
31677
  exports.listenSignalBacktestOnce = listenSignalBacktestOnce;
@@ -30984,22 +31683,18 @@ exports.listenWalker = listenWalker;
30984
31683
  exports.listenWalkerComplete = listenWalkerComplete;
30985
31684
  exports.listenWalkerOnce = listenWalkerOnce;
30986
31685
  exports.listenWalkerProgress = listenWalkerProgress;
30987
- exports.overrideAction = overrideAction;
30988
- exports.overrideExchange = overrideExchange;
30989
- exports.overrideFrame = overrideFrame;
30990
- exports.overrideOptimizer = overrideOptimizer;
30991
- exports.overrideRisk = overrideRisk;
30992
- exports.overrideSizing = overrideSizing;
30993
- exports.overrideStrategy = overrideStrategy;
30994
- exports.overrideWalker = overrideWalker;
30995
- exports.partialLoss = partialLoss;
30996
- exports.partialProfit = partialProfit;
31686
+ exports.overrideActionSchema = overrideActionSchema;
31687
+ exports.overrideExchangeSchema = overrideExchangeSchema;
31688
+ exports.overrideFrameSchema = overrideFrameSchema;
31689
+ exports.overrideOptimizerSchema = overrideOptimizerSchema;
31690
+ exports.overrideRiskSchema = overrideRiskSchema;
31691
+ exports.overrideSizingSchema = overrideSizingSchema;
31692
+ exports.overrideStrategySchema = overrideStrategySchema;
31693
+ exports.overrideWalkerSchema = overrideWalkerSchema;
30997
31694
  exports.roundTicks = roundTicks;
30998
31695
  exports.set = set;
30999
31696
  exports.setColumns = setColumns;
31000
31697
  exports.setConfig = setConfig;
31001
31698
  exports.setLogger = setLogger;
31002
31699
  exports.stop = stop;
31003
- exports.trailingStop = trailingStop;
31004
- exports.trailingTake = trailingTake;
31005
31700
  exports.validate = validate;