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.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.
|
|
4977
|
+
* await strategy.stopStrategy();
|
|
4910
4978
|
* // Existing signal will continue until natural close
|
|
4911
4979
|
* ```
|
|
4912
4980
|
*/
|
|
4913
|
-
async
|
|
4914
|
-
this.params.logger.debug("ClientStrategy
|
|
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.
|
|
5015
|
+
* await strategy.cancelScheduled("BTCUSDT", "my-strategy", false);
|
|
4948
5016
|
* // Strategy continues, can generate new signals
|
|
4949
5017
|
* ```
|
|
4950
5018
|
*/
|
|
4951
|
-
async
|
|
4952
|
-
this.params.logger.debug("ClientStrategy
|
|
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.
|
|
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.
|
|
6430
|
-
this.loggerService.log("strategyConnectionService
|
|
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.
|
|
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.
|
|
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.
|
|
6500
|
-
this.loggerService.log("strategyConnectionService
|
|
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.
|
|
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.
|
|
9694
|
-
this.loggerService.log("strategyCoreService
|
|
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.
|
|
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.
|
|
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.
|
|
9716
|
-
this.loggerService.log("strategyCoreService
|
|
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.
|
|
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
|
|
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 {
|
|
25191
|
+
* import { commitCancelScheduled } from "backtest-kit";
|
|
25032
25192
|
*
|
|
25033
25193
|
* // Cancel scheduled signal with custom ID
|
|
25034
|
-
* await
|
|
25194
|
+
* await commitCancelScheduled("BTCUSDT", "manual-cancel-001");
|
|
25035
25195
|
* ```
|
|
25036
25196
|
*/
|
|
25037
|
-
async function
|
|
25038
|
-
bt.loggerService.info(
|
|
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("
|
|
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("
|
|
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.
|
|
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
|
|
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
|
|
25320
|
-
bt.loggerService.info(
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
28254
|
-
bt.loggerService.info(
|
|
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,
|
|
28260
|
-
bt.exchangeValidationService.validate(context.exchangeName,
|
|
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,
|
|
28461
|
+
bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED);
|
|
28265
28462
|
riskList &&
|
|
28266
|
-
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName,
|
|
28463
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED));
|
|
28267
28464
|
actions &&
|
|
28268
|
-
actions.forEach((actionName) => bt.actionValidationService.validate(actionName,
|
|
28465
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_CANCEL_SCHEDULED));
|
|
28269
28466
|
}
|
|
28270
|
-
await bt.strategyCoreService.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
29209
|
-
bt.loggerService.info(
|
|
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,
|
|
29215
|
-
bt.exchangeValidationService.validate(context.exchangeName,
|
|
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,
|
|
29219
|
-
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName,
|
|
29220
|
-
actions && actions.forEach((actionName) => bt.actionValidationService.validate(actionName,
|
|
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.
|
|
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.
|
|
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.
|
|
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,
|
|
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 };
|