backtest-kit 1.13.4 → 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,14 @@ 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);
3417
3434
  }
3418
3435
  }, {
3419
3436
  when: new Date(timestamp),
@@ -3422,7 +3439,33 @@ const CALL_PING_CALLBACKS_FN = functoolsKit.trycatch(beginTime(async (self, symb
3422
3439
  });
3423
3440
  }), {
3424
3441
  fallback: (error) => {
3425
- const message = "ClientStrategy CALL_PING_CALLBACKS_FN thrown";
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);
3460
+ }
3461
+ }, {
3462
+ when: new Date(timestamp),
3463
+ symbol: symbol,
3464
+ backtest: backtest,
3465
+ });
3466
+ }), {
3467
+ fallback: (error) => {
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,15 @@ 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
6011
6075
  */
6012
- const CREATE_COMMIT_PING_FN = (self) => async (symbol, strategyName, exchangeName, data, backtest, timestamp) => {
6076
+ const CREATE_COMMIT_SCHEDULE_PING_FN = (self) => async (symbol, strategyName, exchangeName, data, backtest, timestamp) => {
6013
6077
  const event = {
6014
6078
  symbol,
6015
6079
  strategyName,
@@ -6018,8 +6082,29 @@ const CREATE_COMMIT_PING_FN = (self) => async (symbol, strategyName, exchangeNam
6018
6082
  backtest,
6019
6083
  timestamp,
6020
6084
  };
6021
- await pingSubject.next(event);
6022
- await self.actionCoreService.ping(backtest, event, { strategyName, exchangeName, frameName: data.frameName });
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
6096
+ */
6097
+ const CREATE_COMMIT_ACTIVE_PING_FN = (self) => async (symbol, strategyName, exchangeName, data, backtest, timestamp) => {
6098
+ const event = {
6099
+ symbol,
6100
+ strategyName,
6101
+ exchangeName,
6102
+ data,
6103
+ backtest,
6104
+ timestamp,
6105
+ };
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);
7565
7651
  }
7566
7652
  }, {
7567
7653
  fallback: (error) => {
7568
- const message = "ClientAction CALL_PING_CALLBACK_FN thrown";
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);
7668
+ }
7669
+ }, {
7670
+ fallback: (error) => {
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,18 @@ 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.
7893
7997
  */
7894
- async ping(event) {
7895
- this.params.logger.debug("ClientAction ping", {
7998
+ async pingScheduled(event) {
7999
+ this.params.logger.debug("ClientAction pingScheduled", {
7896
8000
  actionName: this.params.actionName,
7897
8001
  strategyName: this.params.strategyName,
7898
8002
  frameName: this.params.frameName,
@@ -7901,11 +8005,31 @@ class ClientAction {
7901
8005
  await this.waitForInit();
7902
8006
  }
7903
8007
  // Call handler method if defined
7904
- if (this._handlerInstance?.ping) {
7905
- await this._handlerInstance.ping(event);
8008
+ if (this._handlerInstance?.pingScheduled) {
8009
+ await this._handlerInstance.pingScheduled(event);
7906
8010
  }
7907
8011
  // Call callback if defined
7908
- await CALL_PING_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
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.
8017
+ */
8018
+ async pingActive(event) {
8019
+ this.params.logger.debug("ClientAction pingActive", {
8020
+ actionName: this.params.actionName,
8021
+ strategyName: this.params.strategyName,
8022
+ frameName: this.params.frameName,
8023
+ });
8024
+ if (!this._handlerInstance) {
8025
+ await this.waitForInit();
8026
+ }
8027
+ // Call handler method if defined
8028
+ if (this._handlerInstance?.pingActive) {
8029
+ await this._handlerInstance.pingActive(event);
8030
+ }
8031
+ // Call callback if defined
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", {
8108
8232
  backtest,
8109
8233
  context,
8110
8234
  });
8111
8235
  const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
8112
- await action.partialLoss(event);
8236
+ await action.partialLossAvailable(event);
8113
8237
  };
8114
8238
  /**
8115
- * Routes ping event to appropriate ClientAction instance.
8239
+ * Routes scheduled ping event to appropriate ClientAction instance.
8116
8240
  *
8117
- * @param event - Ping event data
8241
+ * @param event - Scheduled ping event data
8118
8242
  * @param backtest - Whether running in backtest mode
8119
8243
  * @param context - Execution context with action name, strategy name, exchange name, frame name
8120
8244
  */
8121
- this.ping = async (event, backtest, context) => {
8122
- this.loggerService.log("actionConnectionService ping", {
8245
+ this.pingScheduled = async (event, backtest, context) => {
8246
+ this.loggerService.log("actionConnectionService pingScheduled", {
8123
8247
  backtest,
8124
8248
  context,
8125
8249
  });
8126
8250
  const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
8127
- await action.ping(event);
8251
+ await action.pingScheduled(event);
8252
+ };
8253
+ /**
8254
+ * Routes active ping event to appropriate ClientAction instance.
8255
+ *
8256
+ * @param event - Active ping event data
8257
+ * @param backtest - Whether running in backtest mode
8258
+ * @param context - Execution context with action name, strategy name, exchange name, frame name
8259
+ */
8260
+ this.pingActive = async (event, backtest, context) => {
8261
+ this.loggerService.log("actionConnectionService pingActive", {
8262
+ backtest,
8263
+ context,
8264
+ });
8265
+ const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
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,23 +22957,23 @@ const backtest = {
22631
22957
  init();
22632
22958
  var backtest$1 = backtest;
22633
22959
 
22634
- const GET_TIMEFRAME_METHOD_NAME = "get.getTimeframe";
22960
+ const GET_TIMEFRAME_METHOD_NAME = "get.getBacktestTimeframe";
22635
22961
  /**
22636
22962
  * Retrieves current backtest timeframe for given symbol.
22637
22963
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
22638
22964
  * @returns Promise resolving to array of Date objects representing tick timestamps
22639
22965
  * @throws Error if called outside of backtest execution context
22640
22966
  */
22641
- async function getCurrentTimeframe(symbol) {
22967
+ async function getBacktestTimeframe(symbol) {
22642
22968
  backtest$1.loggerService.info(GET_TIMEFRAME_METHOD_NAME, { symbol });
22643
22969
  if (!ExecutionContextService.hasContext()) {
22644
- throw new Error("getCurrentTimeframe requires an execution context");
22970
+ throw new Error("getBacktestTimeframe requires an execution context");
22645
22971
  }
22646
22972
  if (!MethodContextService.hasContext()) {
22647
- throw new Error("getCurrentTimeframe requires a method context");
22973
+ throw new Error("getBacktestTimeframe requires a method context");
22648
22974
  }
22649
22975
  if (!backtest$1.executionContextService.context.backtest) {
22650
- throw new Error("getCurrentTimeframe can only be used during backtest execution");
22976
+ throw new Error("getBacktestTimeframe can only be used during backtest execution");
22651
22977
  }
22652
22978
  return await backtest$1.frameCoreService.getTimeframe(symbol, backtest$1.methodContextService.context.frameName);
22653
22979
  }
@@ -22847,14 +23173,14 @@ async function validate(args = {}) {
22847
23173
  return await validateInternal(args);
22848
23174
  }
22849
23175
 
22850
- const GET_STRATEGY_METHOD_NAME = "get.getStrategy";
22851
- const GET_EXCHANGE_METHOD_NAME = "get.getExchange";
22852
- const GET_FRAME_METHOD_NAME = "get.getFrame";
22853
- const GET_WALKER_METHOD_NAME = "get.getWalker";
22854
- const GET_SIZING_METHOD_NAME = "get.getSizing";
22855
- const GET_RISK_METHOD_NAME = "get.getRisk";
22856
- const GET_OPTIMIZER_METHOD_NAME = "get.getOptimizer";
22857
- const GET_ACTION_METHOD_NAME = "get.getAction";
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";
22858
23184
  /**
22859
23185
  * Retrieves a registered strategy schema by name.
22860
23186
  *
@@ -22869,7 +23195,7 @@ const GET_ACTION_METHOD_NAME = "get.getAction";
22869
23195
  * console.log(strategy.getSignal); // async function
22870
23196
  * ```
22871
23197
  */
22872
- function getStrategy(strategyName) {
23198
+ function getStrategySchema(strategyName) {
22873
23199
  backtest$1.loggerService.log(GET_STRATEGY_METHOD_NAME, {
22874
23200
  strategyName,
22875
23201
  });
@@ -22890,7 +23216,7 @@ function getStrategy(strategyName) {
22890
23216
  * console.log(exchange.formatPrice); // async function
22891
23217
  * ```
22892
23218
  */
22893
- function getExchange(exchangeName) {
23219
+ function getExchangeSchema(exchangeName) {
22894
23220
  backtest$1.loggerService.log(GET_EXCHANGE_METHOD_NAME, {
22895
23221
  exchangeName,
22896
23222
  });
@@ -22912,7 +23238,7 @@ function getExchange(exchangeName) {
22912
23238
  * console.log(frame.endDate); // Date object
22913
23239
  * ```
22914
23240
  */
22915
- function getFrame(frameName) {
23241
+ function getFrameSchema(frameName) {
22916
23242
  backtest$1.loggerService.log(GET_FRAME_METHOD_NAME, {
22917
23243
  frameName,
22918
23244
  });
@@ -22935,7 +23261,7 @@ function getFrame(frameName) {
22935
23261
  * console.log(walker.metric); // "sharpeRatio"
22936
23262
  * ```
22937
23263
  */
22938
- function getWalker(walkerName) {
23264
+ function getWalkerSchema(walkerName) {
22939
23265
  backtest$1.loggerService.log(GET_WALKER_METHOD_NAME, {
22940
23266
  walkerName,
22941
23267
  });
@@ -22957,7 +23283,7 @@ function getWalker(walkerName) {
22957
23283
  * console.log(sizing.maxPositionPercentage); // 10
22958
23284
  * ```
22959
23285
  */
22960
- function getSizing(sizingName) {
23286
+ function getSizingSchema(sizingName) {
22961
23287
  backtest$1.loggerService.log(GET_SIZING_METHOD_NAME, {
22962
23288
  sizingName,
22963
23289
  });
@@ -22978,7 +23304,7 @@ function getSizing(sizingName) {
22978
23304
  * console.log(risk.validations); // Array of validation functions
22979
23305
  * ```
22980
23306
  */
22981
- function getRisk(riskName) {
23307
+ function getRiskSchema(riskName) {
22982
23308
  backtest$1.loggerService.log(GET_RISK_METHOD_NAME, {
22983
23309
  riskName,
22984
23310
  });
@@ -23001,7 +23327,7 @@ function getRisk(riskName) {
23001
23327
  * console.log(optimizer.getPrompt); // async function
23002
23328
  * ```
23003
23329
  */
23004
- function getOptimizer(optimizerName) {
23330
+ function getOptimizerSchema(optimizerName) {
23005
23331
  backtest$1.loggerService.log(GET_OPTIMIZER_METHOD_NAME, {
23006
23332
  optimizerName,
23007
23333
  });
@@ -23022,7 +23348,7 @@ function getOptimizer(optimizerName) {
23022
23348
  * console.log(action.callbacks); // Optional lifecycle callbacks
23023
23349
  * ```
23024
23350
  */
23025
- function getAction(actionName) {
23351
+ function getActionSchema(actionName) {
23026
23352
  backtest$1.loggerService.log(GET_ACTION_METHOD_NAME, {
23027
23353
  actionName,
23028
23354
  });
@@ -23036,6 +23362,8 @@ const FORMAT_PRICE_METHOD_NAME = "exchange.formatPrice";
23036
23362
  const FORMAT_QUANTITY_METHOD_NAME = "exchange.formatQuantity";
23037
23363
  const GET_DATE_METHOD_NAME = "exchange.getDate";
23038
23364
  const GET_MODE_METHOD_NAME = "exchange.getMode";
23365
+ const GET_SYMBOL_METHOD_NAME = "exchange.getSymbol";
23366
+ const GET_CONTEXT_METHOD_NAME = "exchange.getContext";
23039
23367
  const HAS_TRADE_CONTEXT_METHOD_NAME = "exchange.hasTradeContext";
23040
23368
  const GET_ORDER_BOOK_METHOD_NAME = "exchange.getOrderBook";
23041
23369
  /**
@@ -23218,6 +23546,48 @@ async function getMode() {
23218
23546
  const { backtest: bt } = backtest$1.executionContextService.context;
23219
23547
  return bt ? "backtest" : "live";
23220
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
+ }
23221
23591
  /**
23222
23592
  * Fetches order book for a trading pair from the registered exchange.
23223
23593
  *
@@ -23254,52 +23624,12 @@ async function getOrderBook(symbol, depth) {
23254
23624
  return await backtest$1.exchangeConnectionService.getOrderBook(symbol, depth);
23255
23625
  }
23256
23626
 
23257
- const STOP_METHOD_NAME = "strategy.stop";
23258
- const CANCEL_METHOD_NAME = "strategy.cancel";
23259
- const PARTIAL_PROFIT_METHOD_NAME = "strategy.partialProfit";
23260
- const PARTIAL_LOSS_METHOD_NAME = "strategy.partialLoss";
23261
- const TRAILING_STOP_METHOD_NAME = "strategy.trailingStop";
23262
- const TRAILING_PROFIT_METHOD_NAME = "strategy.trailingTake";
23263
- const BREAKEVEN_METHOD_NAME = "strategy.breakeven";
23264
- /**
23265
- * Stops the strategy from generating new signals.
23266
- *
23267
- * Sets internal flag to prevent strategy from opening new signals.
23268
- * Current active signal (if any) will complete normally.
23269
- * Backtest/Live mode will stop at the next safe point (idle state or after signal closes).
23270
- *
23271
- * Automatically detects backtest/live mode from execution context.
23272
- *
23273
- * @param symbol - Trading pair symbol
23274
- * @param strategyName - Strategy name to stop
23275
- * @returns Promise that resolves when stop flag is set
23276
- *
23277
- * @example
23278
- * ```typescript
23279
- * import { stop } from "backtest-kit";
23280
- *
23281
- * // Stop strategy after some condition
23282
- * await stop("BTCUSDT", "my-strategy");
23283
- * ```
23284
- */
23285
- async function stop(symbol) {
23286
- backtest$1.loggerService.info(STOP_METHOD_NAME, {
23287
- symbol,
23288
- });
23289
- if (!ExecutionContextService.hasContext()) {
23290
- throw new Error("stop requires an execution context");
23291
- }
23292
- if (!MethodContextService.hasContext()) {
23293
- throw new Error("stop requires a method context");
23294
- }
23295
- const { backtest: isBacktest } = backtest$1.executionContextService.context;
23296
- const { exchangeName, frameName, strategyName } = backtest$1.methodContextService.context;
23297
- await backtest$1.strategyCoreService.stop(isBacktest, symbol, {
23298
- exchangeName,
23299
- frameName,
23300
- strategyName,
23301
- });
23302
- }
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";
23303
23633
  /**
23304
23634
  * Cancels the scheduled signal without stopping the strategy.
23305
23635
  *
@@ -23322,7 +23652,7 @@ async function stop(symbol) {
23322
23652
  * await cancel("BTCUSDT", "my-strategy", "manual-cancel-001");
23323
23653
  * ```
23324
23654
  */
23325
- async function cancel(symbol, cancelId) {
23655
+ async function commitCancel(symbol, cancelId) {
23326
23656
  backtest$1.loggerService.info(CANCEL_METHOD_NAME, {
23327
23657
  symbol,
23328
23658
  cancelId,
@@ -23364,7 +23694,7 @@ async function cancel(symbol, cancelId) {
23364
23694
  * }
23365
23695
  * ```
23366
23696
  */
23367
- async function partialProfit(symbol, percentToClose) {
23697
+ async function commitPartialProfit(symbol, percentToClose) {
23368
23698
  backtest$1.loggerService.info(PARTIAL_PROFIT_METHOD_NAME, {
23369
23699
  symbol,
23370
23700
  percentToClose,
@@ -23407,7 +23737,7 @@ async function partialProfit(symbol, percentToClose) {
23407
23737
  * }
23408
23738
  * ```
23409
23739
  */
23410
- async function partialLoss(symbol, percentToClose) {
23740
+ async function commitPartialLoss(symbol, percentToClose) {
23411
23741
  backtest$1.loggerService.info(PARTIAL_LOSS_METHOD_NAME, {
23412
23742
  symbol,
23413
23743
  percentToClose,
@@ -23466,7 +23796,7 @@ async function partialLoss(symbol, percentToClose) {
23466
23796
  * // success3 = true (ACCEPTED: newDistance = 10% - 7% = 3%, newSL = 97 > 95, better protection)
23467
23797
  * ```
23468
23798
  */
23469
- async function trailingStop(symbol, percentShift, currentPrice) {
23799
+ async function commitTrailingStop(symbol, percentShift, currentPrice) {
23470
23800
  backtest$1.loggerService.info(TRAILING_STOP_METHOD_NAME, {
23471
23801
  symbol,
23472
23802
  percentShift,
@@ -23525,7 +23855,7 @@ async function trailingStop(symbol, percentShift, currentPrice) {
23525
23855
  * // success3 = true (ACCEPTED: newDistance = 10% - 5% = 5%, newTP = 105 < 107, more conservative)
23526
23856
  * ```
23527
23857
  */
23528
- async function trailingTake(symbol, percentShift, currentPrice) {
23858
+ async function commitTrailingTake(symbol, percentShift, currentPrice) {
23529
23859
  backtest$1.loggerService.info(TRAILING_PROFIT_METHOD_NAME, {
23530
23860
  symbol,
23531
23861
  percentShift,
@@ -23566,7 +23896,7 @@ async function trailingTake(symbol, percentShift, currentPrice) {
23566
23896
  * }
23567
23897
  * ```
23568
23898
  */
23569
- async function breakeven(symbol) {
23899
+ async function commitBreakeven(symbol) {
23570
23900
  backtest$1.loggerService.info(BREAKEVEN_METHOD_NAME, {
23571
23901
  symbol,
23572
23902
  });
@@ -23582,6 +23912,47 @@ async function breakeven(symbol) {
23582
23912
  return await backtest$1.strategyCoreService.breakeven(isBacktest, symbol, currentPrice, { exchangeName, frameName, strategyName });
23583
23913
  }
23584
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
+
23585
23956
  /**
23586
23957
  * Sets custom logger implementation for the framework.
23587
23958
  *
@@ -23732,14 +24103,14 @@ function getDefaultColumns() {
23732
24103
  return DEFAULT_COLUMNS;
23733
24104
  }
23734
24105
 
23735
- const ADD_STRATEGY_METHOD_NAME = "add.addStrategy";
23736
- const ADD_EXCHANGE_METHOD_NAME = "add.addExchange";
23737
- const ADD_FRAME_METHOD_NAME = "add.addFrame";
23738
- const ADD_WALKER_METHOD_NAME = "add.addWalker";
23739
- const ADD_SIZING_METHOD_NAME = "add.addSizing";
23740
- const ADD_RISK_METHOD_NAME = "add.addRisk";
23741
- const ADD_OPTIMIZER_METHOD_NAME = "add.addOptimizer";
23742
- 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";
23743
24114
  /**
23744
24115
  * Registers a trading strategy in the framework.
23745
24116
  *
@@ -23774,7 +24145,7 @@ const ADD_ACTION_METHOD_NAME = "add.addAction";
23774
24145
  * });
23775
24146
  * ```
23776
24147
  */
23777
- function addStrategy(strategySchema) {
24148
+ function addStrategySchema(strategySchema) {
23778
24149
  backtest$1.loggerService.info(ADD_STRATEGY_METHOD_NAME, {
23779
24150
  strategySchema,
23780
24151
  });
@@ -23816,7 +24187,7 @@ function addStrategy(strategySchema) {
23816
24187
  * });
23817
24188
  * ```
23818
24189
  */
23819
- function addExchange(exchangeSchema) {
24190
+ function addExchangeSchema(exchangeSchema) {
23820
24191
  backtest$1.loggerService.info(ADD_EXCHANGE_METHOD_NAME, {
23821
24192
  exchangeSchema,
23822
24193
  });
@@ -23853,7 +24224,7 @@ function addExchange(exchangeSchema) {
23853
24224
  * });
23854
24225
  * ```
23855
24226
  */
23856
- function addFrame(frameSchema) {
24227
+ function addFrameSchema(frameSchema) {
23857
24228
  backtest$1.loggerService.info(ADD_FRAME_METHOD_NAME, {
23858
24229
  frameSchema,
23859
24230
  });
@@ -23897,7 +24268,7 @@ function addFrame(frameSchema) {
23897
24268
  * });
23898
24269
  * ```
23899
24270
  */
23900
- function addWalker(walkerSchema) {
24271
+ function addWalkerSchema(walkerSchema) {
23901
24272
  backtest$1.loggerService.info(ADD_WALKER_METHOD_NAME, {
23902
24273
  walkerSchema,
23903
24274
  });
@@ -23956,7 +24327,7 @@ function addWalker(walkerSchema) {
23956
24327
  * });
23957
24328
  * ```
23958
24329
  */
23959
- function addSizing(sizingSchema) {
24330
+ function addSizingSchema(sizingSchema) {
23960
24331
  backtest$1.loggerService.info(ADD_SIZING_METHOD_NAME, {
23961
24332
  sizingSchema,
23962
24333
  });
@@ -24024,7 +24395,7 @@ function addSizing(sizingSchema) {
24024
24395
  * });
24025
24396
  * ```
24026
24397
  */
24027
- function addRisk(riskSchema) {
24398
+ function addRiskSchema(riskSchema) {
24028
24399
  backtest$1.loggerService.info(ADD_RISK_METHOD_NAME, {
24029
24400
  riskSchema,
24030
24401
  });
@@ -24118,7 +24489,7 @@ function addRisk(riskSchema) {
24118
24489
  * });
24119
24490
  * ```
24120
24491
  */
24121
- function addOptimizer(optimizerSchema) {
24492
+ function addOptimizerSchema(optimizerSchema) {
24122
24493
  backtest$1.loggerService.info(ADD_OPTIMIZER_METHOD_NAME, {
24123
24494
  optimizerSchema,
24124
24495
  });
@@ -24193,7 +24564,7 @@ function addOptimizer(optimizerSchema) {
24193
24564
  * });
24194
24565
  * ```
24195
24566
  */
24196
- function addAction(actionSchema) {
24567
+ function addActionSchema(actionSchema) {
24197
24568
  backtest$1.loggerService.info(ADD_ACTION_METHOD_NAME, {
24198
24569
  actionSchema,
24199
24570
  });
@@ -24201,14 +24572,14 @@ function addAction(actionSchema) {
24201
24572
  backtest$1.actionSchemaService.register(actionSchema.actionName, actionSchema);
24202
24573
  }
24203
24574
 
24204
- const METHOD_NAME_OVERRIDE_STRATEGY = "function.override.overrideStrategy";
24205
- const METHOD_NAME_OVERRIDE_EXCHANGE = "function.override.overrideExchange";
24206
- const METHOD_NAME_OVERRIDE_FRAME = "function.override.overrideFrame";
24207
- const METHOD_NAME_OVERRIDE_WALKER = "function.override.overrideWalker";
24208
- const METHOD_NAME_OVERRIDE_SIZING = "function.override.overrideSizing";
24209
- const METHOD_NAME_OVERRIDE_RISK = "function.override.overrideRisk";
24210
- const METHOD_NAME_OVERRIDE_OPTIMIZER = "function.override.overrideOptimizer";
24211
- 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";
24212
24583
  /**
24213
24584
  * Overrides an existing trading strategy in the framework.
24214
24585
  *
@@ -24229,7 +24600,7 @@ const METHOD_NAME_OVERRIDE_ACTION = "function.override.overrideAction";
24229
24600
  * });
24230
24601
  * ```
24231
24602
  */
24232
- async function overrideStrategy(strategySchema) {
24603
+ async function overrideStrategySchema(strategySchema) {
24233
24604
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_STRATEGY, {
24234
24605
  strategySchema,
24235
24606
  });
@@ -24257,7 +24628,7 @@ async function overrideStrategy(strategySchema) {
24257
24628
  * });
24258
24629
  * ```
24259
24630
  */
24260
- async function overrideExchange(exchangeSchema) {
24631
+ async function overrideExchangeSchema(exchangeSchema) {
24261
24632
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_EXCHANGE, {
24262
24633
  exchangeSchema,
24263
24634
  });
@@ -24285,7 +24656,7 @@ async function overrideExchange(exchangeSchema) {
24285
24656
  * });
24286
24657
  * ```
24287
24658
  */
24288
- async function overrideFrame(frameSchema) {
24659
+ async function overrideFrameSchema(frameSchema) {
24289
24660
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_FRAME, {
24290
24661
  frameSchema,
24291
24662
  });
@@ -24314,7 +24685,7 @@ async function overrideFrame(frameSchema) {
24314
24685
  * });
24315
24686
  * ```
24316
24687
  */
24317
- async function overrideWalker(walkerSchema) {
24688
+ async function overrideWalkerSchema(walkerSchema) {
24318
24689
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_WALKER, {
24319
24690
  walkerSchema,
24320
24691
  });
@@ -24346,7 +24717,7 @@ async function overrideWalker(walkerSchema) {
24346
24717
  * });
24347
24718
  * ```
24348
24719
  */
24349
- async function overrideSizing(sizingSchema) {
24720
+ async function overrideSizingSchema(sizingSchema) {
24350
24721
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_SIZING, {
24351
24722
  sizingSchema,
24352
24723
  });
@@ -24373,7 +24744,7 @@ async function overrideSizing(sizingSchema) {
24373
24744
  * });
24374
24745
  * ```
24375
24746
  */
24376
- async function overrideRisk(riskSchema) {
24747
+ async function overrideRiskSchema(riskSchema) {
24377
24748
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_RISK, {
24378
24749
  riskSchema,
24379
24750
  });
@@ -24407,7 +24778,7 @@ async function overrideRisk(riskSchema) {
24407
24778
  * });
24408
24779
  * ```
24409
24780
  */
24410
- async function overrideOptimizer(optimizerSchema) {
24781
+ async function overrideOptimizerSchema(optimizerSchema) {
24411
24782
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_OPTIMIZER, {
24412
24783
  optimizerSchema,
24413
24784
  });
@@ -24474,7 +24845,7 @@ async function overrideOptimizer(optimizerSchema) {
24474
24845
  * });
24475
24846
  * ```
24476
24847
  */
24477
- async function overrideAction(actionSchema) {
24848
+ async function overrideActionSchema(actionSchema) {
24478
24849
  backtest$1.loggerService.log(METHOD_NAME_OVERRIDE_ACTION, {
24479
24850
  actionSchema,
24480
24851
  });
@@ -24482,13 +24853,13 @@ async function overrideAction(actionSchema) {
24482
24853
  return backtest$1.actionSchemaService.override(actionSchema.actionName, actionSchema);
24483
24854
  }
24484
24855
 
24485
- const LIST_EXCHANGES_METHOD_NAME = "list.listExchanges";
24486
- const LIST_STRATEGIES_METHOD_NAME = "list.listStrategies";
24487
- const LIST_FRAMES_METHOD_NAME = "list.listFrames";
24488
- const LIST_WALKERS_METHOD_NAME = "list.listWalkers";
24489
- const LIST_SIZINGS_METHOD_NAME = "list.listSizings";
24490
- const LIST_RISKS_METHOD_NAME = "list.listRisks";
24491
- 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";
24492
24863
  /**
24493
24864
  * Returns a list of all registered exchange schemas.
24494
24865
  *
@@ -24514,7 +24885,7 @@ const LIST_OPTIMIZERS_METHOD_NAME = "list.listOptimizers";
24514
24885
  * // [{ exchangeName: "binance", note: "Binance cryptocurrency exchange", ... }]
24515
24886
  * ```
24516
24887
  */
24517
- async function listExchanges() {
24888
+ async function listExchangeSchema() {
24518
24889
  backtest$1.loggerService.log(LIST_EXCHANGES_METHOD_NAME);
24519
24890
  return await backtest$1.exchangeValidationService.list();
24520
24891
  }
@@ -24548,7 +24919,7 @@ async function listExchanges() {
24548
24919
  * // [{ strategyName: "my-strategy", note: "Simple moving average...", ... }]
24549
24920
  * ```
24550
24921
  */
24551
- async function listStrategies() {
24922
+ async function listStrategySchema() {
24552
24923
  backtest$1.loggerService.log(LIST_STRATEGIES_METHOD_NAME);
24553
24924
  return await backtest$1.strategyValidationService.list();
24554
24925
  }
@@ -24577,7 +24948,7 @@ async function listStrategies() {
24577
24948
  * // [{ frameName: "1d-backtest", note: "One day backtest...", ... }]
24578
24949
  * ```
24579
24950
  */
24580
- async function listFrames() {
24951
+ async function listFrameSchema() {
24581
24952
  backtest$1.loggerService.log(LIST_FRAMES_METHOD_NAME);
24582
24953
  return await backtest$1.frameValidationService.list();
24583
24954
  }
@@ -24607,7 +24978,7 @@ async function listFrames() {
24607
24978
  * // [{ walkerName: "llm-prompt-optimizer", note: "Compare LLM...", ... }]
24608
24979
  * ```
24609
24980
  */
24610
- async function listWalkers() {
24981
+ async function listWalkerSchema() {
24611
24982
  backtest$1.loggerService.log(LIST_WALKERS_METHOD_NAME);
24612
24983
  return await backtest$1.walkerValidationService.list();
24613
24984
  }
@@ -24646,7 +25017,7 @@ async function listWalkers() {
24646
25017
  * // ]
24647
25018
  * ```
24648
25019
  */
24649
- async function listSizings() {
25020
+ async function listSizingSchema() {
24650
25021
  backtest$1.loggerService.log(LIST_SIZINGS_METHOD_NAME);
24651
25022
  return await backtest$1.sizingValidationService.list();
24652
25023
  }
@@ -24682,7 +25053,7 @@ async function listSizings() {
24682
25053
  * // ]
24683
25054
  * ```
24684
25055
  */
24685
- async function listRisks() {
25056
+ async function listRiskSchema() {
24686
25057
  backtest$1.loggerService.log(LIST_RISKS_METHOD_NAME);
24687
25058
  return await backtest$1.riskValidationService.list();
24688
25059
  }
@@ -24722,7 +25093,7 @@ async function listRisks() {
24722
25093
  * // [{ optimizerName: "llm-strategy-generator", note: "Generates...", ... }]
24723
25094
  * ```
24724
25095
  */
24725
- async function listOptimizers() {
25096
+ async function listOptimizerSchema() {
24726
25097
  backtest$1.loggerService.log(LIST_OPTIMIZERS_METHOD_NAME);
24727
25098
  return await backtest$1.optimizerValidationService.list();
24728
25099
  }
@@ -24757,8 +25128,10 @@ const LISTEN_BREAKEVEN_METHOD_NAME = "event.listenBreakeven";
24757
25128
  const LISTEN_BREAKEVEN_ONCE_METHOD_NAME = "event.listenBreakevenOnce";
24758
25129
  const LISTEN_RISK_METHOD_NAME = "event.listenRisk";
24759
25130
  const LISTEN_RISK_ONCE_METHOD_NAME = "event.listenRiskOnce";
24760
- const LISTEN_PING_METHOD_NAME = "event.listenPing";
24761
- 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";
24762
25135
  /**
24763
25136
  * Subscribes to all signal events with queued async processing.
24764
25137
  *
@@ -25457,7 +25830,7 @@ function listenValidation(fn) {
25457
25830
  * unsubscribe();
25458
25831
  * ```
25459
25832
  */
25460
- function listenPartialProfit(fn) {
25833
+ function listenPartialProfitAvailable(fn) {
25461
25834
  backtest$1.loggerService.log(LISTEN_PARTIAL_PROFIT_METHOD_NAME);
25462
25835
  return partialProfitSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
25463
25836
  }
@@ -25491,7 +25864,7 @@ function listenPartialProfit(fn) {
25491
25864
  * cancel();
25492
25865
  * ```
25493
25866
  */
25494
- function listenPartialProfitOnce(filterFn, fn) {
25867
+ function listenPartialProfitAvailableOnce(filterFn, fn) {
25495
25868
  backtest$1.loggerService.log(LISTEN_PARTIAL_PROFIT_ONCE_METHOD_NAME);
25496
25869
  return partialProfitSubject.filter(filterFn).once(fn);
25497
25870
  }
@@ -25519,7 +25892,7 @@ function listenPartialProfitOnce(filterFn, fn) {
25519
25892
  * unsubscribe();
25520
25893
  * ```
25521
25894
  */
25522
- function listenPartialLoss(fn) {
25895
+ function listenPartialLossAvailable(fn) {
25523
25896
  backtest$1.loggerService.log(LISTEN_PARTIAL_LOSS_METHOD_NAME);
25524
25897
  return partialLossSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
25525
25898
  }
@@ -25553,7 +25926,7 @@ function listenPartialLoss(fn) {
25553
25926
  * cancel();
25554
25927
  * ```
25555
25928
  */
25556
- function listenPartialLossOnce(filterFn, fn) {
25929
+ function listenPartialLossAvailableOnce(filterFn, fn) {
25557
25930
  backtest$1.loggerService.log(LISTEN_PARTIAL_LOSS_ONCE_METHOD_NAME);
25558
25931
  return partialLossSubject.filter(filterFn).once(fn);
25559
25932
  }
@@ -25583,7 +25956,7 @@ function listenPartialLossOnce(filterFn, fn) {
25583
25956
  * unsubscribe();
25584
25957
  * ```
25585
25958
  */
25586
- function listenBreakeven(fn) {
25959
+ function listenBreakevenAvailable(fn) {
25587
25960
  backtest$1.loggerService.log(LISTEN_BREAKEVEN_METHOD_NAME);
25588
25961
  return breakevenSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
25589
25962
  }
@@ -25617,7 +25990,7 @@ function listenBreakeven(fn) {
25617
25990
  * cancel();
25618
25991
  * ```
25619
25992
  */
25620
- function listenBreakevenOnce(filterFn, fn) {
25993
+ function listenBreakevenAvailableOnce(filterFn, fn) {
25621
25994
  backtest$1.loggerService.log(LISTEN_BREAKEVEN_ONCE_METHOD_NAME);
25622
25995
  return breakevenSubject.filter(filterFn).once(fn);
25623
25996
  }
@@ -25713,9 +26086,9 @@ function listenRiskOnce(filterFn, fn) {
25713
26086
  * unsubscribe();
25714
26087
  * ```
25715
26088
  */
25716
- function listenPing(fn) {
25717
- backtest$1.loggerService.log(LISTEN_PING_METHOD_NAME);
25718
- 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)));
25719
26092
  }
25720
26093
  /**
25721
26094
  * Subscribes to filtered ping events with one-time execution.
@@ -25747,9 +26120,74 @@ function listenPing(fn) {
25747
26120
  * cancel();
25748
26121
  * ```
25749
26122
  */
25750
- function listenPingOnce(filterFn, fn) {
25751
- backtest$1.loggerService.log(LISTEN_PING_ONCE_METHOD_NAME);
25752
- 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);
25753
26191
  }
25754
26192
 
25755
26193
  const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
@@ -25819,7 +26257,7 @@ const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
25819
26257
  * // ./dump/strategy/{uuid}/06_llm_output.md (final signal)
25820
26258
  * ```
25821
26259
  */
25822
- async function dumpSignal(signalId, history, signal, outputDir = "./dump/strategy") {
26260
+ async function dumpSignalData(signalId, history, signal, outputDir = "./dump/strategy") {
25823
26261
  backtest$1.loggerService.info(DUMP_SIGNAL_METHOD_NAME, {
25824
26262
  signalId,
25825
26263
  history,
@@ -25839,11 +26277,12 @@ const BACKTEST_METHOD_NAME_GET_STATUS = "BacktestUtils.getStatus";
25839
26277
  const BACKTEST_METHOD_NAME_GET_PENDING_SIGNAL = "BacktestUtils.getPendingSignal";
25840
26278
  const BACKTEST_METHOD_NAME_GET_SCHEDULED_SIGNAL = "BacktestUtils.getScheduledSignal";
25841
26279
  const BACKTEST_METHOD_NAME_GET_BREAKEVEN = "BacktestUtils.getBreakeven";
25842
- const BACKTEST_METHOD_NAME_CANCEL = "BacktestUtils.cancel";
25843
- const BACKTEST_METHOD_NAME_PARTIAL_PROFIT = "BacktestUtils.partialProfit";
25844
- const BACKTEST_METHOD_NAME_PARTIAL_LOSS = "BacktestUtils.partialLoss";
25845
- const BACKTEST_METHOD_NAME_TRAILING_STOP = "BacktestUtils.trailingStop";
25846
- 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";
25847
26286
  const BACKTEST_METHOD_NAME_GET_DATA = "BacktestUtils.getData";
25848
26287
  /**
25849
26288
  * Internal task function that runs backtest and handles completion.
@@ -26367,14 +26806,14 @@ class BacktestUtils {
26367
26806
  * @example
26368
26807
  * ```typescript
26369
26808
  * // Cancel scheduled signal with custom ID
26370
- * await Backtest.cancel("BTCUSDT", "my-strategy", {
26809
+ * await Backtest.commitCancel("BTCUSDT", "my-strategy", {
26371
26810
  * exchangeName: "binance",
26372
26811
  * frameName: "frame1",
26373
26812
  * strategyName: "my-strategy"
26374
26813
  * }, "manual-cancel-001");
26375
26814
  * ```
26376
26815
  */
26377
- this.cancel = async (symbol, context, cancelId) => {
26816
+ this.commitCancel = async (symbol, context, cancelId) => {
26378
26817
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_CANCEL, {
26379
26818
  symbol,
26380
26819
  context,
@@ -26412,7 +26851,7 @@ class BacktestUtils {
26412
26851
  * @example
26413
26852
  * ```typescript
26414
26853
  * // Close 30% of LONG position at profit
26415
- * const success = await Backtest.partialProfit("BTCUSDT", 30, 45000, {
26854
+ * const success = await Backtest.commitPartialProfit("BTCUSDT", 30, 45000, {
26416
26855
  * exchangeName: "binance",
26417
26856
  * frameName: "frame1",
26418
26857
  * strategyName: "my-strategy"
@@ -26422,7 +26861,7 @@ class BacktestUtils {
26422
26861
  * }
26423
26862
  * ```
26424
26863
  */
26425
- this.partialProfit = async (symbol, percentToClose, currentPrice, context) => {
26864
+ this.commitPartialProfit = async (symbol, percentToClose, currentPrice, context) => {
26426
26865
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_PARTIAL_PROFIT, {
26427
26866
  symbol,
26428
26867
  percentToClose,
@@ -26461,7 +26900,7 @@ class BacktestUtils {
26461
26900
  * @example
26462
26901
  * ```typescript
26463
26902
  * // Close 40% of LONG position at loss
26464
- * const success = await Backtest.partialLoss("BTCUSDT", 40, 38000, {
26903
+ * const success = await Backtest.commitPartialLoss("BTCUSDT", 40, 38000, {
26465
26904
  * exchangeName: "binance",
26466
26905
  * frameName: "frame1",
26467
26906
  * strategyName: "my-strategy"
@@ -26471,7 +26910,7 @@ class BacktestUtils {
26471
26910
  * }
26472
26911
  * ```
26473
26912
  */
26474
- this.partialLoss = async (symbol, percentToClose, currentPrice, context) => {
26913
+ this.commitPartialLoss = async (symbol, percentToClose, currentPrice, context) => {
26475
26914
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_PARTIAL_LOSS, {
26476
26915
  symbol,
26477
26916
  percentToClose,
@@ -26519,7 +26958,7 @@ class BacktestUtils {
26519
26958
  * // LONG: entry=100, originalSL=90, distance=10%, currentPrice=102
26520
26959
  *
26521
26960
  * // First call: tighten by 5%
26522
- * await Backtest.trailingStop("BTCUSDT", -5, 102, {
26961
+ * await Backtest.commitTrailingStop("BTCUSDT", -5, 102, {
26523
26962
  * exchangeName: "binance",
26524
26963
  * frameName: "frame1",
26525
26964
  * strategyName: "my-strategy"
@@ -26527,15 +26966,15 @@ class BacktestUtils {
26527
26966
  * // newDistance = 10% - 5% = 5%, newSL = 95
26528
26967
  *
26529
26968
  * // Second call: try weaker protection (smaller percentShift)
26530
- * await Backtest.trailingStop("BTCUSDT", -3, 102, context);
26969
+ * await Backtest.commitTrailingStop("BTCUSDT", -3, 102, context);
26531
26970
  * // SKIPPED: newSL=97 < 95 (worse protection, larger % absorbs smaller)
26532
26971
  *
26533
26972
  * // Third call: stronger protection (larger percentShift)
26534
- * await Backtest.trailingStop("BTCUSDT", -7, 102, context);
26973
+ * await Backtest.commitTrailingStop("BTCUSDT", -7, 102, context);
26535
26974
  * // ACCEPTED: newDistance = 10% - 7% = 3%, newSL = 97 > 95 (better protection)
26536
26975
  * ```
26537
26976
  */
26538
- this.trailingStop = async (symbol, percentShift, currentPrice, context) => {
26977
+ this.commitTrailingStop = async (symbol, percentShift, currentPrice, context) => {
26539
26978
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_TRAILING_STOP, {
26540
26979
  symbol,
26541
26980
  percentShift,
@@ -26583,7 +27022,7 @@ class BacktestUtils {
26583
27022
  * // LONG: entry=100, originalTP=110, distance=10%, currentPrice=102
26584
27023
  *
26585
27024
  * // First call: bring TP closer by 3%
26586
- * await Backtest.trailingTake("BTCUSDT", -3, 102, {
27025
+ * await Backtest.commitTrailingTake("BTCUSDT", -3, 102, {
26587
27026
  * exchangeName: "binance",
26588
27027
  * frameName: "frame1",
26589
27028
  * strategyName: "my-strategy"
@@ -26591,15 +27030,15 @@ class BacktestUtils {
26591
27030
  * // newDistance = 10% - 3% = 7%, newTP = 107
26592
27031
  *
26593
27032
  * // Second call: try to move TP further (less conservative)
26594
- * await Backtest.trailingTake("BTCUSDT", 2, 102, context);
27033
+ * await Backtest.commitTrailingTake("BTCUSDT", 2, 102, context);
26595
27034
  * // SKIPPED: newTP=112 > 107 (less conservative, larger % absorbs smaller)
26596
27035
  *
26597
27036
  * // Third call: even more conservative
26598
- * await Backtest.trailingTake("BTCUSDT", -5, 102, context);
27037
+ * await Backtest.commitTrailingTake("BTCUSDT", -5, 102, context);
26599
27038
  * // ACCEPTED: newDistance = 10% - 5% = 5%, newTP = 105 < 107 (more conservative)
26600
27039
  * ```
26601
27040
  */
26602
- this.trailingTake = async (symbol, percentShift, currentPrice, context) => {
27041
+ this.commitTrailingTake = async (symbol, percentShift, currentPrice, context) => {
26603
27042
  backtest$1.loggerService.info(BACKTEST_METHOD_NAME_TRAILING_PROFIT, {
26604
27043
  symbol,
26605
27044
  percentShift,
@@ -26632,7 +27071,7 @@ class BacktestUtils {
26632
27071
  *
26633
27072
  * @example
26634
27073
  * ```typescript
26635
- * const moved = await Backtest.breakeven(
27074
+ * const moved = await Backtest.commitBreakeven(
26636
27075
  * "BTCUSDT",
26637
27076
  * 112,
26638
27077
  * { strategyName: "my-strategy", exchangeName: "binance", frameName: "1h" }
@@ -26640,22 +27079,22 @@ class BacktestUtils {
26640
27079
  * console.log(moved); // true (SL moved to entry price)
26641
27080
  * ```
26642
27081
  */
26643
- this.breakeven = async (symbol, currentPrice, context) => {
26644
- backtest$1.loggerService.info("Backtest.breakeven", {
27082
+ this.commitBreakeven = async (symbol, currentPrice, context) => {
27083
+ backtest$1.loggerService.info(BACKTEST_METHOD_NAME_BREAKEVEN, {
26645
27084
  symbol,
26646
27085
  currentPrice,
26647
27086
  context,
26648
27087
  });
26649
- backtest$1.strategyValidationService.validate(context.strategyName, "Backtest.breakeven");
26650
- 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);
26651
27090
  {
26652
27091
  const { riskName, riskList, actions } = backtest$1.strategySchemaService.get(context.strategyName);
26653
27092
  riskName &&
26654
- backtest$1.riskValidationService.validate(riskName, "Backtest.breakeven");
27093
+ backtest$1.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BREAKEVEN);
26655
27094
  riskList &&
26656
- riskList.forEach((riskName) => backtest$1.riskValidationService.validate(riskName, "Backtest.breakeven"));
27095
+ riskList.forEach((riskName) => backtest$1.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BREAKEVEN));
26657
27096
  actions &&
26658
- actions.forEach((actionName) => backtest$1.actionValidationService.validate(actionName, "Backtest.breakeven"));
27097
+ actions.forEach((actionName) => backtest$1.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_BREAKEVEN));
26659
27098
  }
26660
27099
  return await backtest$1.strategyCoreService.breakeven(true, symbol, currentPrice, context);
26661
27100
  };
@@ -26827,11 +27266,12 @@ const LIVE_METHOD_NAME_GET_STATUS = "LiveUtils.getStatus";
26827
27266
  const LIVE_METHOD_NAME_GET_PENDING_SIGNAL = "LiveUtils.getPendingSignal";
26828
27267
  const LIVE_METHOD_NAME_GET_SCHEDULED_SIGNAL = "LiveUtils.getScheduledSignal";
26829
27268
  const LIVE_METHOD_NAME_GET_BREAKEVEN = "LiveUtils.getBreakeven";
26830
- const LIVE_METHOD_NAME_CANCEL = "LiveUtils.cancel";
26831
- const LIVE_METHOD_NAME_PARTIAL_PROFIT = "LiveUtils.partialProfit";
26832
- const LIVE_METHOD_NAME_PARTIAL_LOSS = "LiveUtils.partialLoss";
26833
- const LIVE_METHOD_NAME_TRAILING_STOP = "LiveUtils.trailingStop";
26834
- 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";
26835
27275
  /**
26836
27276
  * Internal task function that runs live trading and handles completion.
26837
27277
  * Consumes live trading results and updates instance state flags.
@@ -27321,14 +27761,14 @@ class LiveUtils {
27321
27761
  * @example
27322
27762
  * ```typescript
27323
27763
  * // Cancel scheduled signal in live trading with custom ID
27324
- * await Live.cancel("BTCUSDT", "my-strategy", {
27764
+ * await Live.commitCancel("BTCUSDT", "my-strategy", {
27325
27765
  * exchangeName: "binance",
27326
27766
  * frameName: "",
27327
27767
  * strategyName: "my-strategy"
27328
27768
  * }, "manual-cancel-001");
27329
27769
  * ```
27330
27770
  */
27331
- this.cancel = async (symbol, context, cancelId) => {
27771
+ this.commitCancel = async (symbol, context, cancelId) => {
27332
27772
  backtest$1.loggerService.info(LIVE_METHOD_NAME_CANCEL, {
27333
27773
  symbol,
27334
27774
  context,
@@ -27367,7 +27807,7 @@ class LiveUtils {
27367
27807
  * @example
27368
27808
  * ```typescript
27369
27809
  * // Close 30% of LONG position at profit
27370
- * const success = await Live.partialProfit("BTCUSDT", 30, 45000, {
27810
+ * const success = await Live.commitPartialProfit("BTCUSDT", 30, 45000, {
27371
27811
  * exchangeName: "binance",
27372
27812
  * strategyName: "my-strategy"
27373
27813
  * });
@@ -27376,7 +27816,7 @@ class LiveUtils {
27376
27816
  * }
27377
27817
  * ```
27378
27818
  */
27379
- this.partialProfit = async (symbol, percentToClose, currentPrice, context) => {
27819
+ this.commitPartialProfit = async (symbol, percentToClose, currentPrice, context) => {
27380
27820
  backtest$1.loggerService.info(LIVE_METHOD_NAME_PARTIAL_PROFIT, {
27381
27821
  symbol,
27382
27822
  percentToClose,
@@ -27416,7 +27856,7 @@ class LiveUtils {
27416
27856
  * @example
27417
27857
  * ```typescript
27418
27858
  * // Close 40% of LONG position at loss
27419
- * const success = await Live.partialLoss("BTCUSDT", 40, 38000, {
27859
+ * const success = await Live.commitPartialLoss("BTCUSDT", 40, 38000, {
27420
27860
  * exchangeName: "binance",
27421
27861
  * strategyName: "my-strategy"
27422
27862
  * });
@@ -27425,7 +27865,7 @@ class LiveUtils {
27425
27865
  * }
27426
27866
  * ```
27427
27867
  */
27428
- this.partialLoss = async (symbol, percentToClose, currentPrice, context) => {
27868
+ this.commitPartialLoss = async (symbol, percentToClose, currentPrice, context) => {
27429
27869
  backtest$1.loggerService.info(LIVE_METHOD_NAME_PARTIAL_LOSS, {
27430
27870
  symbol,
27431
27871
  percentToClose,
@@ -27474,22 +27914,22 @@ class LiveUtils {
27474
27914
  * // LONG: entry=100, originalSL=90, distance=10%, currentPrice=102
27475
27915
  *
27476
27916
  * // First call: tighten by 5%
27477
- * const success1 = await Live.trailingStop("BTCUSDT", -5, 102, {
27917
+ * const success1 = await Live.commitTrailingStop("BTCUSDT", -5, 102, {
27478
27918
  * exchangeName: "binance",
27479
27919
  * strategyName: "my-strategy"
27480
27920
  * });
27481
27921
  * // success1 = true, newDistance = 10% - 5% = 5%, newSL = 95
27482
27922
  *
27483
27923
  * // Second call: try weaker protection (smaller percentShift)
27484
- * const success2 = await Live.trailingStop("BTCUSDT", -3, 102, context);
27924
+ * const success2 = await Live.commitTrailingStop("BTCUSDT", -3, 102, context);
27485
27925
  * // success2 = false (SKIPPED: newSL=97 < 95, worse protection, larger % absorbs smaller)
27486
27926
  *
27487
27927
  * // Third call: stronger protection (larger percentShift)
27488
- * const success3 = await Live.trailingStop("BTCUSDT", -7, 102, context);
27928
+ * const success3 = await Live.commitTrailingStop("BTCUSDT", -7, 102, context);
27489
27929
  * // success3 = true (ACCEPTED: newDistance = 10% - 7% = 3%, newSL = 97 > 95, better protection)
27490
27930
  * ```
27491
27931
  */
27492
- this.trailingStop = async (symbol, percentShift, currentPrice, context) => {
27932
+ this.commitTrailingStop = async (symbol, percentShift, currentPrice, context) => {
27493
27933
  backtest$1.loggerService.info(LIVE_METHOD_NAME_TRAILING_STOP, {
27494
27934
  symbol,
27495
27935
  percentShift,
@@ -27538,22 +27978,22 @@ class LiveUtils {
27538
27978
  * // LONG: entry=100, originalTP=110, distance=10%, currentPrice=102
27539
27979
  *
27540
27980
  * // First call: bring TP closer by 3%
27541
- * const success1 = await Live.trailingTake("BTCUSDT", -3, 102, {
27981
+ * const success1 = await Live.commitTrailingTake("BTCUSDT", -3, 102, {
27542
27982
  * exchangeName: "binance",
27543
27983
  * strategyName: "my-strategy"
27544
27984
  * });
27545
27985
  * // success1 = true, newDistance = 10% - 3% = 7%, newTP = 107
27546
27986
  *
27547
27987
  * // Second call: try to move TP further (less conservative)
27548
- * const success2 = await Live.trailingTake("BTCUSDT", 2, 102, context);
27988
+ * const success2 = await Live.commitTrailingTake("BTCUSDT", 2, 102, context);
27549
27989
  * // success2 = false (SKIPPED: newTP=112 > 107, less conservative, larger % absorbs smaller)
27550
27990
  *
27551
27991
  * // Third call: even more conservative
27552
- * const success3 = await Live.trailingTake("BTCUSDT", -5, 102, context);
27992
+ * const success3 = await Live.commitTrailingTake("BTCUSDT", -5, 102, context);
27553
27993
  * // success3 = true (ACCEPTED: newDistance = 10% - 5% = 5%, newTP = 105 < 107, more conservative)
27554
27994
  * ```
27555
27995
  */
27556
- this.trailingTake = async (symbol, percentShift, currentPrice, context) => {
27996
+ this.commitTrailingTake = async (symbol, percentShift, currentPrice, context) => {
27557
27997
  backtest$1.loggerService.info(LIVE_METHOD_NAME_TRAILING_PROFIT, {
27558
27998
  symbol,
27559
27999
  percentShift,
@@ -27587,7 +28027,7 @@ class LiveUtils {
27587
28027
  *
27588
28028
  * @example
27589
28029
  * ```typescript
27590
- * const moved = await Live.breakeven(
28030
+ * const moved = await Live.commitBreakeven(
27591
28031
  * "BTCUSDT",
27592
28032
  * 112,
27593
28033
  * { strategyName: "my-strategy", exchangeName: "binance" }
@@ -27595,19 +28035,19 @@ class LiveUtils {
27595
28035
  * console.log(moved); // true (SL moved to entry price)
27596
28036
  * ```
27597
28037
  */
27598
- this.breakeven = async (symbol, currentPrice, context) => {
27599
- backtest$1.loggerService.info("Live.breakeven", {
28038
+ this.commitBreakeven = async (symbol, currentPrice, context) => {
28039
+ backtest$1.loggerService.info(LIVE_METHOD_NAME_BREAKEVEN, {
27600
28040
  symbol,
27601
28041
  currentPrice,
27602
28042
  context,
27603
28043
  });
27604
- backtest$1.strategyValidationService.validate(context.strategyName, "Live.breakeven");
27605
- 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);
27606
28046
  {
27607
28047
  const { riskName, riskList, actions } = backtest$1.strategySchemaService.get(context.strategyName);
27608
- riskName && backtest$1.riskValidationService.validate(riskName, "Live.breakeven");
27609
- riskList && riskList.forEach((riskName) => backtest$1.riskValidationService.validate(riskName, "Live.breakeven"));
27610
- 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));
27611
28051
  }
27612
28052
  return await backtest$1.strategyCoreService.breakeven(false, symbol, currentPrice, {
27613
28053
  strategyName: context.strategyName,
@@ -29435,10 +29875,15 @@ class ExchangeInstance {
29435
29875
  const whenTimestamp = when.getTime();
29436
29876
  const sinceTimestamp = since.getTime();
29437
29877
  const filteredData = allData.filter((candle) => candle.timestamp >= sinceTimestamp && candle.timestamp <= whenTimestamp);
29438
- if (filteredData.length < limit) {
29439
- 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`);
29440
29882
  }
29441
- return filteredData;
29883
+ if (uniqueData.length < limit) {
29884
+ backtest$1.loggerService.warn(`ExchangeInstance Expected ${limit} candles, got ${uniqueData.length}`);
29885
+ }
29886
+ return uniqueData;
29442
29887
  };
29443
29888
  /**
29444
29889
  * Calculates VWAP (Volume Weighted Average Price) from last N 1m candles.
@@ -30617,10 +31062,11 @@ const METHOD_NAME_INIT = "ActionBase.init";
30617
31062
  const METHOD_NAME_EVENT = "ActionBase.event";
30618
31063
  const METHOD_NAME_SIGNAL_LIVE = "ActionBase.signalLive";
30619
31064
  const METHOD_NAME_SIGNAL_BACKTEST = "ActionBase.signalBacktest";
30620
- const METHOD_NAME_BREAKEVEN = "ActionBase.breakeven";
30621
- const METHOD_NAME_PARTIAL_PROFIT = "ActionBase.partialProfit";
30622
- const METHOD_NAME_PARTIAL_LOSS = "ActionBase.partialLoss";
30623
- 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";
30624
31070
  const METHOD_NAME_RISK_REJECTION = "ActionBase.riskRejection";
30625
31071
  const METHOD_NAME_DISPOSE = "ActionBase.dispose";
30626
31072
  const DEFAULT_SOURCE = "default";
@@ -30651,10 +31097,11 @@ const DEFAULT_SOURCE = "default";
30651
31097
  * - signal() - Called on every tick/candle (all modes)
30652
31098
  * - signalLive() - Called only in live mode
30653
31099
  * - signalBacktest() - Called only in backtest mode
30654
- * - breakeven() - Called when SL moved to entry
30655
- * - partialProfit() - Called on profit milestones (10%, 20%, etc.)
30656
- * - partialLoss() - Called on loss milestones (-10%, -20%, etc.)
30657
- * - 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
30658
31105
  * - riskRejection() - Called when signal rejected by risk management
30659
31106
  *
30660
31107
  * @example
@@ -30695,7 +31142,7 @@ const DEFAULT_SOURCE = "default";
30695
31142
  * }
30696
31143
  *
30697
31144
  * // Register the action
30698
- * addAction({
31145
+ * addActionSchema({
30699
31146
  * actionName: "telegram-notifier",
30700
31147
  * handler: TelegramNotifier
30701
31148
  * });
@@ -30737,11 +31184,13 @@ class ActionBase {
30737
31184
  * @param strategyName - Strategy identifier this action is attached to
30738
31185
  * @param frameName - Timeframe identifier this action is attached to
30739
31186
  * @param actionName - Action identifier
31187
+ * @param backtest - If running in backtest
30740
31188
  */
30741
- constructor(strategyName, frameName, actionName) {
31189
+ constructor(strategyName, frameName, actionName, backtest) {
30742
31190
  this.strategyName = strategyName;
30743
31191
  this.frameName = frameName;
30744
31192
  this.actionName = actionName;
31193
+ this.backtest = backtest;
30745
31194
  }
30746
31195
  /**
30747
31196
  * Initializes the action handler.
@@ -30865,7 +31314,7 @@ class ActionBase {
30865
31314
  * Called once per signal when price moves far enough to cover fees and slippage.
30866
31315
  * Breakeven threshold: (CC_PERCENT_SLIPPAGE + CC_PERCENT_FEE) * 2 + CC_BREAKEVEN_THRESHOLD
30867
31316
  *
30868
- * Triggered by: ActionCoreService.breakeven() via BreakevenConnectionService
31317
+ * Triggered by: ActionCoreService.breakevenAvailable() via BreakevenConnectionService
30869
31318
  * Source: breakevenSubject.next() in CREATE_COMMIT_BREAKEVEN_FN callback
30870
31319
  * Frequency: Once per signal when threshold reached
30871
31320
  *
@@ -30875,7 +31324,7 @@ class ActionBase {
30875
31324
  *
30876
31325
  * @example
30877
31326
  * ```typescript
30878
- * async breakeven(event: BreakevenContract) {
31327
+ * async breakevenAvailable(event: BreakevenContract) {
30879
31328
  * await this.telegram.send(
30880
31329
  * `[${event.strategyName}] Breakeven reached! ` +
30881
31330
  * `Signal: ${event.data.side} @ ${event.currentPrice}`
@@ -30883,8 +31332,8 @@ class ActionBase {
30883
31332
  * }
30884
31333
  * ```
30885
31334
  */
30886
- breakeven(event, source = DEFAULT_SOURCE) {
30887
- backtest$1.loggerService.info(METHOD_NAME_BREAKEVEN, {
31335
+ breakevenAvailable(event, source = DEFAULT_SOURCE) {
31336
+ backtest$1.loggerService.info(METHOD_NAME_BREAKEVEN_AVAILABLE, {
30888
31337
  event,
30889
31338
  source,
30890
31339
  });
@@ -30895,7 +31344,7 @@ class ActionBase {
30895
31344
  * Called once per profit level per signal (deduplicated).
30896
31345
  * Use to track profit milestones and adjust position management.
30897
31346
  *
30898
- * Triggered by: ActionCoreService.partialProfit() via PartialConnectionService
31347
+ * Triggered by: ActionCoreService.partialProfitAvailable() via PartialConnectionService
30899
31348
  * Source: partialProfitSubject.next() in CREATE_COMMIT_PROFIT_FN callback
30900
31349
  * Frequency: Once per profit level per signal
30901
31350
  *
@@ -30905,7 +31354,7 @@ class ActionBase {
30905
31354
  *
30906
31355
  * @example
30907
31356
  * ```typescript
30908
- * async partialProfit(event: PartialProfitContract) {
31357
+ * async partialProfitAvailable(event: PartialProfitContract) {
30909
31358
  * await this.telegram.send(
30910
31359
  * `[${event.strategyName}] Profit ${event.level}% reached! ` +
30911
31360
  * `Current price: ${event.currentPrice}`
@@ -30914,8 +31363,8 @@ class ActionBase {
30914
31363
  * }
30915
31364
  * ```
30916
31365
  */
30917
- partialProfit(event, source = DEFAULT_SOURCE) {
30918
- backtest$1.loggerService.info(METHOD_NAME_PARTIAL_PROFIT, {
31366
+ partialProfitAvailable(event, source = DEFAULT_SOURCE) {
31367
+ backtest$1.loggerService.info(METHOD_NAME_PARTIAL_PROFIT_AVAILABLE, {
30919
31368
  event,
30920
31369
  source,
30921
31370
  });
@@ -30926,7 +31375,7 @@ class ActionBase {
30926
31375
  * Called once per loss level per signal (deduplicated).
30927
31376
  * Use to track loss milestones and implement risk management actions.
30928
31377
  *
30929
- * Triggered by: ActionCoreService.partialLoss() via PartialConnectionService
31378
+ * Triggered by: ActionCoreService.partialLossAvailable() via PartialConnectionService
30930
31379
  * Source: partialLossSubject.next() in CREATE_COMMIT_LOSS_FN callback
30931
31380
  * Frequency: Once per loss level per signal
30932
31381
  *
@@ -30936,7 +31385,7 @@ class ActionBase {
30936
31385
  *
30937
31386
  * @example
30938
31387
  * ```typescript
30939
- * async partialLoss(event: PartialLossContract) {
31388
+ * async partialLossAvailable(event: PartialLossContract) {
30940
31389
  * await this.telegram.send(
30941
31390
  * `[${event.strategyName}] Loss ${event.level}% reached! ` +
30942
31391
  * `Current price: ${event.currentPrice}`
@@ -30945,37 +31394,66 @@ class ActionBase {
30945
31394
  * }
30946
31395
  * ```
30947
31396
  */
30948
- partialLoss(event, source = DEFAULT_SOURCE) {
30949
- backtest$1.loggerService.info(METHOD_NAME_PARTIAL_LOSS, {
31397
+ partialLossAvailable(event, source = DEFAULT_SOURCE) {
31398
+ backtest$1.loggerService.info(METHOD_NAME_PARTIAL_LOSS_AVAILABLE, {
30950
31399
  event,
30951
31400
  source,
30952
31401
  });
30953
31402
  }
30954
31403
  /**
30955
- * Handles ping events during scheduled signal monitoring.
31404
+ * Handles scheduled ping events during scheduled signal monitoring.
30956
31405
  *
30957
31406
  * Called every minute while a scheduled signal is waiting for activation.
30958
31407
  * Use to monitor pending signals and track wait time.
30959
31408
  *
30960
- * Triggered by: ActionCoreService.ping() via StrategyConnectionService
30961
- * 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
30962
31411
  * Frequency: Every minute while scheduled signal is waiting
30963
31412
  *
30964
- * Default implementation: Logs ping event.
31413
+ * Default implementation: Logs scheduled ping event.
30965
31414
  *
30966
31415
  * @param event - Scheduled signal monitoring data with symbol, strategy info, signal data, timestamp
30967
31416
  *
30968
31417
  * @example
30969
31418
  * ```typescript
30970
- * ping(event: PingContract) {
31419
+ * pingScheduled(event: SchedulePingContract) {
30971
31420
  * const waitTime = Date.now() - event.data.timestampScheduled;
30972
31421
  * const waitMinutes = Math.floor(waitTime / 60000);
30973
31422
  * console.log(`Scheduled signal waiting ${waitMinutes} minutes`);
30974
31423
  * }
30975
31424
  * ```
30976
31425
  */
30977
- ping(event, source = DEFAULT_SOURCE) {
30978
- 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, {
30979
31457
  event,
30980
31458
  source,
30981
31459
  });
@@ -31123,51 +31601,59 @@ exports.ReportBase = ReportBase;
31123
31601
  exports.Risk = Risk;
31124
31602
  exports.Schedule = Schedule;
31125
31603
  exports.Walker = Walker;
31126
- exports.addAction = addAction;
31127
- exports.addExchange = addExchange;
31128
- exports.addFrame = addFrame;
31129
- exports.addOptimizer = addOptimizer;
31130
- exports.addRisk = addRisk;
31131
- exports.addSizing = addSizing;
31132
- exports.addStrategy = addStrategy;
31133
- exports.addWalker = addWalker;
31134
- exports.breakeven = breakeven;
31135
- exports.cancel = cancel;
31136
- 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;
31137
31619
  exports.emitters = emitters;
31138
31620
  exports.formatPrice = formatPrice;
31139
31621
  exports.formatQuantity = formatQuantity;
31140
31622
  exports.get = get;
31141
- exports.getAction = getAction;
31623
+ exports.getActionSchema = getActionSchema;
31142
31624
  exports.getAveragePrice = getAveragePrice;
31625
+ exports.getBacktestTimeframe = getBacktestTimeframe;
31143
31626
  exports.getCandles = getCandles;
31144
31627
  exports.getColumns = getColumns;
31145
31628
  exports.getConfig = getConfig;
31146
- exports.getCurrentTimeframe = getCurrentTimeframe;
31629
+ exports.getContext = getContext;
31147
31630
  exports.getDate = getDate;
31148
31631
  exports.getDefaultColumns = getDefaultColumns;
31149
31632
  exports.getDefaultConfig = getDefaultConfig;
31150
- exports.getExchange = getExchange;
31151
- exports.getFrame = getFrame;
31633
+ exports.getExchangeSchema = getExchangeSchema;
31634
+ exports.getFrameSchema = getFrameSchema;
31152
31635
  exports.getMode = getMode;
31153
- exports.getOptimizer = getOptimizer;
31636
+ exports.getOptimizerSchema = getOptimizerSchema;
31154
31637
  exports.getOrderBook = getOrderBook;
31155
- exports.getRisk = getRisk;
31156
- exports.getSizing = getSizing;
31157
- exports.getStrategy = getStrategy;
31158
- exports.getWalker = getWalker;
31638
+ exports.getRiskSchema = getRiskSchema;
31639
+ exports.getSizingSchema = getSizingSchema;
31640
+ exports.getStrategySchema = getStrategySchema;
31641
+ exports.getSymbol = getSymbol;
31642
+ exports.getWalkerSchema = getWalkerSchema;
31159
31643
  exports.hasTradeContext = hasTradeContext;
31160
31644
  exports.lib = backtest;
31161
- exports.listExchanges = listExchanges;
31162
- exports.listFrames = listFrames;
31163
- exports.listOptimizers = listOptimizers;
31164
- exports.listRisks = listRisks;
31165
- exports.listSizings = listSizings;
31166
- exports.listStrategies = listStrategies;
31167
- 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;
31168
31654
  exports.listenBacktestProgress = listenBacktestProgress;
31169
- exports.listenBreakeven = listenBreakeven;
31170
- exports.listenBreakevenOnce = listenBreakevenOnce;
31655
+ exports.listenBreakevenAvailable = listenBreakevenAvailable;
31656
+ exports.listenBreakevenAvailableOnce = listenBreakevenAvailableOnce;
31171
31657
  exports.listenDoneBacktest = listenDoneBacktest;
31172
31658
  exports.listenDoneBacktestOnce = listenDoneBacktestOnce;
31173
31659
  exports.listenDoneLive = listenDoneLive;
@@ -31177,15 +31663,15 @@ exports.listenDoneWalkerOnce = listenDoneWalkerOnce;
31177
31663
  exports.listenError = listenError;
31178
31664
  exports.listenExit = listenExit;
31179
31665
  exports.listenOptimizerProgress = listenOptimizerProgress;
31180
- exports.listenPartialLoss = listenPartialLoss;
31181
- exports.listenPartialLossOnce = listenPartialLossOnce;
31182
- exports.listenPartialProfit = listenPartialProfit;
31183
- exports.listenPartialProfitOnce = listenPartialProfitOnce;
31666
+ exports.listenPartialLossAvailable = listenPartialLossAvailable;
31667
+ exports.listenPartialLossAvailableOnce = listenPartialLossAvailableOnce;
31668
+ exports.listenPartialProfitAvailable = listenPartialProfitAvailable;
31669
+ exports.listenPartialProfitAvailableOnce = listenPartialProfitAvailableOnce;
31184
31670
  exports.listenPerformance = listenPerformance;
31185
- exports.listenPing = listenPing;
31186
- exports.listenPingOnce = listenPingOnce;
31187
31671
  exports.listenRisk = listenRisk;
31188
31672
  exports.listenRiskOnce = listenRiskOnce;
31673
+ exports.listenSchedulePing = listenSchedulePing;
31674
+ exports.listenSchedulePingOnce = listenSchedulePingOnce;
31189
31675
  exports.listenSignal = listenSignal;
31190
31676
  exports.listenSignalBacktest = listenSignalBacktest;
31191
31677
  exports.listenSignalBacktestOnce = listenSignalBacktestOnce;
@@ -31197,22 +31683,18 @@ exports.listenWalker = listenWalker;
31197
31683
  exports.listenWalkerComplete = listenWalkerComplete;
31198
31684
  exports.listenWalkerOnce = listenWalkerOnce;
31199
31685
  exports.listenWalkerProgress = listenWalkerProgress;
31200
- exports.overrideAction = overrideAction;
31201
- exports.overrideExchange = overrideExchange;
31202
- exports.overrideFrame = overrideFrame;
31203
- exports.overrideOptimizer = overrideOptimizer;
31204
- exports.overrideRisk = overrideRisk;
31205
- exports.overrideSizing = overrideSizing;
31206
- exports.overrideStrategy = overrideStrategy;
31207
- exports.overrideWalker = overrideWalker;
31208
- exports.partialLoss = partialLoss;
31209
- 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;
31210
31694
  exports.roundTicks = roundTicks;
31211
31695
  exports.set = set;
31212
31696
  exports.setColumns = setColumns;
31213
31697
  exports.setConfig = setConfig;
31214
31698
  exports.setLogger = setLogger;
31215
31699
  exports.stop = stop;
31216
- exports.trailingStop = trailingStop;
31217
- exports.trailingTake = trailingTake;
31218
31700
  exports.validate = validate;