backtest-kit 2.0.12 → 2.1.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.mjs CHANGED
@@ -4389,6 +4389,7 @@ class ClientStrategy {
4389
4389
  this._lastSignalTimestamp = null;
4390
4390
  this._scheduledSignal = null;
4391
4391
  this._cancelledSignal = null;
4392
+ this._closedSignal = null;
4392
4393
  /**
4393
4394
  * Initializes strategy state by loading persisted signal from disk.
4394
4395
  *
@@ -4665,6 +4666,41 @@ class ClientStrategy {
4665
4666
  reason: "user",
4666
4667
  cancelId: cancelledSignal.cancelId,
4667
4668
  };
4669
+ await CALL_TICK_CALLBACKS_FN(this, this.params.execution.context.symbol, result, currentTime, this.params.execution.context.backtest);
4670
+ return result;
4671
+ }
4672
+ // Check if pending signal was closed - emit closed event once
4673
+ if (this._closedSignal) {
4674
+ const currentPrice = await this.params.exchange.getAveragePrice(this.params.execution.context.symbol);
4675
+ const closedSignal = this._closedSignal;
4676
+ this._closedSignal = null; // Clear after emitting
4677
+ this.params.logger.info("ClientStrategy tick: pending signal was closed", {
4678
+ symbol: this.params.execution.context.symbol,
4679
+ signalId: closedSignal.id,
4680
+ });
4681
+ // Call onClose callback
4682
+ await CALL_CLOSE_CALLBACKS_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, currentTime, this.params.execution.context.backtest);
4683
+ // КРИТИЧНО: Очищаем состояние ClientPartial при закрытии позиции
4684
+ await CALL_PARTIAL_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, currentTime, this.params.execution.context.backtest);
4685
+ // КРИТИЧНО: Очищаем состояние ClientBreakeven при закрытии позиции
4686
+ await CALL_BREAKEVEN_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, currentTime, this.params.execution.context.backtest);
4687
+ await CALL_RISK_REMOVE_SIGNAL_FN(this, this.params.execution.context.symbol, currentTime, this.params.execution.context.backtest);
4688
+ const pnl = toProfitLossDto(closedSignal, currentPrice);
4689
+ const result = {
4690
+ action: "closed",
4691
+ signal: TO_PUBLIC_SIGNAL(closedSignal),
4692
+ currentPrice,
4693
+ closeReason: "closed",
4694
+ closeTimestamp: currentTime,
4695
+ pnl,
4696
+ strategyName: this.params.method.context.strategyName,
4697
+ exchangeName: this.params.method.context.exchangeName,
4698
+ frameName: this.params.method.context.frameName,
4699
+ symbol: this.params.execution.context.symbol,
4700
+ backtest: this.params.execution.context.backtest,
4701
+ closeId: closedSignal.closeId,
4702
+ };
4703
+ await CALL_TICK_CALLBACKS_FN(this, this.params.execution.context.symbol, result, currentTime, this.params.execution.context.backtest);
4668
4704
  return result;
4669
4705
  }
4670
4706
  // Monitor scheduled signal
@@ -4778,8 +4814,40 @@ class ClientStrategy {
4778
4814
  reason: "user",
4779
4815
  cancelId: cancelledSignal.cancelId,
4780
4816
  };
4817
+ await CALL_TICK_CALLBACKS_FN(this, this.params.execution.context.symbol, cancelledResult, closeTimestamp, this.params.execution.context.backtest);
4781
4818
  return cancelledResult;
4782
4819
  }
4820
+ // If signal was closed - return closed
4821
+ if (this._closedSignal) {
4822
+ this.params.logger.debug("ClientStrategy backtest: pending signal was closed");
4823
+ const currentPrice = await this.params.exchange.getAveragePrice(symbol);
4824
+ const closedSignal = this._closedSignal;
4825
+ this._closedSignal = null; // Clear after using
4826
+ const closeTimestamp = this.params.execution.context.when.getTime();
4827
+ await CALL_CLOSE_CALLBACKS_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, closeTimestamp, this.params.execution.context.backtest);
4828
+ // КРИТИЧНО: Очищаем состояние ClientPartial при закрытии позиции
4829
+ await CALL_PARTIAL_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, closeTimestamp, this.params.execution.context.backtest);
4830
+ // КРИТИЧНО: Очищаем состояние ClientBreakeven при закрытии позиции
4831
+ await CALL_BREAKEVEN_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, closeTimestamp, this.params.execution.context.backtest);
4832
+ await CALL_RISK_REMOVE_SIGNAL_FN(this, this.params.execution.context.symbol, closeTimestamp, this.params.execution.context.backtest);
4833
+ const pnl = toProfitLossDto(closedSignal, currentPrice);
4834
+ const closedResult = {
4835
+ action: "closed",
4836
+ signal: TO_PUBLIC_SIGNAL(closedSignal),
4837
+ currentPrice,
4838
+ closeReason: "closed",
4839
+ closeTimestamp: closeTimestamp,
4840
+ pnl,
4841
+ strategyName: this.params.method.context.strategyName,
4842
+ exchangeName: this.params.method.context.exchangeName,
4843
+ frameName: this.params.method.context.frameName,
4844
+ symbol: this.params.execution.context.symbol,
4845
+ backtest: true,
4846
+ closeId: closedSignal.closeId,
4847
+ };
4848
+ await CALL_TICK_CALLBACKS_FN(this, this.params.execution.context.symbol, closedResult, closeTimestamp, this.params.execution.context.backtest);
4849
+ return closedResult;
4850
+ }
4783
4851
  if (!this._pendingSignal && !this._scheduledSignal) {
4784
4852
  throw new Error("ClientStrategy backtest: no pending or scheduled signal");
4785
4853
  }
@@ -4906,12 +4974,12 @@ class ClientStrategy {
4906
4974
  * @example
4907
4975
  * ```typescript
4908
4976
  * // In Live.background() cancellation
4909
- * await strategy.stop();
4977
+ * await strategy.stopStrategy();
4910
4978
  * // Existing signal will continue until natural close
4911
4979
  * ```
4912
4980
  */
4913
- async stop(symbol, backtest) {
4914
- this.params.logger.debug("ClientStrategy stop", {
4981
+ async stopStrategy(symbol, backtest) {
4982
+ this.params.logger.debug("ClientStrategy stopStrategy", {
4915
4983
  symbol,
4916
4984
  hasPendingSignal: this._pendingSignal !== null,
4917
4985
  hasScheduledSignal: this._scheduledSignal !== null,
@@ -4944,12 +5012,12 @@ class ClientStrategy {
4944
5012
  * @example
4945
5013
  * ```typescript
4946
5014
  * // Cancel scheduled signal without stopping strategy
4947
- * await strategy.cancel("BTCUSDT", "my-strategy", false);
5015
+ * await strategy.cancelScheduled("BTCUSDT", "my-strategy", false);
4948
5016
  * // Strategy continues, can generate new signals
4949
5017
  * ```
4950
5018
  */
4951
- async cancel(symbol, backtest, cancelId) {
4952
- this.params.logger.debug("ClientStrategy cancel", {
5019
+ async cancelScheduled(symbol, backtest, cancelId) {
5020
+ this.params.logger.debug("ClientStrategy cancelScheduled", {
4953
5021
  symbol,
4954
5022
  hasScheduledSignal: this._scheduledSignal !== null,
4955
5023
  cancelId,
@@ -4966,6 +5034,45 @@ class ClientStrategy {
4966
5034
  }
4967
5035
  await PersistScheduleAdapter.writeScheduleData(this._scheduledSignal, symbol, this.params.method.context.strategyName, this.params.method.context.exchangeName);
4968
5036
  }
5037
+ /**
5038
+ * Closes the pending signal without stopping the strategy.
5039
+ *
5040
+ * Clears the pending signal (active position).
5041
+ * Does NOT affect scheduled signals or strategy operation.
5042
+ * Does NOT set stop flag - strategy can continue generating new signals.
5043
+ *
5044
+ * Use case: Close an active position that is no longer desired without stopping the entire strategy.
5045
+ *
5046
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
5047
+ * @param backtest - Whether running in backtest mode
5048
+ * @param closeId - Optional identifier for this close operation
5049
+ * @returns Promise that resolves when pending signal is cleared
5050
+ *
5051
+ * @example
5052
+ * ```typescript
5053
+ * // Close pending signal without stopping strategy
5054
+ * await strategy.closePending("BTCUSDT", false, "user-close-123");
5055
+ * // Strategy continues, can generate new signals
5056
+ * ```
5057
+ */
5058
+ async closePending(symbol, backtest, closeId) {
5059
+ this.params.logger.debug("ClientStrategy closePending", {
5060
+ symbol,
5061
+ hasPendingSignal: this._pendingSignal !== null,
5062
+ closeId,
5063
+ });
5064
+ // Save closed signal for next tick to emit closed event
5065
+ if (this._pendingSignal) {
5066
+ this._closedSignal = Object.assign({}, this._pendingSignal, {
5067
+ closeId,
5068
+ });
5069
+ this._pendingSignal = null;
5070
+ }
5071
+ if (backtest) {
5072
+ return;
5073
+ }
5074
+ await PersistSignalAdapter.writeSignalData(this._pendingSignal, symbol, this.params.strategyName, this.params.exchangeName);
5075
+ }
4969
5076
  /**
4970
5077
  * Executes partial close at profit level (moving toward TP).
4971
5078
  *
@@ -6418,7 +6525,7 @@ class StrategyConnectionService {
6418
6525
  /**
6419
6526
  * Stops the specified strategy from generating new signals.
6420
6527
  *
6421
- * Delegates to ClientStrategy.stop() which sets internal flag to prevent
6528
+ * Delegates to ClientStrategy.stopStrategy() which sets internal flag to prevent
6422
6529
  * getSignal from being called on subsequent ticks.
6423
6530
  *
6424
6531
  * @param backtest - Whether running in backtest mode
@@ -6426,13 +6533,13 @@ class StrategyConnectionService {
6426
6533
  * @param ctx - Context with strategyName, exchangeName, frameName
6427
6534
  * @returns Promise that resolves when stop flag is set
6428
6535
  */
6429
- this.stop = async (backtest, symbol, context) => {
6430
- this.loggerService.log("strategyConnectionService stop", {
6536
+ this.stopStrategy = async (backtest, symbol, context) => {
6537
+ this.loggerService.log("strategyConnectionService stopStrategy", {
6431
6538
  symbol,
6432
6539
  context,
6433
6540
  });
6434
6541
  const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
6435
- await strategy.stop(symbol, backtest);
6542
+ await strategy.stopStrategy(symbol, backtest);
6436
6543
  };
6437
6544
  /**
6438
6545
  * Disposes the ClientStrategy instance for the given context.
@@ -6484,7 +6591,7 @@ class StrategyConnectionService {
6484
6591
  /**
6485
6592
  * Cancels the scheduled signal for the specified strategy.
6486
6593
  *
6487
- * Delegates to ClientStrategy.cancel() which clears the scheduled signal
6594
+ * Delegates to ClientStrategy.cancelScheduled() which clears the scheduled signal
6488
6595
  * without stopping the strategy or affecting pending signals.
6489
6596
  *
6490
6597
  * Note: Cancelled event will be emitted on next tick() call when strategy
@@ -6496,14 +6603,39 @@ class StrategyConnectionService {
6496
6603
  * @param cancelId - Optional cancellation ID for user-initiated cancellations
6497
6604
  * @returns Promise that resolves when scheduled signal is cancelled
6498
6605
  */
6499
- this.cancel = async (backtest, symbol, context, cancelId) => {
6500
- this.loggerService.log("strategyConnectionService cancel", {
6606
+ this.cancelScheduled = async (backtest, symbol, context, cancelId) => {
6607
+ this.loggerService.log("strategyConnectionService cancelScheduled", {
6501
6608
  symbol,
6502
6609
  context,
6503
6610
  cancelId,
6504
6611
  });
6505
6612
  const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
6506
- await strategy.cancel(symbol, backtest, cancelId);
6613
+ await strategy.cancelScheduled(symbol, backtest, cancelId);
6614
+ };
6615
+ /**
6616
+ * Closes the pending signal without stopping the strategy.
6617
+ *
6618
+ * Clears the pending signal (active position).
6619
+ * Does NOT affect scheduled signals or strategy operation.
6620
+ * Does NOT set stop flag - strategy can continue generating new signals.
6621
+ *
6622
+ * Note: Closed event will be emitted on next tick() call when strategy
6623
+ * detects the pending signal was closed.
6624
+ *
6625
+ * @param backtest - Whether running in backtest mode
6626
+ * @param symbol - Trading pair symbol
6627
+ * @param context - Context with strategyName, exchangeName, frameName
6628
+ * @param closeId - Optional close ID for user-initiated closes
6629
+ * @returns Promise that resolves when pending signal is closed
6630
+ */
6631
+ this.closePending = async (backtest, symbol, context, closeId) => {
6632
+ this.loggerService.log("strategyConnectionService closePending", {
6633
+ symbol,
6634
+ context,
6635
+ closeId,
6636
+ });
6637
+ const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
6638
+ await strategy.closePending(symbol, backtest, closeId);
6507
6639
  };
6508
6640
  /**
6509
6641
  * Executes partial close at profit level (moving toward TP).
@@ -9690,19 +9822,19 @@ class StrategyCoreService {
9690
9822
  * @param ctx - Context with strategyName, exchangeName, frameName
9691
9823
  * @returns Promise that resolves when stop flag is set
9692
9824
  */
9693
- this.stop = async (backtest, symbol, context) => {
9694
- this.loggerService.log("strategyCoreService stop", {
9825
+ this.stopStrategy = async (backtest, symbol, context) => {
9826
+ this.loggerService.log("strategyCoreService stopStrategy", {
9695
9827
  symbol,
9696
9828
  context,
9697
9829
  backtest,
9698
9830
  });
9699
9831
  await this.validate(context);
9700
- return await this.strategyConnectionService.stop(backtest, symbol, context);
9832
+ return await this.strategyConnectionService.stopStrategy(backtest, symbol, context);
9701
9833
  };
9702
9834
  /**
9703
9835
  * Cancels the scheduled signal without stopping the strategy.
9704
9836
  *
9705
- * Delegates to StrategyConnectionService.cancel() to clear scheduled signal
9837
+ * Delegates to StrategyConnectionService.cancelScheduled() to clear scheduled signal
9706
9838
  * and emit cancelled event through emitters.
9707
9839
  * Does not require execution context.
9708
9840
  *
@@ -9712,15 +9844,42 @@ class StrategyCoreService {
9712
9844
  * @param cancelId - Optional cancellation ID for user-initiated cancellations
9713
9845
  * @returns Promise that resolves when scheduled signal is cancelled
9714
9846
  */
9715
- this.cancel = async (backtest, symbol, context, cancelId) => {
9716
- this.loggerService.log("strategyCoreService cancel", {
9847
+ this.cancelScheduled = async (backtest, symbol, context, cancelId) => {
9848
+ this.loggerService.log("strategyCoreService cancelScheduled", {
9717
9849
  symbol,
9718
9850
  context,
9719
9851
  backtest,
9720
9852
  cancelId,
9721
9853
  });
9722
9854
  await this.validate(context);
9723
- return await this.strategyConnectionService.cancel(backtest, symbol, context, cancelId);
9855
+ return await this.strategyConnectionService.cancelScheduled(backtest, symbol, context, cancelId);
9856
+ };
9857
+ /**
9858
+ * Closes the pending signal without stopping the strategy.
9859
+ *
9860
+ * Clears the pending signal (active position).
9861
+ * Does NOT affect scheduled signals or strategy operation.
9862
+ * Does NOT set stop flag - strategy can continue generating new signals.
9863
+ *
9864
+ * Delegates to StrategyConnectionService.closePending() to clear pending signal
9865
+ * and emit closed event through emitters.
9866
+ * Does not require execution context.
9867
+ *
9868
+ * @param backtest - Whether running in backtest mode
9869
+ * @param symbol - Trading pair symbol
9870
+ * @param context - Context with strategyName, exchangeName, frameName
9871
+ * @param closeId - Optional close ID for user-initiated closes
9872
+ * @returns Promise that resolves when pending signal is closed
9873
+ */
9874
+ this.closePending = async (backtest, symbol, context, closeId) => {
9875
+ this.loggerService.log("strategyCoreService closePending", {
9876
+ symbol,
9877
+ context,
9878
+ backtest,
9879
+ closeId,
9880
+ });
9881
+ await this.validate(context);
9882
+ return await this.strategyConnectionService.closePending(backtest, symbol, context, closeId);
9724
9883
  };
9725
9884
  /**
9726
9885
  * Disposes the ClientStrategy instance for the given context.
@@ -25006,7 +25165,8 @@ async function getOrderBook(symbol, depth) {
25006
25165
  return await bt.exchangeConnectionService.getOrderBook(symbol, depth);
25007
25166
  }
25008
25167
 
25009
- const CANCEL_METHOD_NAME = "strategy.commitCancel";
25168
+ const CANCEL_SCHEDULED_METHOD_NAME = "strategy.commitCancelScheduled";
25169
+ const CLOSE_PENDING_METHOD_NAME = "strategy.commitClosePending";
25010
25170
  const PARTIAL_PROFIT_METHOD_NAME = "strategy.commitPartialProfit";
25011
25171
  const PARTIAL_LOSS_METHOD_NAME = "strategy.commitPartialLoss";
25012
25172
  const TRAILING_STOP_METHOD_NAME = "strategy.commitTrailingStop";
@@ -25028,26 +25188,62 @@ const BREAKEVEN_METHOD_NAME = "strategy.commitBreakeven";
25028
25188
  *
25029
25189
  * @example
25030
25190
  * ```typescript
25031
- * import { cancel } from "backtest-kit";
25191
+ * import { commitCancelScheduled } from "backtest-kit";
25032
25192
  *
25033
25193
  * // Cancel scheduled signal with custom ID
25034
- * await cancel("BTCUSDT", "my-strategy", "manual-cancel-001");
25194
+ * await commitCancelScheduled("BTCUSDT", "manual-cancel-001");
25035
25195
  * ```
25036
25196
  */
25037
- async function commitCancel(symbol, cancelId) {
25038
- bt.loggerService.info(CANCEL_METHOD_NAME, {
25197
+ async function commitCancelScheduled(symbol, cancelId) {
25198
+ bt.loggerService.info(CANCEL_SCHEDULED_METHOD_NAME, {
25039
25199
  symbol,
25040
25200
  cancelId,
25041
25201
  });
25042
25202
  if (!ExecutionContextService.hasContext()) {
25043
- throw new Error("cancel requires an execution context");
25203
+ throw new Error("commitCancelScheduled requires an execution context");
25204
+ }
25205
+ if (!MethodContextService.hasContext()) {
25206
+ throw new Error("commitCancelScheduled requires a method context");
25207
+ }
25208
+ const { backtest: isBacktest } = bt.executionContextService.context;
25209
+ const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
25210
+ await bt.strategyCoreService.cancelScheduled(isBacktest, symbol, { exchangeName, frameName, strategyName }, cancelId);
25211
+ }
25212
+ /**
25213
+ * Closes the pending signal without stopping the strategy.
25214
+ *
25215
+ * Clears the pending signal (active position).
25216
+ * Does NOT affect scheduled signals or strategy operation.
25217
+ * Does NOT set stop flag - strategy can continue generating new signals.
25218
+ *
25219
+ * Automatically detects backtest/live mode from execution context.
25220
+ *
25221
+ * @param symbol - Trading pair symbol
25222
+ * @param closeId - Optional close ID for tracking user-initiated closes
25223
+ * @returns Promise that resolves when pending signal is closed
25224
+ *
25225
+ * @example
25226
+ * ```typescript
25227
+ * import { commitClosePending } from "backtest-kit";
25228
+ *
25229
+ * // Close pending signal with custom ID
25230
+ * await commitClosePending("BTCUSDT", "manual-close-001");
25231
+ * ```
25232
+ */
25233
+ async function commitClosePending(symbol, closeId) {
25234
+ bt.loggerService.info(CLOSE_PENDING_METHOD_NAME, {
25235
+ symbol,
25236
+ closeId,
25237
+ });
25238
+ if (!ExecutionContextService.hasContext()) {
25239
+ throw new Error("commitClosePending requires an execution context");
25044
25240
  }
25045
25241
  if (!MethodContextService.hasContext()) {
25046
- throw new Error("cancel requires a method context");
25242
+ throw new Error("commitClosePending requires a method context");
25047
25243
  }
25048
25244
  const { backtest: isBacktest } = bt.executionContextService.context;
25049
25245
  const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
25050
- await bt.strategyCoreService.cancel(isBacktest, symbol, { exchangeName, frameName, strategyName }, cancelId);
25246
+ await bt.strategyCoreService.closePending(isBacktest, symbol, { exchangeName, frameName, strategyName }, closeId);
25051
25247
  }
25052
25248
  /**
25053
25249
  * Executes partial close at profit level (moving toward TP).
@@ -25294,7 +25490,7 @@ async function commitBreakeven(symbol) {
25294
25490
  return await bt.strategyCoreService.breakeven(isBacktest, symbol, currentPrice, { exchangeName, frameName, strategyName });
25295
25491
  }
25296
25492
 
25297
- const STOP_METHOD_NAME = "control.stop";
25493
+ const STOP_STRATEGY_METHOD_NAME = "control.stopStrategy";
25298
25494
  /**
25299
25495
  * Stops the strategy from generating new signals.
25300
25496
  *
@@ -25316,8 +25512,8 @@ const STOP_METHOD_NAME = "control.stop";
25316
25512
  * await stop("BTCUSDT", "my-strategy");
25317
25513
  * ```
25318
25514
  */
25319
- async function stop(symbol) {
25320
- bt.loggerService.info(STOP_METHOD_NAME, {
25515
+ async function stopStrategy(symbol) {
25516
+ bt.loggerService.info(STOP_STRATEGY_METHOD_NAME, {
25321
25517
  symbol,
25322
25518
  });
25323
25519
  if (!ExecutionContextService.hasContext()) {
@@ -25328,7 +25524,7 @@ async function stop(symbol) {
25328
25524
  }
25329
25525
  const { backtest: isBacktest } = bt.executionContextService.context;
25330
25526
  const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
25331
- await bt.strategyCoreService.stop(isBacktest, symbol, {
25527
+ await bt.strategyCoreService.stopStrategy(isBacktest, symbol, {
25332
25528
  exchangeName,
25333
25529
  frameName,
25334
25530
  strategyName,
@@ -27715,7 +27911,8 @@ const BACKTEST_METHOD_NAME_GET_PENDING_SIGNAL = "BacktestUtils.getPendingSignal"
27715
27911
  const BACKTEST_METHOD_NAME_GET_SCHEDULED_SIGNAL = "BacktestUtils.getScheduledSignal";
27716
27912
  const BACKTEST_METHOD_NAME_GET_BREAKEVEN = "BacktestUtils.getBreakeven";
27717
27913
  const BACKTEST_METHOD_NAME_BREAKEVEN = "Backtest.commitBreakeven";
27718
- const BACKTEST_METHOD_NAME_CANCEL = "BacktestUtils.commitCancel";
27914
+ const BACKTEST_METHOD_NAME_CANCEL_SCHEDULED = "Backtest.commitCancelScheduled";
27915
+ const BACKTEST_METHOD_NAME_CLOSE_PENDING = "Backtest.commitClosePending";
27719
27916
  const BACKTEST_METHOD_NAME_PARTIAL_PROFIT = "BacktestUtils.commitPartialProfit";
27720
27917
  const BACKTEST_METHOD_NAME_PARTIAL_LOSS = "BacktestUtils.commitPartialLoss";
27721
27918
  const BACKTEST_METHOD_NAME_TRAILING_STOP = "BacktestUtils.commitTrailingStop";
@@ -27957,7 +28154,7 @@ class BacktestInstance {
27957
28154
  }
27958
28155
  this.task(symbol, context).catch((error) => exitEmitter.next(new Error(getErrorMessage(error))));
27959
28156
  return () => {
27960
- bt.strategyCoreService.stop(true, symbol, {
28157
+ bt.strategyCoreService.stopStrategy(true, symbol, {
27961
28158
  strategyName: context.strategyName,
27962
28159
  exchangeName: context.exchangeName,
27963
28160
  frameName: context.frameName,
@@ -28225,7 +28422,7 @@ class BacktestUtils {
28225
28422
  actions &&
28226
28423
  actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_STOP));
28227
28424
  }
28228
- await bt.strategyCoreService.stop(true, symbol, context);
28425
+ await bt.strategyCoreService.stopStrategy(true, symbol, context);
28229
28426
  };
28230
28427
  /**
28231
28428
  * Cancels the scheduled signal without stopping the strategy.
@@ -28250,24 +28447,65 @@ class BacktestUtils {
28250
28447
  * }, "manual-cancel-001");
28251
28448
  * ```
28252
28449
  */
28253
- this.commitCancel = async (symbol, context, cancelId) => {
28254
- bt.loggerService.info(BACKTEST_METHOD_NAME_CANCEL, {
28450
+ this.commitCancelScheduled = async (symbol, context, cancelId) => {
28451
+ bt.loggerService.info(BACKTEST_METHOD_NAME_CANCEL_SCHEDULED, {
28255
28452
  symbol,
28256
28453
  context,
28257
28454
  cancelId,
28258
28455
  });
28259
- bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_CANCEL);
28260
- bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_CANCEL);
28456
+ bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED);
28457
+ bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED);
28261
28458
  {
28262
28459
  const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
28263
28460
  riskName &&
28264
- bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CANCEL);
28461
+ bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED);
28265
28462
  riskList &&
28266
- riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CANCEL));
28463
+ riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED));
28267
28464
  actions &&
28268
- actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_CANCEL));
28465
+ actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED));
28269
28466
  }
28270
- await bt.strategyCoreService.cancel(true, symbol, context, cancelId);
28467
+ await bt.strategyCoreService.cancelScheduled(true, symbol, context, cancelId);
28468
+ };
28469
+ /**
28470
+ * Closes the pending signal without stopping the strategy.
28471
+ *
28472
+ * Clears the pending signal (active position).
28473
+ * Does NOT affect scheduled signals or strategy operation.
28474
+ * Does NOT set stop flag - strategy can continue generating new signals.
28475
+ *
28476
+ * @param symbol - Trading pair symbol
28477
+ * @param context - Execution context with strategyName, exchangeName, and frameName
28478
+ * @param closeId - Optional close ID for user-initiated closes
28479
+ * @returns Promise that resolves when pending signal is closed
28480
+ *
28481
+ * @example
28482
+ * ```typescript
28483
+ * // Close pending signal with custom ID
28484
+ * await Backtest.commitClose("BTCUSDT", {
28485
+ * exchangeName: "binance",
28486
+ * strategyName: "my-strategy",
28487
+ * frameName: "1m"
28488
+ * }, "manual-close-001");
28489
+ * ```
28490
+ */
28491
+ this.commitClosePending = async (symbol, context, closeId) => {
28492
+ bt.loggerService.info(BACKTEST_METHOD_NAME_CLOSE_PENDING, {
28493
+ symbol,
28494
+ context,
28495
+ closeId,
28496
+ });
28497
+ bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_CLOSE_PENDING);
28498
+ bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_CLOSE_PENDING);
28499
+ {
28500
+ const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
28501
+ riskName &&
28502
+ bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CLOSE_PENDING);
28503
+ riskList &&
28504
+ riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CLOSE_PENDING));
28505
+ actions &&
28506
+ actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_CLOSE_PENDING));
28507
+ }
28508
+ await bt.strategyCoreService.closePending(true, symbol, context, closeId);
28271
28509
  };
28272
28510
  /**
28273
28511
  * Executes partial close at profit level (moving toward TP).
@@ -28704,7 +28942,8 @@ const LIVE_METHOD_NAME_GET_PENDING_SIGNAL = "LiveUtils.getPendingSignal";
28704
28942
  const LIVE_METHOD_NAME_GET_SCHEDULED_SIGNAL = "LiveUtils.getScheduledSignal";
28705
28943
  const LIVE_METHOD_NAME_GET_BREAKEVEN = "LiveUtils.getBreakeven";
28706
28944
  const LIVE_METHOD_NAME_BREAKEVEN = "Live.commitBreakeven";
28707
- const LIVE_METHOD_NAME_CANCEL = "LiveUtils.commitCancel";
28945
+ const LIVE_METHOD_NAME_CANCEL_SCHEDULED = "Live.cancelScheduled";
28946
+ const LIVE_METHOD_NAME_CLOSE_PENDING = "Live.closePending";
28708
28947
  const LIVE_METHOD_NAME_PARTIAL_PROFIT = "LiveUtils.commitPartialProfit";
28709
28948
  const LIVE_METHOD_NAME_PARTIAL_LOSS = "LiveUtils.commitPartialLoss";
28710
28949
  const LIVE_METHOD_NAME_TRAILING_STOP = "LiveUtils.commitTrailingStop";
@@ -28909,7 +29148,7 @@ class LiveInstance {
28909
29148
  }
28910
29149
  this.task(symbol, context).catch((error) => exitEmitter.next(new Error(getErrorMessage(error))));
28911
29150
  return () => {
28912
- bt.strategyCoreService.stop(false, symbol, {
29151
+ bt.strategyCoreService.stopStrategy(false, symbol, {
28913
29152
  strategyName: context.strategyName,
28914
29153
  exchangeName: context.exchangeName,
28915
29154
  frameName: ""
@@ -29176,7 +29415,7 @@ class LiveUtils {
29176
29415
  riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_STOP));
29177
29416
  actions && actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_STOP));
29178
29417
  }
29179
- await bt.strategyCoreService.stop(false, symbol, {
29418
+ await bt.strategyCoreService.stopStrategy(false, symbol, {
29180
29419
  strategyName: context.strategyName,
29181
29420
  exchangeName: context.exchangeName,
29182
29421
  frameName: "",
@@ -29205,26 +29444,67 @@ class LiveUtils {
29205
29444
  * }, "manual-cancel-001");
29206
29445
  * ```
29207
29446
  */
29208
- this.commitCancel = async (symbol, context, cancelId) => {
29209
- bt.loggerService.info(LIVE_METHOD_NAME_CANCEL, {
29447
+ this.commitCancelScheduled = async (symbol, context, cancelId) => {
29448
+ bt.loggerService.info(LIVE_METHOD_NAME_CANCEL_SCHEDULED, {
29210
29449
  symbol,
29211
29450
  context,
29212
29451
  cancelId,
29213
29452
  });
29214
- bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_CANCEL);
29215
- bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_CANCEL);
29453
+ bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_CANCEL_SCHEDULED);
29454
+ bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_CANCEL_SCHEDULED);
29216
29455
  {
29217
29456
  const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
29218
- riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CANCEL);
29219
- riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CANCEL));
29220
- actions && actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_CANCEL));
29457
+ riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CANCEL_SCHEDULED);
29458
+ riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CANCEL_SCHEDULED));
29459
+ actions && actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_CANCEL_SCHEDULED));
29221
29460
  }
29222
- await bt.strategyCoreService.cancel(false, symbol, {
29461
+ await bt.strategyCoreService.cancelScheduled(false, symbol, {
29223
29462
  strategyName: context.strategyName,
29224
29463
  exchangeName: context.exchangeName,
29225
29464
  frameName: "",
29226
29465
  }, cancelId);
29227
29466
  };
29467
+ /**
29468
+ * Closes the pending signal without stopping the strategy.
29469
+ *
29470
+ * Clears the pending signal (active position).
29471
+ * Does NOT affect scheduled signals or strategy operation.
29472
+ * Does NOT set stop flag - strategy can continue generating new signals.
29473
+ *
29474
+ * @param symbol - Trading pair symbol
29475
+ * @param context - Execution context with strategyName and exchangeName
29476
+ * @param closeId - Optional close ID for user-initiated closes
29477
+ * @returns Promise that resolves when pending signal is closed
29478
+ *
29479
+ * @example
29480
+ * ```typescript
29481
+ * // Close pending signal with custom ID
29482
+ * await Live.commitClose("BTCUSDT", {
29483
+ * exchangeName: "binance",
29484
+ * strategyName: "my-strategy"
29485
+ * }, "manual-close-001");
29486
+ * ```
29487
+ */
29488
+ this.commitClosePending = async (symbol, context, closeId) => {
29489
+ bt.loggerService.info(LIVE_METHOD_NAME_CLOSE_PENDING, {
29490
+ symbol,
29491
+ context,
29492
+ closeId,
29493
+ });
29494
+ bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_CLOSE_PENDING);
29495
+ bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_CLOSE_PENDING);
29496
+ {
29497
+ const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
29498
+ riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CLOSE_PENDING);
29499
+ riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CLOSE_PENDING));
29500
+ actions && actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_CLOSE_PENDING));
29501
+ }
29502
+ await bt.strategyCoreService.closePending(false, symbol, {
29503
+ strategyName: context.strategyName,
29504
+ exchangeName: context.exchangeName,
29505
+ frameName: "",
29506
+ }, closeId);
29507
+ };
29228
29508
  /**
29229
29509
  * Executes partial close at profit level (moving toward TP).
29230
29510
  *
@@ -30141,7 +30421,7 @@ class WalkerInstance {
30141
30421
  this.task(symbol, context).catch((error) => exitEmitter.next(new Error(getErrorMessage(error))));
30142
30422
  return () => {
30143
30423
  for (const strategyName of walkerSchema.strategies) {
30144
- bt.strategyCoreService.stop(true, symbol, {
30424
+ bt.strategyCoreService.stopStrategy(true, symbol, {
30145
30425
  strategyName,
30146
30426
  exchangeName: walkerSchema.exchangeName,
30147
30427
  frameName: walkerSchema.frameName
@@ -30297,7 +30577,7 @@ class WalkerUtils {
30297
30577
  }
30298
30578
  for (const strategyName of walkerSchema.strategies) {
30299
30579
  await walkerStopSubject.next({ symbol, strategyName, walkerName: context.walkerName });
30300
- await bt.strategyCoreService.stop(true, symbol, {
30580
+ await bt.strategyCoreService.stopStrategy(true, symbol, {
30301
30581
  strategyName,
30302
30582
  exchangeName: walkerSchema.exchangeName,
30303
30583
  frameName: walkerSchema.frameName
@@ -32680,4 +32960,4 @@ const set = (object, path, value) => {
32680
32960
  }
32681
32961
  };
32682
32962
 
32683
- export { ActionBase, Backtest, Breakeven, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, Markdown, MarkdownFileBase, MarkdownFolderBase, MethodContextService, Notification, Optimizer, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, Report, ReportBase, Risk, Schedule, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addOptimizerSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, commitBreakeven, commitCancel, commitPartialLoss, commitPartialProfit, commitSignalPromptHistory, commitTrailingStop, commitTrailingTake, dumpSignalData, emitters, formatPrice, formatQuantity, get, getActionSchema, getAveragePrice, getBacktestTimeframe, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getExchangeSchema, getFrameSchema, getMode, getOptimizerSchema, getOrderBook, getRiskSchema, getSizingSchema, getStrategySchema, getSymbol, getWalkerSchema, hasTradeContext, backtest as lib, listExchangeSchema, listFrameSchema, listOptimizerSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideOptimizerSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, roundTicks, set, setColumns, setConfig, setLogger, stop, validate };
32963
+ export { ActionBase, Backtest, Breakeven, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, Markdown, MarkdownFileBase, MarkdownFolderBase, MethodContextService, Notification, Optimizer, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, Report, ReportBase, Risk, Schedule, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addOptimizerSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialProfit, commitSignalPromptHistory, commitTrailingStop, commitTrailingTake, dumpSignalData, emitters, formatPrice, formatQuantity, get, getActionSchema, getAveragePrice, getBacktestTimeframe, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getExchangeSchema, getFrameSchema, getMode, getOptimizerSchema, getOrderBook, getRiskSchema, getSizingSchema, getStrategySchema, getSymbol, getWalkerSchema, hasTradeContext, backtest as lib, listExchangeSchema, listFrameSchema, listOptimizerSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideOptimizerSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, roundTicks, set, setColumns, setConfig, setLogger, stopStrategy, validate };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "2.0.12",
3
+ "version": "2.1.1",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",