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.cjs +340 -59
- package/build/index.mjs +338 -58
- package/package.json +1 -1
- package/types.d.ts +160 -19
package/build/index.cjs
CHANGED
|
@@ -4410,6 +4410,7 @@ class ClientStrategy {
|
|
|
4410
4410
|
this._lastSignalTimestamp = null;
|
|
4411
4411
|
this._scheduledSignal = null;
|
|
4412
4412
|
this._cancelledSignal = null;
|
|
4413
|
+
this._closedSignal = null;
|
|
4413
4414
|
/**
|
|
4414
4415
|
* Initializes strategy state by loading persisted signal from disk.
|
|
4415
4416
|
*
|
|
@@ -4686,6 +4687,41 @@ class ClientStrategy {
|
|
|
4686
4687
|
reason: "user",
|
|
4687
4688
|
cancelId: cancelledSignal.cancelId,
|
|
4688
4689
|
};
|
|
4690
|
+
await CALL_TICK_CALLBACKS_FN(this, this.params.execution.context.symbol, result, currentTime, this.params.execution.context.backtest);
|
|
4691
|
+
return result;
|
|
4692
|
+
}
|
|
4693
|
+
// Check if pending signal was closed - emit closed event once
|
|
4694
|
+
if (this._closedSignal) {
|
|
4695
|
+
const currentPrice = await this.params.exchange.getAveragePrice(this.params.execution.context.symbol);
|
|
4696
|
+
const closedSignal = this._closedSignal;
|
|
4697
|
+
this._closedSignal = null; // Clear after emitting
|
|
4698
|
+
this.params.logger.info("ClientStrategy tick: pending signal was closed", {
|
|
4699
|
+
symbol: this.params.execution.context.symbol,
|
|
4700
|
+
signalId: closedSignal.id,
|
|
4701
|
+
});
|
|
4702
|
+
// Call onClose callback
|
|
4703
|
+
await CALL_CLOSE_CALLBACKS_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, currentTime, this.params.execution.context.backtest);
|
|
4704
|
+
// КРИТИЧНО: Очищаем состояние ClientPartial при закрытии позиции
|
|
4705
|
+
await CALL_PARTIAL_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, currentTime, this.params.execution.context.backtest);
|
|
4706
|
+
// КРИТИЧНО: Очищаем состояние ClientBreakeven при закрытии позиции
|
|
4707
|
+
await CALL_BREAKEVEN_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, currentTime, this.params.execution.context.backtest);
|
|
4708
|
+
await CALL_RISK_REMOVE_SIGNAL_FN(this, this.params.execution.context.symbol, currentTime, this.params.execution.context.backtest);
|
|
4709
|
+
const pnl = toProfitLossDto(closedSignal, currentPrice);
|
|
4710
|
+
const result = {
|
|
4711
|
+
action: "closed",
|
|
4712
|
+
signal: TO_PUBLIC_SIGNAL(closedSignal),
|
|
4713
|
+
currentPrice,
|
|
4714
|
+
closeReason: "closed",
|
|
4715
|
+
closeTimestamp: currentTime,
|
|
4716
|
+
pnl,
|
|
4717
|
+
strategyName: this.params.method.context.strategyName,
|
|
4718
|
+
exchangeName: this.params.method.context.exchangeName,
|
|
4719
|
+
frameName: this.params.method.context.frameName,
|
|
4720
|
+
symbol: this.params.execution.context.symbol,
|
|
4721
|
+
backtest: this.params.execution.context.backtest,
|
|
4722
|
+
closeId: closedSignal.closeId,
|
|
4723
|
+
};
|
|
4724
|
+
await CALL_TICK_CALLBACKS_FN(this, this.params.execution.context.symbol, result, currentTime, this.params.execution.context.backtest);
|
|
4689
4725
|
return result;
|
|
4690
4726
|
}
|
|
4691
4727
|
// Monitor scheduled signal
|
|
@@ -4799,8 +4835,40 @@ class ClientStrategy {
|
|
|
4799
4835
|
reason: "user",
|
|
4800
4836
|
cancelId: cancelledSignal.cancelId,
|
|
4801
4837
|
};
|
|
4838
|
+
await CALL_TICK_CALLBACKS_FN(this, this.params.execution.context.symbol, cancelledResult, closeTimestamp, this.params.execution.context.backtest);
|
|
4802
4839
|
return cancelledResult;
|
|
4803
4840
|
}
|
|
4841
|
+
// If signal was closed - return closed
|
|
4842
|
+
if (this._closedSignal) {
|
|
4843
|
+
this.params.logger.debug("ClientStrategy backtest: pending signal was closed");
|
|
4844
|
+
const currentPrice = await this.params.exchange.getAveragePrice(symbol);
|
|
4845
|
+
const closedSignal = this._closedSignal;
|
|
4846
|
+
this._closedSignal = null; // Clear after using
|
|
4847
|
+
const closeTimestamp = this.params.execution.context.when.getTime();
|
|
4848
|
+
await CALL_CLOSE_CALLBACKS_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, closeTimestamp, this.params.execution.context.backtest);
|
|
4849
|
+
// КРИТИЧНО: Очищаем состояние ClientPartial при закрытии позиции
|
|
4850
|
+
await CALL_PARTIAL_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, closeTimestamp, this.params.execution.context.backtest);
|
|
4851
|
+
// КРИТИЧНО: Очищаем состояние ClientBreakeven при закрытии позиции
|
|
4852
|
+
await CALL_BREAKEVEN_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, closeTimestamp, this.params.execution.context.backtest);
|
|
4853
|
+
await CALL_RISK_REMOVE_SIGNAL_FN(this, this.params.execution.context.symbol, closeTimestamp, this.params.execution.context.backtest);
|
|
4854
|
+
const pnl = toProfitLossDto(closedSignal, currentPrice);
|
|
4855
|
+
const closedResult = {
|
|
4856
|
+
action: "closed",
|
|
4857
|
+
signal: TO_PUBLIC_SIGNAL(closedSignal),
|
|
4858
|
+
currentPrice,
|
|
4859
|
+
closeReason: "closed",
|
|
4860
|
+
closeTimestamp: closeTimestamp,
|
|
4861
|
+
pnl,
|
|
4862
|
+
strategyName: this.params.method.context.strategyName,
|
|
4863
|
+
exchangeName: this.params.method.context.exchangeName,
|
|
4864
|
+
frameName: this.params.method.context.frameName,
|
|
4865
|
+
symbol: this.params.execution.context.symbol,
|
|
4866
|
+
backtest: true,
|
|
4867
|
+
closeId: closedSignal.closeId,
|
|
4868
|
+
};
|
|
4869
|
+
await CALL_TICK_CALLBACKS_FN(this, this.params.execution.context.symbol, closedResult, closeTimestamp, this.params.execution.context.backtest);
|
|
4870
|
+
return closedResult;
|
|
4871
|
+
}
|
|
4804
4872
|
if (!this._pendingSignal && !this._scheduledSignal) {
|
|
4805
4873
|
throw new Error("ClientStrategy backtest: no pending or scheduled signal");
|
|
4806
4874
|
}
|
|
@@ -4927,12 +4995,12 @@ class ClientStrategy {
|
|
|
4927
4995
|
* @example
|
|
4928
4996
|
* ```typescript
|
|
4929
4997
|
* // In Live.background() cancellation
|
|
4930
|
-
* await strategy.
|
|
4998
|
+
* await strategy.stopStrategy();
|
|
4931
4999
|
* // Existing signal will continue until natural close
|
|
4932
5000
|
* ```
|
|
4933
5001
|
*/
|
|
4934
|
-
async
|
|
4935
|
-
this.params.logger.debug("ClientStrategy
|
|
5002
|
+
async stopStrategy(symbol, backtest) {
|
|
5003
|
+
this.params.logger.debug("ClientStrategy stopStrategy", {
|
|
4936
5004
|
symbol,
|
|
4937
5005
|
hasPendingSignal: this._pendingSignal !== null,
|
|
4938
5006
|
hasScheduledSignal: this._scheduledSignal !== null,
|
|
@@ -4965,12 +5033,12 @@ class ClientStrategy {
|
|
|
4965
5033
|
* @example
|
|
4966
5034
|
* ```typescript
|
|
4967
5035
|
* // Cancel scheduled signal without stopping strategy
|
|
4968
|
-
* await strategy.
|
|
5036
|
+
* await strategy.cancelScheduled("BTCUSDT", "my-strategy", false);
|
|
4969
5037
|
* // Strategy continues, can generate new signals
|
|
4970
5038
|
* ```
|
|
4971
5039
|
*/
|
|
4972
|
-
async
|
|
4973
|
-
this.params.logger.debug("ClientStrategy
|
|
5040
|
+
async cancelScheduled(symbol, backtest, cancelId) {
|
|
5041
|
+
this.params.logger.debug("ClientStrategy cancelScheduled", {
|
|
4974
5042
|
symbol,
|
|
4975
5043
|
hasScheduledSignal: this._scheduledSignal !== null,
|
|
4976
5044
|
cancelId,
|
|
@@ -4987,6 +5055,45 @@ class ClientStrategy {
|
|
|
4987
5055
|
}
|
|
4988
5056
|
await PersistScheduleAdapter.writeScheduleData(this._scheduledSignal, symbol, this.params.method.context.strategyName, this.params.method.context.exchangeName);
|
|
4989
5057
|
}
|
|
5058
|
+
/**
|
|
5059
|
+
* Closes the pending signal without stopping the strategy.
|
|
5060
|
+
*
|
|
5061
|
+
* Clears the pending signal (active position).
|
|
5062
|
+
* Does NOT affect scheduled signals or strategy operation.
|
|
5063
|
+
* Does NOT set stop flag - strategy can continue generating new signals.
|
|
5064
|
+
*
|
|
5065
|
+
* Use case: Close an active position that is no longer desired without stopping the entire strategy.
|
|
5066
|
+
*
|
|
5067
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
5068
|
+
* @param backtest - Whether running in backtest mode
|
|
5069
|
+
* @param closeId - Optional identifier for this close operation
|
|
5070
|
+
* @returns Promise that resolves when pending signal is cleared
|
|
5071
|
+
*
|
|
5072
|
+
* @example
|
|
5073
|
+
* ```typescript
|
|
5074
|
+
* // Close pending signal without stopping strategy
|
|
5075
|
+
* await strategy.closePending("BTCUSDT", false, "user-close-123");
|
|
5076
|
+
* // Strategy continues, can generate new signals
|
|
5077
|
+
* ```
|
|
5078
|
+
*/
|
|
5079
|
+
async closePending(symbol, backtest, closeId) {
|
|
5080
|
+
this.params.logger.debug("ClientStrategy closePending", {
|
|
5081
|
+
symbol,
|
|
5082
|
+
hasPendingSignal: this._pendingSignal !== null,
|
|
5083
|
+
closeId,
|
|
5084
|
+
});
|
|
5085
|
+
// Save closed signal for next tick to emit closed event
|
|
5086
|
+
if (this._pendingSignal) {
|
|
5087
|
+
this._closedSignal = Object.assign({}, this._pendingSignal, {
|
|
5088
|
+
closeId,
|
|
5089
|
+
});
|
|
5090
|
+
this._pendingSignal = null;
|
|
5091
|
+
}
|
|
5092
|
+
if (backtest) {
|
|
5093
|
+
return;
|
|
5094
|
+
}
|
|
5095
|
+
await PersistSignalAdapter.writeSignalData(this._pendingSignal, symbol, this.params.strategyName, this.params.exchangeName);
|
|
5096
|
+
}
|
|
4990
5097
|
/**
|
|
4991
5098
|
* Executes partial close at profit level (moving toward TP).
|
|
4992
5099
|
*
|
|
@@ -6439,7 +6546,7 @@ class StrategyConnectionService {
|
|
|
6439
6546
|
/**
|
|
6440
6547
|
* Stops the specified strategy from generating new signals.
|
|
6441
6548
|
*
|
|
6442
|
-
* Delegates to ClientStrategy.
|
|
6549
|
+
* Delegates to ClientStrategy.stopStrategy() which sets internal flag to prevent
|
|
6443
6550
|
* getSignal from being called on subsequent ticks.
|
|
6444
6551
|
*
|
|
6445
6552
|
* @param backtest - Whether running in backtest mode
|
|
@@ -6447,13 +6554,13 @@ class StrategyConnectionService {
|
|
|
6447
6554
|
* @param ctx - Context with strategyName, exchangeName, frameName
|
|
6448
6555
|
* @returns Promise that resolves when stop flag is set
|
|
6449
6556
|
*/
|
|
6450
|
-
this.
|
|
6451
|
-
this.loggerService.log("strategyConnectionService
|
|
6557
|
+
this.stopStrategy = async (backtest, symbol, context) => {
|
|
6558
|
+
this.loggerService.log("strategyConnectionService stopStrategy", {
|
|
6452
6559
|
symbol,
|
|
6453
6560
|
context,
|
|
6454
6561
|
});
|
|
6455
6562
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
6456
|
-
await strategy.
|
|
6563
|
+
await strategy.stopStrategy(symbol, backtest);
|
|
6457
6564
|
};
|
|
6458
6565
|
/**
|
|
6459
6566
|
* Disposes the ClientStrategy instance for the given context.
|
|
@@ -6505,7 +6612,7 @@ class StrategyConnectionService {
|
|
|
6505
6612
|
/**
|
|
6506
6613
|
* Cancels the scheduled signal for the specified strategy.
|
|
6507
6614
|
*
|
|
6508
|
-
* Delegates to ClientStrategy.
|
|
6615
|
+
* Delegates to ClientStrategy.cancelScheduled() which clears the scheduled signal
|
|
6509
6616
|
* without stopping the strategy or affecting pending signals.
|
|
6510
6617
|
*
|
|
6511
6618
|
* Note: Cancelled event will be emitted on next tick() call when strategy
|
|
@@ -6517,14 +6624,39 @@ class StrategyConnectionService {
|
|
|
6517
6624
|
* @param cancelId - Optional cancellation ID for user-initiated cancellations
|
|
6518
6625
|
* @returns Promise that resolves when scheduled signal is cancelled
|
|
6519
6626
|
*/
|
|
6520
|
-
this.
|
|
6521
|
-
this.loggerService.log("strategyConnectionService
|
|
6627
|
+
this.cancelScheduled = async (backtest, symbol, context, cancelId) => {
|
|
6628
|
+
this.loggerService.log("strategyConnectionService cancelScheduled", {
|
|
6522
6629
|
symbol,
|
|
6523
6630
|
context,
|
|
6524
6631
|
cancelId,
|
|
6525
6632
|
});
|
|
6526
6633
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
6527
|
-
await strategy.
|
|
6634
|
+
await strategy.cancelScheduled(symbol, backtest, cancelId);
|
|
6635
|
+
};
|
|
6636
|
+
/**
|
|
6637
|
+
* Closes the pending signal without stopping the strategy.
|
|
6638
|
+
*
|
|
6639
|
+
* Clears the pending signal (active position).
|
|
6640
|
+
* Does NOT affect scheduled signals or strategy operation.
|
|
6641
|
+
* Does NOT set stop flag - strategy can continue generating new signals.
|
|
6642
|
+
*
|
|
6643
|
+
* Note: Closed event will be emitted on next tick() call when strategy
|
|
6644
|
+
* detects the pending signal was closed.
|
|
6645
|
+
*
|
|
6646
|
+
* @param backtest - Whether running in backtest mode
|
|
6647
|
+
* @param symbol - Trading pair symbol
|
|
6648
|
+
* @param context - Context with strategyName, exchangeName, frameName
|
|
6649
|
+
* @param closeId - Optional close ID for user-initiated closes
|
|
6650
|
+
* @returns Promise that resolves when pending signal is closed
|
|
6651
|
+
*/
|
|
6652
|
+
this.closePending = async (backtest, symbol, context, closeId) => {
|
|
6653
|
+
this.loggerService.log("strategyConnectionService closePending", {
|
|
6654
|
+
symbol,
|
|
6655
|
+
context,
|
|
6656
|
+
closeId,
|
|
6657
|
+
});
|
|
6658
|
+
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
6659
|
+
await strategy.closePending(symbol, backtest, closeId);
|
|
6528
6660
|
};
|
|
6529
6661
|
/**
|
|
6530
6662
|
* Executes partial close at profit level (moving toward TP).
|
|
@@ -9711,19 +9843,19 @@ class StrategyCoreService {
|
|
|
9711
9843
|
* @param ctx - Context with strategyName, exchangeName, frameName
|
|
9712
9844
|
* @returns Promise that resolves when stop flag is set
|
|
9713
9845
|
*/
|
|
9714
|
-
this.
|
|
9715
|
-
this.loggerService.log("strategyCoreService
|
|
9846
|
+
this.stopStrategy = async (backtest, symbol, context) => {
|
|
9847
|
+
this.loggerService.log("strategyCoreService stopStrategy", {
|
|
9716
9848
|
symbol,
|
|
9717
9849
|
context,
|
|
9718
9850
|
backtest,
|
|
9719
9851
|
});
|
|
9720
9852
|
await this.validate(context);
|
|
9721
|
-
return await this.strategyConnectionService.
|
|
9853
|
+
return await this.strategyConnectionService.stopStrategy(backtest, symbol, context);
|
|
9722
9854
|
};
|
|
9723
9855
|
/**
|
|
9724
9856
|
* Cancels the scheduled signal without stopping the strategy.
|
|
9725
9857
|
*
|
|
9726
|
-
* Delegates to StrategyConnectionService.
|
|
9858
|
+
* Delegates to StrategyConnectionService.cancelScheduled() to clear scheduled signal
|
|
9727
9859
|
* and emit cancelled event through emitters.
|
|
9728
9860
|
* Does not require execution context.
|
|
9729
9861
|
*
|
|
@@ -9733,15 +9865,42 @@ class StrategyCoreService {
|
|
|
9733
9865
|
* @param cancelId - Optional cancellation ID for user-initiated cancellations
|
|
9734
9866
|
* @returns Promise that resolves when scheduled signal is cancelled
|
|
9735
9867
|
*/
|
|
9736
|
-
this.
|
|
9737
|
-
this.loggerService.log("strategyCoreService
|
|
9868
|
+
this.cancelScheduled = async (backtest, symbol, context, cancelId) => {
|
|
9869
|
+
this.loggerService.log("strategyCoreService cancelScheduled", {
|
|
9738
9870
|
symbol,
|
|
9739
9871
|
context,
|
|
9740
9872
|
backtest,
|
|
9741
9873
|
cancelId,
|
|
9742
9874
|
});
|
|
9743
9875
|
await this.validate(context);
|
|
9744
|
-
return await this.strategyConnectionService.
|
|
9876
|
+
return await this.strategyConnectionService.cancelScheduled(backtest, symbol, context, cancelId);
|
|
9877
|
+
};
|
|
9878
|
+
/**
|
|
9879
|
+
* Closes the pending signal without stopping the strategy.
|
|
9880
|
+
*
|
|
9881
|
+
* Clears the pending signal (active position).
|
|
9882
|
+
* Does NOT affect scheduled signals or strategy operation.
|
|
9883
|
+
* Does NOT set stop flag - strategy can continue generating new signals.
|
|
9884
|
+
*
|
|
9885
|
+
* Delegates to StrategyConnectionService.closePending() to clear pending signal
|
|
9886
|
+
* and emit closed event through emitters.
|
|
9887
|
+
* Does not require execution context.
|
|
9888
|
+
*
|
|
9889
|
+
* @param backtest - Whether running in backtest mode
|
|
9890
|
+
* @param symbol - Trading pair symbol
|
|
9891
|
+
* @param context - Context with strategyName, exchangeName, frameName
|
|
9892
|
+
* @param closeId - Optional close ID for user-initiated closes
|
|
9893
|
+
* @returns Promise that resolves when pending signal is closed
|
|
9894
|
+
*/
|
|
9895
|
+
this.closePending = async (backtest, symbol, context, closeId) => {
|
|
9896
|
+
this.loggerService.log("strategyCoreService closePending", {
|
|
9897
|
+
symbol,
|
|
9898
|
+
context,
|
|
9899
|
+
backtest,
|
|
9900
|
+
closeId,
|
|
9901
|
+
});
|
|
9902
|
+
await this.validate(context);
|
|
9903
|
+
return await this.strategyConnectionService.closePending(backtest, symbol, context, closeId);
|
|
9745
9904
|
};
|
|
9746
9905
|
/**
|
|
9747
9906
|
* Disposes the ClientStrategy instance for the given context.
|
|
@@ -25027,7 +25186,8 @@ async function getOrderBook(symbol, depth) {
|
|
|
25027
25186
|
return await bt.exchangeConnectionService.getOrderBook(symbol, depth);
|
|
25028
25187
|
}
|
|
25029
25188
|
|
|
25030
|
-
const
|
|
25189
|
+
const CANCEL_SCHEDULED_METHOD_NAME = "strategy.commitCancelScheduled";
|
|
25190
|
+
const CLOSE_PENDING_METHOD_NAME = "strategy.commitClosePending";
|
|
25031
25191
|
const PARTIAL_PROFIT_METHOD_NAME = "strategy.commitPartialProfit";
|
|
25032
25192
|
const PARTIAL_LOSS_METHOD_NAME = "strategy.commitPartialLoss";
|
|
25033
25193
|
const TRAILING_STOP_METHOD_NAME = "strategy.commitTrailingStop";
|
|
@@ -25049,26 +25209,62 @@ const BREAKEVEN_METHOD_NAME = "strategy.commitBreakeven";
|
|
|
25049
25209
|
*
|
|
25050
25210
|
* @example
|
|
25051
25211
|
* ```typescript
|
|
25052
|
-
* import {
|
|
25212
|
+
* import { commitCancelScheduled } from "backtest-kit";
|
|
25053
25213
|
*
|
|
25054
25214
|
* // Cancel scheduled signal with custom ID
|
|
25055
|
-
* await
|
|
25215
|
+
* await commitCancelScheduled("BTCUSDT", "manual-cancel-001");
|
|
25056
25216
|
* ```
|
|
25057
25217
|
*/
|
|
25058
|
-
async function
|
|
25059
|
-
bt.loggerService.info(
|
|
25218
|
+
async function commitCancelScheduled(symbol, cancelId) {
|
|
25219
|
+
bt.loggerService.info(CANCEL_SCHEDULED_METHOD_NAME, {
|
|
25060
25220
|
symbol,
|
|
25061
25221
|
cancelId,
|
|
25062
25222
|
});
|
|
25063
25223
|
if (!ExecutionContextService.hasContext()) {
|
|
25064
|
-
throw new Error("
|
|
25224
|
+
throw new Error("commitCancelScheduled requires an execution context");
|
|
25225
|
+
}
|
|
25226
|
+
if (!MethodContextService.hasContext()) {
|
|
25227
|
+
throw new Error("commitCancelScheduled requires a method context");
|
|
25228
|
+
}
|
|
25229
|
+
const { backtest: isBacktest } = bt.executionContextService.context;
|
|
25230
|
+
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
25231
|
+
await bt.strategyCoreService.cancelScheduled(isBacktest, symbol, { exchangeName, frameName, strategyName }, cancelId);
|
|
25232
|
+
}
|
|
25233
|
+
/**
|
|
25234
|
+
* Closes the pending signal without stopping the strategy.
|
|
25235
|
+
*
|
|
25236
|
+
* Clears the pending signal (active position).
|
|
25237
|
+
* Does NOT affect scheduled signals or strategy operation.
|
|
25238
|
+
* Does NOT set stop flag - strategy can continue generating new signals.
|
|
25239
|
+
*
|
|
25240
|
+
* Automatically detects backtest/live mode from execution context.
|
|
25241
|
+
*
|
|
25242
|
+
* @param symbol - Trading pair symbol
|
|
25243
|
+
* @param closeId - Optional close ID for tracking user-initiated closes
|
|
25244
|
+
* @returns Promise that resolves when pending signal is closed
|
|
25245
|
+
*
|
|
25246
|
+
* @example
|
|
25247
|
+
* ```typescript
|
|
25248
|
+
* import { commitClosePending } from "backtest-kit";
|
|
25249
|
+
*
|
|
25250
|
+
* // Close pending signal with custom ID
|
|
25251
|
+
* await commitClosePending("BTCUSDT", "manual-close-001");
|
|
25252
|
+
* ```
|
|
25253
|
+
*/
|
|
25254
|
+
async function commitClosePending(symbol, closeId) {
|
|
25255
|
+
bt.loggerService.info(CLOSE_PENDING_METHOD_NAME, {
|
|
25256
|
+
symbol,
|
|
25257
|
+
closeId,
|
|
25258
|
+
});
|
|
25259
|
+
if (!ExecutionContextService.hasContext()) {
|
|
25260
|
+
throw new Error("commitClosePending requires an execution context");
|
|
25065
25261
|
}
|
|
25066
25262
|
if (!MethodContextService.hasContext()) {
|
|
25067
|
-
throw new Error("
|
|
25263
|
+
throw new Error("commitClosePending requires a method context");
|
|
25068
25264
|
}
|
|
25069
25265
|
const { backtest: isBacktest } = bt.executionContextService.context;
|
|
25070
25266
|
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
25071
|
-
await bt.strategyCoreService.
|
|
25267
|
+
await bt.strategyCoreService.closePending(isBacktest, symbol, { exchangeName, frameName, strategyName }, closeId);
|
|
25072
25268
|
}
|
|
25073
25269
|
/**
|
|
25074
25270
|
* Executes partial close at profit level (moving toward TP).
|
|
@@ -25315,7 +25511,7 @@ async function commitBreakeven(symbol) {
|
|
|
25315
25511
|
return await bt.strategyCoreService.breakeven(isBacktest, symbol, currentPrice, { exchangeName, frameName, strategyName });
|
|
25316
25512
|
}
|
|
25317
25513
|
|
|
25318
|
-
const
|
|
25514
|
+
const STOP_STRATEGY_METHOD_NAME = "control.stopStrategy";
|
|
25319
25515
|
/**
|
|
25320
25516
|
* Stops the strategy from generating new signals.
|
|
25321
25517
|
*
|
|
@@ -25337,8 +25533,8 @@ const STOP_METHOD_NAME = "control.stop";
|
|
|
25337
25533
|
* await stop("BTCUSDT", "my-strategy");
|
|
25338
25534
|
* ```
|
|
25339
25535
|
*/
|
|
25340
|
-
async function
|
|
25341
|
-
bt.loggerService.info(
|
|
25536
|
+
async function stopStrategy(symbol) {
|
|
25537
|
+
bt.loggerService.info(STOP_STRATEGY_METHOD_NAME, {
|
|
25342
25538
|
symbol,
|
|
25343
25539
|
});
|
|
25344
25540
|
if (!ExecutionContextService.hasContext()) {
|
|
@@ -25349,7 +25545,7 @@ async function stop(symbol) {
|
|
|
25349
25545
|
}
|
|
25350
25546
|
const { backtest: isBacktest } = bt.executionContextService.context;
|
|
25351
25547
|
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
25352
|
-
await bt.strategyCoreService.
|
|
25548
|
+
await bt.strategyCoreService.stopStrategy(isBacktest, symbol, {
|
|
25353
25549
|
exchangeName,
|
|
25354
25550
|
frameName,
|
|
25355
25551
|
strategyName,
|
|
@@ -27736,7 +27932,8 @@ const BACKTEST_METHOD_NAME_GET_PENDING_SIGNAL = "BacktestUtils.getPendingSignal"
|
|
|
27736
27932
|
const BACKTEST_METHOD_NAME_GET_SCHEDULED_SIGNAL = "BacktestUtils.getScheduledSignal";
|
|
27737
27933
|
const BACKTEST_METHOD_NAME_GET_BREAKEVEN = "BacktestUtils.getBreakeven";
|
|
27738
27934
|
const BACKTEST_METHOD_NAME_BREAKEVEN = "Backtest.commitBreakeven";
|
|
27739
|
-
const
|
|
27935
|
+
const BACKTEST_METHOD_NAME_CANCEL_SCHEDULED = "Backtest.commitCancelScheduled";
|
|
27936
|
+
const BACKTEST_METHOD_NAME_CLOSE_PENDING = "Backtest.commitClosePending";
|
|
27740
27937
|
const BACKTEST_METHOD_NAME_PARTIAL_PROFIT = "BacktestUtils.commitPartialProfit";
|
|
27741
27938
|
const BACKTEST_METHOD_NAME_PARTIAL_LOSS = "BacktestUtils.commitPartialLoss";
|
|
27742
27939
|
const BACKTEST_METHOD_NAME_TRAILING_STOP = "BacktestUtils.commitTrailingStop";
|
|
@@ -27978,7 +28175,7 @@ class BacktestInstance {
|
|
|
27978
28175
|
}
|
|
27979
28176
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
|
|
27980
28177
|
return () => {
|
|
27981
|
-
bt.strategyCoreService.
|
|
28178
|
+
bt.strategyCoreService.stopStrategy(true, symbol, {
|
|
27982
28179
|
strategyName: context.strategyName,
|
|
27983
28180
|
exchangeName: context.exchangeName,
|
|
27984
28181
|
frameName: context.frameName,
|
|
@@ -28246,7 +28443,7 @@ class BacktestUtils {
|
|
|
28246
28443
|
actions &&
|
|
28247
28444
|
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_STOP));
|
|
28248
28445
|
}
|
|
28249
|
-
await bt.strategyCoreService.
|
|
28446
|
+
await bt.strategyCoreService.stopStrategy(true, symbol, context);
|
|
28250
28447
|
};
|
|
28251
28448
|
/**
|
|
28252
28449
|
* Cancels the scheduled signal without stopping the strategy.
|
|
@@ -28271,24 +28468,65 @@ class BacktestUtils {
|
|
|
28271
28468
|
* }, "manual-cancel-001");
|
|
28272
28469
|
* ```
|
|
28273
28470
|
*/
|
|
28274
|
-
this.
|
|
28275
|
-
bt.loggerService.info(
|
|
28471
|
+
this.commitCancelScheduled = async (symbol, context, cancelId) => {
|
|
28472
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_CANCEL_SCHEDULED, {
|
|
28276
28473
|
symbol,
|
|
28277
28474
|
context,
|
|
28278
28475
|
cancelId,
|
|
28279
28476
|
});
|
|
28280
|
-
bt.strategyValidationService.validate(context.strategyName,
|
|
28281
|
-
bt.exchangeValidationService.validate(context.exchangeName,
|
|
28477
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED);
|
|
28478
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED);
|
|
28282
28479
|
{
|
|
28283
28480
|
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
28284
28481
|
riskName &&
|
|
28285
|
-
bt.riskValidationService.validate(riskName,
|
|
28482
|
+
bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED);
|
|
28286
28483
|
riskList &&
|
|
28287
|
-
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName,
|
|
28484
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED));
|
|
28288
28485
|
actions &&
|
|
28289
|
-
actions.forEach((actionName) => bt.actionValidationService.validate(actionName,
|
|
28486
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED));
|
|
28290
28487
|
}
|
|
28291
|
-
await bt.strategyCoreService.
|
|
28488
|
+
await bt.strategyCoreService.cancelScheduled(true, symbol, context, cancelId);
|
|
28489
|
+
};
|
|
28490
|
+
/**
|
|
28491
|
+
* Closes the pending signal without stopping the strategy.
|
|
28492
|
+
*
|
|
28493
|
+
* Clears the pending signal (active position).
|
|
28494
|
+
* Does NOT affect scheduled signals or strategy operation.
|
|
28495
|
+
* Does NOT set stop flag - strategy can continue generating new signals.
|
|
28496
|
+
*
|
|
28497
|
+
* @param symbol - Trading pair symbol
|
|
28498
|
+
* @param context - Execution context with strategyName, exchangeName, and frameName
|
|
28499
|
+
* @param closeId - Optional close ID for user-initiated closes
|
|
28500
|
+
* @returns Promise that resolves when pending signal is closed
|
|
28501
|
+
*
|
|
28502
|
+
* @example
|
|
28503
|
+
* ```typescript
|
|
28504
|
+
* // Close pending signal with custom ID
|
|
28505
|
+
* await Backtest.commitClose("BTCUSDT", {
|
|
28506
|
+
* exchangeName: "binance",
|
|
28507
|
+
* strategyName: "my-strategy",
|
|
28508
|
+
* frameName: "1m"
|
|
28509
|
+
* }, "manual-close-001");
|
|
28510
|
+
* ```
|
|
28511
|
+
*/
|
|
28512
|
+
this.commitClosePending = async (symbol, context, closeId) => {
|
|
28513
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_CLOSE_PENDING, {
|
|
28514
|
+
symbol,
|
|
28515
|
+
context,
|
|
28516
|
+
closeId,
|
|
28517
|
+
});
|
|
28518
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_CLOSE_PENDING);
|
|
28519
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_CLOSE_PENDING);
|
|
28520
|
+
{
|
|
28521
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
28522
|
+
riskName &&
|
|
28523
|
+
bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CLOSE_PENDING);
|
|
28524
|
+
riskList &&
|
|
28525
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CLOSE_PENDING));
|
|
28526
|
+
actions &&
|
|
28527
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_CLOSE_PENDING));
|
|
28528
|
+
}
|
|
28529
|
+
await bt.strategyCoreService.closePending(true, symbol, context, closeId);
|
|
28292
28530
|
};
|
|
28293
28531
|
/**
|
|
28294
28532
|
* Executes partial close at profit level (moving toward TP).
|
|
@@ -28725,7 +28963,8 @@ const LIVE_METHOD_NAME_GET_PENDING_SIGNAL = "LiveUtils.getPendingSignal";
|
|
|
28725
28963
|
const LIVE_METHOD_NAME_GET_SCHEDULED_SIGNAL = "LiveUtils.getScheduledSignal";
|
|
28726
28964
|
const LIVE_METHOD_NAME_GET_BREAKEVEN = "LiveUtils.getBreakeven";
|
|
28727
28965
|
const LIVE_METHOD_NAME_BREAKEVEN = "Live.commitBreakeven";
|
|
28728
|
-
const
|
|
28966
|
+
const LIVE_METHOD_NAME_CANCEL_SCHEDULED = "Live.cancelScheduled";
|
|
28967
|
+
const LIVE_METHOD_NAME_CLOSE_PENDING = "Live.closePending";
|
|
28729
28968
|
const LIVE_METHOD_NAME_PARTIAL_PROFIT = "LiveUtils.commitPartialProfit";
|
|
28730
28969
|
const LIVE_METHOD_NAME_PARTIAL_LOSS = "LiveUtils.commitPartialLoss";
|
|
28731
28970
|
const LIVE_METHOD_NAME_TRAILING_STOP = "LiveUtils.commitTrailingStop";
|
|
@@ -28930,7 +29169,7 @@ class LiveInstance {
|
|
|
28930
29169
|
}
|
|
28931
29170
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
|
|
28932
29171
|
return () => {
|
|
28933
|
-
bt.strategyCoreService.
|
|
29172
|
+
bt.strategyCoreService.stopStrategy(false, symbol, {
|
|
28934
29173
|
strategyName: context.strategyName,
|
|
28935
29174
|
exchangeName: context.exchangeName,
|
|
28936
29175
|
frameName: ""
|
|
@@ -29197,7 +29436,7 @@ class LiveUtils {
|
|
|
29197
29436
|
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_STOP));
|
|
29198
29437
|
actions && actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_STOP));
|
|
29199
29438
|
}
|
|
29200
|
-
await bt.strategyCoreService.
|
|
29439
|
+
await bt.strategyCoreService.stopStrategy(false, symbol, {
|
|
29201
29440
|
strategyName: context.strategyName,
|
|
29202
29441
|
exchangeName: context.exchangeName,
|
|
29203
29442
|
frameName: "",
|
|
@@ -29226,26 +29465,67 @@ class LiveUtils {
|
|
|
29226
29465
|
* }, "manual-cancel-001");
|
|
29227
29466
|
* ```
|
|
29228
29467
|
*/
|
|
29229
|
-
this.
|
|
29230
|
-
bt.loggerService.info(
|
|
29468
|
+
this.commitCancelScheduled = async (symbol, context, cancelId) => {
|
|
29469
|
+
bt.loggerService.info(LIVE_METHOD_NAME_CANCEL_SCHEDULED, {
|
|
29231
29470
|
symbol,
|
|
29232
29471
|
context,
|
|
29233
29472
|
cancelId,
|
|
29234
29473
|
});
|
|
29235
|
-
bt.strategyValidationService.validate(context.strategyName,
|
|
29236
|
-
bt.exchangeValidationService.validate(context.exchangeName,
|
|
29474
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_CANCEL_SCHEDULED);
|
|
29475
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_CANCEL_SCHEDULED);
|
|
29237
29476
|
{
|
|
29238
29477
|
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
29239
|
-
riskName && bt.riskValidationService.validate(riskName,
|
|
29240
|
-
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName,
|
|
29241
|
-
actions && actions.forEach((actionName) => bt.actionValidationService.validate(actionName,
|
|
29478
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CANCEL_SCHEDULED);
|
|
29479
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CANCEL_SCHEDULED));
|
|
29480
|
+
actions && actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_CANCEL_SCHEDULED));
|
|
29242
29481
|
}
|
|
29243
|
-
await bt.strategyCoreService.
|
|
29482
|
+
await bt.strategyCoreService.cancelScheduled(false, symbol, {
|
|
29244
29483
|
strategyName: context.strategyName,
|
|
29245
29484
|
exchangeName: context.exchangeName,
|
|
29246
29485
|
frameName: "",
|
|
29247
29486
|
}, cancelId);
|
|
29248
29487
|
};
|
|
29488
|
+
/**
|
|
29489
|
+
* Closes the pending signal without stopping the strategy.
|
|
29490
|
+
*
|
|
29491
|
+
* Clears the pending signal (active position).
|
|
29492
|
+
* Does NOT affect scheduled signals or strategy operation.
|
|
29493
|
+
* Does NOT set stop flag - strategy can continue generating new signals.
|
|
29494
|
+
*
|
|
29495
|
+
* @param symbol - Trading pair symbol
|
|
29496
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
29497
|
+
* @param closeId - Optional close ID for user-initiated closes
|
|
29498
|
+
* @returns Promise that resolves when pending signal is closed
|
|
29499
|
+
*
|
|
29500
|
+
* @example
|
|
29501
|
+
* ```typescript
|
|
29502
|
+
* // Close pending signal with custom ID
|
|
29503
|
+
* await Live.commitClose("BTCUSDT", {
|
|
29504
|
+
* exchangeName: "binance",
|
|
29505
|
+
* strategyName: "my-strategy"
|
|
29506
|
+
* }, "manual-close-001");
|
|
29507
|
+
* ```
|
|
29508
|
+
*/
|
|
29509
|
+
this.commitClosePending = async (symbol, context, closeId) => {
|
|
29510
|
+
bt.loggerService.info(LIVE_METHOD_NAME_CLOSE_PENDING, {
|
|
29511
|
+
symbol,
|
|
29512
|
+
context,
|
|
29513
|
+
closeId,
|
|
29514
|
+
});
|
|
29515
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_CLOSE_PENDING);
|
|
29516
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_CLOSE_PENDING);
|
|
29517
|
+
{
|
|
29518
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
29519
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CLOSE_PENDING);
|
|
29520
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_CLOSE_PENDING));
|
|
29521
|
+
actions && actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_CLOSE_PENDING));
|
|
29522
|
+
}
|
|
29523
|
+
await bt.strategyCoreService.closePending(false, symbol, {
|
|
29524
|
+
strategyName: context.strategyName,
|
|
29525
|
+
exchangeName: context.exchangeName,
|
|
29526
|
+
frameName: "",
|
|
29527
|
+
}, closeId);
|
|
29528
|
+
};
|
|
29249
29529
|
/**
|
|
29250
29530
|
* Executes partial close at profit level (moving toward TP).
|
|
29251
29531
|
*
|
|
@@ -30162,7 +30442,7 @@ class WalkerInstance {
|
|
|
30162
30442
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
|
|
30163
30443
|
return () => {
|
|
30164
30444
|
for (const strategyName of walkerSchema.strategies) {
|
|
30165
|
-
bt.strategyCoreService.
|
|
30445
|
+
bt.strategyCoreService.stopStrategy(true, symbol, {
|
|
30166
30446
|
strategyName,
|
|
30167
30447
|
exchangeName: walkerSchema.exchangeName,
|
|
30168
30448
|
frameName: walkerSchema.frameName
|
|
@@ -30318,7 +30598,7 @@ class WalkerUtils {
|
|
|
30318
30598
|
}
|
|
30319
30599
|
for (const strategyName of walkerSchema.strategies) {
|
|
30320
30600
|
await walkerStopSubject.next({ symbol, strategyName, walkerName: context.walkerName });
|
|
30321
|
-
await bt.strategyCoreService.
|
|
30601
|
+
await bt.strategyCoreService.stopStrategy(true, symbol, {
|
|
30322
30602
|
strategyName,
|
|
30323
30603
|
exchangeName: walkerSchema.exchangeName,
|
|
30324
30604
|
frameName: walkerSchema.frameName
|
|
@@ -32739,7 +33019,8 @@ exports.addSizingSchema = addSizingSchema;
|
|
|
32739
33019
|
exports.addStrategySchema = addStrategySchema;
|
|
32740
33020
|
exports.addWalkerSchema = addWalkerSchema;
|
|
32741
33021
|
exports.commitBreakeven = commitBreakeven;
|
|
32742
|
-
exports.
|
|
33022
|
+
exports.commitCancelScheduled = commitCancelScheduled;
|
|
33023
|
+
exports.commitClosePending = commitClosePending;
|
|
32743
33024
|
exports.commitPartialLoss = commitPartialLoss;
|
|
32744
33025
|
exports.commitPartialProfit = commitPartialProfit;
|
|
32745
33026
|
exports.commitSignalPromptHistory = commitSignalPromptHistory;
|
|
@@ -32827,5 +33108,5 @@ exports.set = set;
|
|
|
32827
33108
|
exports.setColumns = setColumns;
|
|
32828
33109
|
exports.setConfig = setConfig;
|
|
32829
33110
|
exports.setLogger = setLogger;
|
|
32830
|
-
exports.
|
|
33111
|
+
exports.stopStrategy = stopStrategy;
|
|
32831
33112
|
exports.validate = validate;
|