backtest-kit 5.6.2 → 5.6.4
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 +208 -0
- package/build/index.mjs +208 -0
- package/package.json +1 -1
- package/types.d.ts +120 -1
package/build/index.cjs
CHANGED
|
@@ -6475,6 +6475,18 @@ class ClientStrategy {
|
|
|
6475
6475
|
});
|
|
6476
6476
|
return this._pendingSignal !== null;
|
|
6477
6477
|
}
|
|
6478
|
+
/**
|
|
6479
|
+
* Checks if there is a scheduled signal.
|
|
6480
|
+
*
|
|
6481
|
+
* @param symbol - Trading symbol to check for scheduled signal
|
|
6482
|
+
* @returns Promise resolving to true if a scheduled signal exists, false otherwise
|
|
6483
|
+
*/
|
|
6484
|
+
async hasScheduledSignal(symbol) {
|
|
6485
|
+
this.params.logger.debug("ClientStrategy hasScheduledSignal", {
|
|
6486
|
+
symbol,
|
|
6487
|
+
});
|
|
6488
|
+
return this._scheduledSignal !== null;
|
|
6489
|
+
}
|
|
6478
6490
|
/**
|
|
6479
6491
|
* Updates pending signal and persists to disk in live mode.
|
|
6480
6492
|
*
|
|
@@ -10034,6 +10046,22 @@ class StrategyConnectionService {
|
|
|
10034
10046
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
10035
10047
|
return await strategy.hasPendingSignal(symbol);
|
|
10036
10048
|
};
|
|
10049
|
+
/**
|
|
10050
|
+
* Checks if there is an active scheduled signal for the strategy.
|
|
10051
|
+
* Delegates to ClientStrategy.hasScheduledSignal() which checks if there is a waiting position signal
|
|
10052
|
+
* @param backtest - Whether running in backtest mode
|
|
10053
|
+
* @param symbol - Trading pair symbol
|
|
10054
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
10055
|
+
* @returns Promise resolving to true if there is a waiting scheduled signal, false otherwise
|
|
10056
|
+
*/
|
|
10057
|
+
this.hasScheduledSignal = async (backtest, symbol, context) => {
|
|
10058
|
+
this.loggerService.log("strategyConnectionService hasScheduledSignal", {
|
|
10059
|
+
symbol,
|
|
10060
|
+
context,
|
|
10061
|
+
});
|
|
10062
|
+
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
10063
|
+
return await strategy.hasScheduledSignal(symbol);
|
|
10064
|
+
};
|
|
10037
10065
|
/**
|
|
10038
10066
|
* Returns the original estimated duration for the current pending signal.
|
|
10039
10067
|
*
|
|
@@ -14385,6 +14413,24 @@ class StrategyCoreService {
|
|
|
14385
14413
|
await this.validate(context);
|
|
14386
14414
|
return await this.strategyConnectionService.hasPendingSignal(backtest, symbol, context);
|
|
14387
14415
|
};
|
|
14416
|
+
/**
|
|
14417
|
+
* Checks if there is a waiting scheduled signal for the symbol.
|
|
14418
|
+
* Validates strategy existence and delegates to connection service
|
|
14419
|
+
* to check if a scheduled signal exists for the symbol.
|
|
14420
|
+
* Does not require execution context as this is a state query operation.
|
|
14421
|
+
* @param backtest - Whether running in backtest mode
|
|
14422
|
+
* @param symbol - Trading pair symbol
|
|
14423
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
14424
|
+
* @returns Promise<boolean> - true if scheduled signal exists, false otherwise
|
|
14425
|
+
*/
|
|
14426
|
+
this.hasScheduledSignal = async (backtest, symbol, context) => {
|
|
14427
|
+
this.loggerService.log("strategyCoreService hasScheduledSignal", {
|
|
14428
|
+
symbol,
|
|
14429
|
+
context,
|
|
14430
|
+
});
|
|
14431
|
+
await this.validate(context);
|
|
14432
|
+
return await this.strategyConnectionService.hasScheduledSignal(backtest, symbol, context);
|
|
14433
|
+
};
|
|
14388
14434
|
/**
|
|
14389
14435
|
* Returns the original estimated duration for the current pending signal.
|
|
14390
14436
|
*
|
|
@@ -36018,6 +36064,13 @@ function listenStrategyCommitOnce(filterFn, fn) {
|
|
|
36018
36064
|
*/
|
|
36019
36065
|
function listenSync(fn) {
|
|
36020
36066
|
bt.loggerService.log(LISTEN_SYNC_METHOD_NAME);
|
|
36067
|
+
{
|
|
36068
|
+
console.error("listenSync is unwanted cause exchange integration should be implemented in Broker.useBrokerAdapter as an infrastructure domain layer");
|
|
36069
|
+
console.error("If you need to implement custom logic on signal open/close, please use signal(), signalBacktest(), signalLive() in addActionSchema handler");
|
|
36070
|
+
console.error("If listenSync throws the exchange will not execute the order!");
|
|
36071
|
+
console.error("");
|
|
36072
|
+
console.error("You have been warned!");
|
|
36073
|
+
}
|
|
36021
36074
|
return syncSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
36022
36075
|
}
|
|
36023
36076
|
/**
|
|
@@ -36030,6 +36083,13 @@ function listenSync(fn) {
|
|
|
36030
36083
|
*/
|
|
36031
36084
|
function listenSyncOnce(filterFn, fn) {
|
|
36032
36085
|
bt.loggerService.log(LISTEN_SYNC_ONCE_METHOD_NAME);
|
|
36086
|
+
{
|
|
36087
|
+
console.error("listenSyncOnce is unwanted cause exchange integration should be implemented in Broker.useBrokerAdapter as an infrastructure domain layer");
|
|
36088
|
+
console.error("If you need to implement custom logic on signal open/close, please use signal(), signalBacktest(), signalLive() in addActionSchema handler");
|
|
36089
|
+
console.error("If listenSyncOnce throws the exchange WILL EXECUTE the order!");
|
|
36090
|
+
console.error("");
|
|
36091
|
+
console.error("You have been warned!");
|
|
36092
|
+
}
|
|
36033
36093
|
return syncSubject.filter(filterFn).once(fn);
|
|
36034
36094
|
}
|
|
36035
36095
|
/**
|
|
@@ -36104,6 +36164,8 @@ const BACKTEST_METHOD_NAME_TRAILING_PROFIT_COST = "BacktestUtils.commitTrailingT
|
|
|
36104
36164
|
const BACKTEST_METHOD_NAME_ACTIVATE_SCHEDULED = "Backtest.commitActivateScheduled";
|
|
36105
36165
|
const BACKTEST_METHOD_NAME_AVERAGE_BUY = "Backtest.commitAverageBuy";
|
|
36106
36166
|
const BACKTEST_METHOD_NAME_GET_DATA = "BacktestUtils.getData";
|
|
36167
|
+
const BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "BacktestUtils.hasNoPendingSignal";
|
|
36168
|
+
const BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "BacktestUtils.hasNoScheduledSignal";
|
|
36107
36169
|
/**
|
|
36108
36170
|
* Internal task function that runs backtest and handles completion.
|
|
36109
36171
|
* Consumes backtest results and updates instance state flags.
|
|
@@ -36607,6 +36669,74 @@ class BacktestUtils {
|
|
|
36607
36669
|
}
|
|
36608
36670
|
return await bt.strategyCoreService.getScheduledSignal(true, symbol, currentPrice, context);
|
|
36609
36671
|
};
|
|
36672
|
+
/**
|
|
36673
|
+
* Returns true if there is NO active pending signal for the given symbol.
|
|
36674
|
+
*
|
|
36675
|
+
* Inverse of strategyCoreService.hasPendingSignal. Use to guard signal generation logic.
|
|
36676
|
+
*
|
|
36677
|
+
* @param symbol - Trading pair symbol
|
|
36678
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
36679
|
+
* @returns Promise<boolean> - true if no pending signal exists, false if one does
|
|
36680
|
+
*
|
|
36681
|
+
* @example
|
|
36682
|
+
* ```typescript
|
|
36683
|
+
* if (await Backtest.hasNoPendingSignal("BTCUSDT", { strategyName, exchangeName, frameName })) {
|
|
36684
|
+
* // safe to open a new position
|
|
36685
|
+
* }
|
|
36686
|
+
* ```
|
|
36687
|
+
*/
|
|
36688
|
+
this.hasNoPendingSignal = async (symbol, context) => {
|
|
36689
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL, {
|
|
36690
|
+
symbol,
|
|
36691
|
+
context,
|
|
36692
|
+
});
|
|
36693
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
36694
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
36695
|
+
{
|
|
36696
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
36697
|
+
riskName &&
|
|
36698
|
+
bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
36699
|
+
riskList &&
|
|
36700
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL));
|
|
36701
|
+
actions &&
|
|
36702
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL));
|
|
36703
|
+
}
|
|
36704
|
+
return await functoolsKit.not(bt.strategyCoreService.hasPendingSignal(true, symbol, context));
|
|
36705
|
+
};
|
|
36706
|
+
/**
|
|
36707
|
+
* Returns true if there is NO active scheduled signal for the given symbol.
|
|
36708
|
+
*
|
|
36709
|
+
* Inverse of strategyCoreService.hasScheduledSignal. Use to guard signal generation logic.
|
|
36710
|
+
*
|
|
36711
|
+
* @param symbol - Trading pair symbol
|
|
36712
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
36713
|
+
* @returns Promise<boolean> - true if no scheduled signal exists, false if one does
|
|
36714
|
+
*
|
|
36715
|
+
* @example
|
|
36716
|
+
* ```typescript
|
|
36717
|
+
* if (await Backtest.hasNoScheduledSignal("BTCUSDT", { strategyName, exchangeName, frameName })) {
|
|
36718
|
+
* // safe to schedule a new signal
|
|
36719
|
+
* }
|
|
36720
|
+
* ```
|
|
36721
|
+
*/
|
|
36722
|
+
this.hasNoScheduledSignal = async (symbol, context) => {
|
|
36723
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL, {
|
|
36724
|
+
symbol,
|
|
36725
|
+
context,
|
|
36726
|
+
});
|
|
36727
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
36728
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
36729
|
+
{
|
|
36730
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
36731
|
+
riskName &&
|
|
36732
|
+
bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
36733
|
+
riskList &&
|
|
36734
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL));
|
|
36735
|
+
actions &&
|
|
36736
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL));
|
|
36737
|
+
}
|
|
36738
|
+
return await functoolsKit.not(bt.strategyCoreService.hasScheduledSignal(true, symbol, context));
|
|
36739
|
+
};
|
|
36610
36740
|
/**
|
|
36611
36741
|
* Checks if breakeven threshold has been reached for the current pending signal.
|
|
36612
36742
|
*
|
|
@@ -38252,6 +38382,8 @@ const LIVE_METHOD_NAME_TRAILING_STOP_COST = "LiveUtils.commitTrailingStopCost";
|
|
|
38252
38382
|
const LIVE_METHOD_NAME_TRAILING_PROFIT_COST = "LiveUtils.commitTrailingTakeCost";
|
|
38253
38383
|
const LIVE_METHOD_NAME_ACTIVATE_SCHEDULED = "Live.commitActivateScheduled";
|
|
38254
38384
|
const LIVE_METHOD_NAME_AVERAGE_BUY = "Live.commitAverageBuy";
|
|
38385
|
+
const LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "LiveUtils.hasNoPendingSignal";
|
|
38386
|
+
const LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "LiveUtils.hasNoScheduledSignal";
|
|
38255
38387
|
/**
|
|
38256
38388
|
* Internal task function that runs live trading and handles completion.
|
|
38257
38389
|
* Consumes live trading results and updates instance state flags.
|
|
@@ -38784,6 +38916,82 @@ class LiveUtils {
|
|
|
38784
38916
|
frameName: "",
|
|
38785
38917
|
});
|
|
38786
38918
|
};
|
|
38919
|
+
/**
|
|
38920
|
+
* Returns true if there is NO active pending signal for the given symbol.
|
|
38921
|
+
*
|
|
38922
|
+
* Inverse of strategyCoreService.hasPendingSignal. Use to guard signal generation logic.
|
|
38923
|
+
*
|
|
38924
|
+
* @param symbol - Trading pair symbol
|
|
38925
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
38926
|
+
* @returns Promise<boolean> - true if no pending signal exists, false if one does
|
|
38927
|
+
*
|
|
38928
|
+
* @example
|
|
38929
|
+
* ```typescript
|
|
38930
|
+
* if (await Live.hasNoPendingSignal("BTCUSDT", { strategyName, exchangeName })) {
|
|
38931
|
+
* // safe to open a new position
|
|
38932
|
+
* }
|
|
38933
|
+
* ```
|
|
38934
|
+
*/
|
|
38935
|
+
this.hasNoPendingSignal = async (symbol, context) => {
|
|
38936
|
+
bt.loggerService.info(LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL, {
|
|
38937
|
+
symbol,
|
|
38938
|
+
context,
|
|
38939
|
+
});
|
|
38940
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
38941
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
38942
|
+
{
|
|
38943
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
38944
|
+
riskName &&
|
|
38945
|
+
bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
38946
|
+
riskList &&
|
|
38947
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL));
|
|
38948
|
+
actions &&
|
|
38949
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL));
|
|
38950
|
+
}
|
|
38951
|
+
return await functoolsKit.not(bt.strategyCoreService.hasPendingSignal(false, symbol, {
|
|
38952
|
+
strategyName: context.strategyName,
|
|
38953
|
+
exchangeName: context.exchangeName,
|
|
38954
|
+
frameName: "",
|
|
38955
|
+
}));
|
|
38956
|
+
};
|
|
38957
|
+
/**
|
|
38958
|
+
* Returns true if there is NO active scheduled signal for the given symbol.
|
|
38959
|
+
*
|
|
38960
|
+
* Inverse of strategyCoreService.hasScheduledSignal. Use to guard signal generation logic.
|
|
38961
|
+
*
|
|
38962
|
+
* @param symbol - Trading pair symbol
|
|
38963
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
38964
|
+
* @returns Promise<boolean> - true if no scheduled signal exists, false if one does
|
|
38965
|
+
*
|
|
38966
|
+
* @example
|
|
38967
|
+
* ```typescript
|
|
38968
|
+
* if (await Live.hasNoScheduledSignal("BTCUSDT", { strategyName, exchangeName })) {
|
|
38969
|
+
* // safe to schedule a new signal
|
|
38970
|
+
* }
|
|
38971
|
+
* ```
|
|
38972
|
+
*/
|
|
38973
|
+
this.hasNoScheduledSignal = async (symbol, context) => {
|
|
38974
|
+
bt.loggerService.info(LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL, {
|
|
38975
|
+
symbol,
|
|
38976
|
+
context,
|
|
38977
|
+
});
|
|
38978
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
38979
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
38980
|
+
{
|
|
38981
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
38982
|
+
riskName &&
|
|
38983
|
+
bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
38984
|
+
riskList &&
|
|
38985
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL));
|
|
38986
|
+
actions &&
|
|
38987
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL));
|
|
38988
|
+
}
|
|
38989
|
+
return await functoolsKit.not(bt.strategyCoreService.hasScheduledSignal(false, symbol, {
|
|
38990
|
+
strategyName: context.strategyName,
|
|
38991
|
+
exchangeName: context.exchangeName,
|
|
38992
|
+
frameName: "",
|
|
38993
|
+
}));
|
|
38994
|
+
};
|
|
38787
38995
|
/**
|
|
38788
38996
|
* Checks if breakeven threshold has been reached for the current pending signal.
|
|
38789
38997
|
*
|
package/build/index.mjs
CHANGED
|
@@ -6455,6 +6455,18 @@ class ClientStrategy {
|
|
|
6455
6455
|
});
|
|
6456
6456
|
return this._pendingSignal !== null;
|
|
6457
6457
|
}
|
|
6458
|
+
/**
|
|
6459
|
+
* Checks if there is a scheduled signal.
|
|
6460
|
+
*
|
|
6461
|
+
* @param symbol - Trading symbol to check for scheduled signal
|
|
6462
|
+
* @returns Promise resolving to true if a scheduled signal exists, false otherwise
|
|
6463
|
+
*/
|
|
6464
|
+
async hasScheduledSignal(symbol) {
|
|
6465
|
+
this.params.logger.debug("ClientStrategy hasScheduledSignal", {
|
|
6466
|
+
symbol,
|
|
6467
|
+
});
|
|
6468
|
+
return this._scheduledSignal !== null;
|
|
6469
|
+
}
|
|
6458
6470
|
/**
|
|
6459
6471
|
* Updates pending signal and persists to disk in live mode.
|
|
6460
6472
|
*
|
|
@@ -10014,6 +10026,22 @@ class StrategyConnectionService {
|
|
|
10014
10026
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
10015
10027
|
return await strategy.hasPendingSignal(symbol);
|
|
10016
10028
|
};
|
|
10029
|
+
/**
|
|
10030
|
+
* Checks if there is an active scheduled signal for the strategy.
|
|
10031
|
+
* Delegates to ClientStrategy.hasScheduledSignal() which checks if there is a waiting position signal
|
|
10032
|
+
* @param backtest - Whether running in backtest mode
|
|
10033
|
+
* @param symbol - Trading pair symbol
|
|
10034
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
10035
|
+
* @returns Promise resolving to true if there is a waiting scheduled signal, false otherwise
|
|
10036
|
+
*/
|
|
10037
|
+
this.hasScheduledSignal = async (backtest, symbol, context) => {
|
|
10038
|
+
this.loggerService.log("strategyConnectionService hasScheduledSignal", {
|
|
10039
|
+
symbol,
|
|
10040
|
+
context,
|
|
10041
|
+
});
|
|
10042
|
+
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
10043
|
+
return await strategy.hasScheduledSignal(symbol);
|
|
10044
|
+
};
|
|
10017
10045
|
/**
|
|
10018
10046
|
* Returns the original estimated duration for the current pending signal.
|
|
10019
10047
|
*
|
|
@@ -14365,6 +14393,24 @@ class StrategyCoreService {
|
|
|
14365
14393
|
await this.validate(context);
|
|
14366
14394
|
return await this.strategyConnectionService.hasPendingSignal(backtest, symbol, context);
|
|
14367
14395
|
};
|
|
14396
|
+
/**
|
|
14397
|
+
* Checks if there is a waiting scheduled signal for the symbol.
|
|
14398
|
+
* Validates strategy existence and delegates to connection service
|
|
14399
|
+
* to check if a scheduled signal exists for the symbol.
|
|
14400
|
+
* Does not require execution context as this is a state query operation.
|
|
14401
|
+
* @param backtest - Whether running in backtest mode
|
|
14402
|
+
* @param symbol - Trading pair symbol
|
|
14403
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
14404
|
+
* @returns Promise<boolean> - true if scheduled signal exists, false otherwise
|
|
14405
|
+
*/
|
|
14406
|
+
this.hasScheduledSignal = async (backtest, symbol, context) => {
|
|
14407
|
+
this.loggerService.log("strategyCoreService hasScheduledSignal", {
|
|
14408
|
+
symbol,
|
|
14409
|
+
context,
|
|
14410
|
+
});
|
|
14411
|
+
await this.validate(context);
|
|
14412
|
+
return await this.strategyConnectionService.hasScheduledSignal(backtest, symbol, context);
|
|
14413
|
+
};
|
|
14368
14414
|
/**
|
|
14369
14415
|
* Returns the original estimated duration for the current pending signal.
|
|
14370
14416
|
*
|
|
@@ -35998,6 +36044,13 @@ function listenStrategyCommitOnce(filterFn, fn) {
|
|
|
35998
36044
|
*/
|
|
35999
36045
|
function listenSync(fn) {
|
|
36000
36046
|
bt.loggerService.log(LISTEN_SYNC_METHOD_NAME);
|
|
36047
|
+
{
|
|
36048
|
+
console.error("listenSync is unwanted cause exchange integration should be implemented in Broker.useBrokerAdapter as an infrastructure domain layer");
|
|
36049
|
+
console.error("If you need to implement custom logic on signal open/close, please use signal(), signalBacktest(), signalLive() in addActionSchema handler");
|
|
36050
|
+
console.error("If listenSync throws the exchange will not execute the order!");
|
|
36051
|
+
console.error("");
|
|
36052
|
+
console.error("You have been warned!");
|
|
36053
|
+
}
|
|
36001
36054
|
return syncSubject.subscribe(queued(async (event) => fn(event)));
|
|
36002
36055
|
}
|
|
36003
36056
|
/**
|
|
@@ -36010,6 +36063,13 @@ function listenSync(fn) {
|
|
|
36010
36063
|
*/
|
|
36011
36064
|
function listenSyncOnce(filterFn, fn) {
|
|
36012
36065
|
bt.loggerService.log(LISTEN_SYNC_ONCE_METHOD_NAME);
|
|
36066
|
+
{
|
|
36067
|
+
console.error("listenSyncOnce is unwanted cause exchange integration should be implemented in Broker.useBrokerAdapter as an infrastructure domain layer");
|
|
36068
|
+
console.error("If you need to implement custom logic on signal open/close, please use signal(), signalBacktest(), signalLive() in addActionSchema handler");
|
|
36069
|
+
console.error("If listenSyncOnce throws the exchange WILL EXECUTE the order!");
|
|
36070
|
+
console.error("");
|
|
36071
|
+
console.error("You have been warned!");
|
|
36072
|
+
}
|
|
36013
36073
|
return syncSubject.filter(filterFn).once(fn);
|
|
36014
36074
|
}
|
|
36015
36075
|
/**
|
|
@@ -36084,6 +36144,8 @@ const BACKTEST_METHOD_NAME_TRAILING_PROFIT_COST = "BacktestUtils.commitTrailingT
|
|
|
36084
36144
|
const BACKTEST_METHOD_NAME_ACTIVATE_SCHEDULED = "Backtest.commitActivateScheduled";
|
|
36085
36145
|
const BACKTEST_METHOD_NAME_AVERAGE_BUY = "Backtest.commitAverageBuy";
|
|
36086
36146
|
const BACKTEST_METHOD_NAME_GET_DATA = "BacktestUtils.getData";
|
|
36147
|
+
const BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "BacktestUtils.hasNoPendingSignal";
|
|
36148
|
+
const BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "BacktestUtils.hasNoScheduledSignal";
|
|
36087
36149
|
/**
|
|
36088
36150
|
* Internal task function that runs backtest and handles completion.
|
|
36089
36151
|
* Consumes backtest results and updates instance state flags.
|
|
@@ -36587,6 +36649,74 @@ class BacktestUtils {
|
|
|
36587
36649
|
}
|
|
36588
36650
|
return await bt.strategyCoreService.getScheduledSignal(true, symbol, currentPrice, context);
|
|
36589
36651
|
};
|
|
36652
|
+
/**
|
|
36653
|
+
* Returns true if there is NO active pending signal for the given symbol.
|
|
36654
|
+
*
|
|
36655
|
+
* Inverse of strategyCoreService.hasPendingSignal. Use to guard signal generation logic.
|
|
36656
|
+
*
|
|
36657
|
+
* @param symbol - Trading pair symbol
|
|
36658
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
36659
|
+
* @returns Promise<boolean> - true if no pending signal exists, false if one does
|
|
36660
|
+
*
|
|
36661
|
+
* @example
|
|
36662
|
+
* ```typescript
|
|
36663
|
+
* if (await Backtest.hasNoPendingSignal("BTCUSDT", { strategyName, exchangeName, frameName })) {
|
|
36664
|
+
* // safe to open a new position
|
|
36665
|
+
* }
|
|
36666
|
+
* ```
|
|
36667
|
+
*/
|
|
36668
|
+
this.hasNoPendingSignal = async (symbol, context) => {
|
|
36669
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL, {
|
|
36670
|
+
symbol,
|
|
36671
|
+
context,
|
|
36672
|
+
});
|
|
36673
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
36674
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
36675
|
+
{
|
|
36676
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
36677
|
+
riskName &&
|
|
36678
|
+
bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
36679
|
+
riskList &&
|
|
36680
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL));
|
|
36681
|
+
actions &&
|
|
36682
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL));
|
|
36683
|
+
}
|
|
36684
|
+
return await not(bt.strategyCoreService.hasPendingSignal(true, symbol, context));
|
|
36685
|
+
};
|
|
36686
|
+
/**
|
|
36687
|
+
* Returns true if there is NO active scheduled signal for the given symbol.
|
|
36688
|
+
*
|
|
36689
|
+
* Inverse of strategyCoreService.hasScheduledSignal. Use to guard signal generation logic.
|
|
36690
|
+
*
|
|
36691
|
+
* @param symbol - Trading pair symbol
|
|
36692
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
36693
|
+
* @returns Promise<boolean> - true if no scheduled signal exists, false if one does
|
|
36694
|
+
*
|
|
36695
|
+
* @example
|
|
36696
|
+
* ```typescript
|
|
36697
|
+
* if (await Backtest.hasNoScheduledSignal("BTCUSDT", { strategyName, exchangeName, frameName })) {
|
|
36698
|
+
* // safe to schedule a new signal
|
|
36699
|
+
* }
|
|
36700
|
+
* ```
|
|
36701
|
+
*/
|
|
36702
|
+
this.hasNoScheduledSignal = async (symbol, context) => {
|
|
36703
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL, {
|
|
36704
|
+
symbol,
|
|
36705
|
+
context,
|
|
36706
|
+
});
|
|
36707
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
36708
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
36709
|
+
{
|
|
36710
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
36711
|
+
riskName &&
|
|
36712
|
+
bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
36713
|
+
riskList &&
|
|
36714
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL));
|
|
36715
|
+
actions &&
|
|
36716
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL));
|
|
36717
|
+
}
|
|
36718
|
+
return await not(bt.strategyCoreService.hasScheduledSignal(true, symbol, context));
|
|
36719
|
+
};
|
|
36590
36720
|
/**
|
|
36591
36721
|
* Checks if breakeven threshold has been reached for the current pending signal.
|
|
36592
36722
|
*
|
|
@@ -38232,6 +38362,8 @@ const LIVE_METHOD_NAME_TRAILING_STOP_COST = "LiveUtils.commitTrailingStopCost";
|
|
|
38232
38362
|
const LIVE_METHOD_NAME_TRAILING_PROFIT_COST = "LiveUtils.commitTrailingTakeCost";
|
|
38233
38363
|
const LIVE_METHOD_NAME_ACTIVATE_SCHEDULED = "Live.commitActivateScheduled";
|
|
38234
38364
|
const LIVE_METHOD_NAME_AVERAGE_BUY = "Live.commitAverageBuy";
|
|
38365
|
+
const LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "LiveUtils.hasNoPendingSignal";
|
|
38366
|
+
const LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "LiveUtils.hasNoScheduledSignal";
|
|
38235
38367
|
/**
|
|
38236
38368
|
* Internal task function that runs live trading and handles completion.
|
|
38237
38369
|
* Consumes live trading results and updates instance state flags.
|
|
@@ -38764,6 +38896,82 @@ class LiveUtils {
|
|
|
38764
38896
|
frameName: "",
|
|
38765
38897
|
});
|
|
38766
38898
|
};
|
|
38899
|
+
/**
|
|
38900
|
+
* Returns true if there is NO active pending signal for the given symbol.
|
|
38901
|
+
*
|
|
38902
|
+
* Inverse of strategyCoreService.hasPendingSignal. Use to guard signal generation logic.
|
|
38903
|
+
*
|
|
38904
|
+
* @param symbol - Trading pair symbol
|
|
38905
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
38906
|
+
* @returns Promise<boolean> - true if no pending signal exists, false if one does
|
|
38907
|
+
*
|
|
38908
|
+
* @example
|
|
38909
|
+
* ```typescript
|
|
38910
|
+
* if (await Live.hasNoPendingSignal("BTCUSDT", { strategyName, exchangeName })) {
|
|
38911
|
+
* // safe to open a new position
|
|
38912
|
+
* }
|
|
38913
|
+
* ```
|
|
38914
|
+
*/
|
|
38915
|
+
this.hasNoPendingSignal = async (symbol, context) => {
|
|
38916
|
+
bt.loggerService.info(LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL, {
|
|
38917
|
+
symbol,
|
|
38918
|
+
context,
|
|
38919
|
+
});
|
|
38920
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
38921
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
38922
|
+
{
|
|
38923
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
38924
|
+
riskName &&
|
|
38925
|
+
bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL);
|
|
38926
|
+
riskList &&
|
|
38927
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL));
|
|
38928
|
+
actions &&
|
|
38929
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL));
|
|
38930
|
+
}
|
|
38931
|
+
return await not(bt.strategyCoreService.hasPendingSignal(false, symbol, {
|
|
38932
|
+
strategyName: context.strategyName,
|
|
38933
|
+
exchangeName: context.exchangeName,
|
|
38934
|
+
frameName: "",
|
|
38935
|
+
}));
|
|
38936
|
+
};
|
|
38937
|
+
/**
|
|
38938
|
+
* Returns true if there is NO active scheduled signal for the given symbol.
|
|
38939
|
+
*
|
|
38940
|
+
* Inverse of strategyCoreService.hasScheduledSignal. Use to guard signal generation logic.
|
|
38941
|
+
*
|
|
38942
|
+
* @param symbol - Trading pair symbol
|
|
38943
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
38944
|
+
* @returns Promise<boolean> - true if no scheduled signal exists, false if one does
|
|
38945
|
+
*
|
|
38946
|
+
* @example
|
|
38947
|
+
* ```typescript
|
|
38948
|
+
* if (await Live.hasNoScheduledSignal("BTCUSDT", { strategyName, exchangeName })) {
|
|
38949
|
+
* // safe to schedule a new signal
|
|
38950
|
+
* }
|
|
38951
|
+
* ```
|
|
38952
|
+
*/
|
|
38953
|
+
this.hasNoScheduledSignal = async (symbol, context) => {
|
|
38954
|
+
bt.loggerService.info(LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL, {
|
|
38955
|
+
symbol,
|
|
38956
|
+
context,
|
|
38957
|
+
});
|
|
38958
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
38959
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
38960
|
+
{
|
|
38961
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
38962
|
+
riskName &&
|
|
38963
|
+
bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL);
|
|
38964
|
+
riskList &&
|
|
38965
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL));
|
|
38966
|
+
actions &&
|
|
38967
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL));
|
|
38968
|
+
}
|
|
38969
|
+
return await not(bt.strategyCoreService.hasScheduledSignal(false, symbol, {
|
|
38970
|
+
strategyName: context.strategyName,
|
|
38971
|
+
exchangeName: context.exchangeName,
|
|
38972
|
+
frameName: "",
|
|
38973
|
+
}));
|
|
38974
|
+
};
|
|
38767
38975
|
/**
|
|
38768
38976
|
* Checks if breakeven threshold has been reached for the current pending signal.
|
|
38769
38977
|
*
|
package/package.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -1021,7 +1021,7 @@ interface ActivePingContract {
|
|
|
1021
1021
|
* Complete pending signal row data.
|
|
1022
1022
|
* Contains all signal information: id, position, priceOpen, priceTakeProfit, priceStopLoss, etc.
|
|
1023
1023
|
*/
|
|
1024
|
-
data:
|
|
1024
|
+
data: IPublicSignalRow;
|
|
1025
1025
|
/**
|
|
1026
1026
|
* Current market price of the symbol at the time of the ping.
|
|
1027
1027
|
* Useful for users to implement custom management logic based on price conditions.
|
|
@@ -3399,6 +3399,15 @@ interface IStrategy {
|
|
|
3399
3399
|
* @returns Promise resolving to true if pending signal exists, false otherwise
|
|
3400
3400
|
*/
|
|
3401
3401
|
hasPendingSignal: (symbol: string) => Promise<boolean>;
|
|
3402
|
+
/**
|
|
3403
|
+
* Checks if there is an active scheduled signal for the symbol.
|
|
3404
|
+
*
|
|
3405
|
+
* Used internally to determine if TP/SL monitoring should occur on tick.
|
|
3406
|
+
*
|
|
3407
|
+
* @param symbol - Trading pair symbol
|
|
3408
|
+
* @returns Promise resolving to true if scheduled signal exists, false otherwise
|
|
3409
|
+
*/
|
|
3410
|
+
hasScheduledSignal: (symbol: string) => Promise<boolean>;
|
|
3402
3411
|
/**
|
|
3403
3412
|
* Returns the original estimated duration for the current pending signal.
|
|
3404
3413
|
*
|
|
@@ -12295,6 +12304,48 @@ declare class BacktestUtils {
|
|
|
12295
12304
|
exchangeName: ExchangeName;
|
|
12296
12305
|
frameName: FrameName;
|
|
12297
12306
|
}) => Promise<IScheduledSignalRow>;
|
|
12307
|
+
/**
|
|
12308
|
+
* Returns true if there is NO active pending signal for the given symbol.
|
|
12309
|
+
*
|
|
12310
|
+
* Inverse of strategyCoreService.hasPendingSignal. Use to guard signal generation logic.
|
|
12311
|
+
*
|
|
12312
|
+
* @param symbol - Trading pair symbol
|
|
12313
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
12314
|
+
* @returns Promise<boolean> - true if no pending signal exists, false if one does
|
|
12315
|
+
*
|
|
12316
|
+
* @example
|
|
12317
|
+
* ```typescript
|
|
12318
|
+
* if (await Backtest.hasNoPendingSignal("BTCUSDT", { strategyName, exchangeName, frameName })) {
|
|
12319
|
+
* // safe to open a new position
|
|
12320
|
+
* }
|
|
12321
|
+
* ```
|
|
12322
|
+
*/
|
|
12323
|
+
hasNoPendingSignal: (symbol: string, context: {
|
|
12324
|
+
strategyName: StrategyName;
|
|
12325
|
+
exchangeName: ExchangeName;
|
|
12326
|
+
frameName: FrameName;
|
|
12327
|
+
}) => Promise<boolean>;
|
|
12328
|
+
/**
|
|
12329
|
+
* Returns true if there is NO active scheduled signal for the given symbol.
|
|
12330
|
+
*
|
|
12331
|
+
* Inverse of strategyCoreService.hasScheduledSignal. Use to guard signal generation logic.
|
|
12332
|
+
*
|
|
12333
|
+
* @param symbol - Trading pair symbol
|
|
12334
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
12335
|
+
* @returns Promise<boolean> - true if no scheduled signal exists, false if one does
|
|
12336
|
+
*
|
|
12337
|
+
* @example
|
|
12338
|
+
* ```typescript
|
|
12339
|
+
* if (await Backtest.hasNoScheduledSignal("BTCUSDT", { strategyName, exchangeName, frameName })) {
|
|
12340
|
+
* // safe to schedule a new signal
|
|
12341
|
+
* }
|
|
12342
|
+
* ```
|
|
12343
|
+
*/
|
|
12344
|
+
hasNoScheduledSignal: (symbol: string, context: {
|
|
12345
|
+
strategyName: StrategyName;
|
|
12346
|
+
exchangeName: ExchangeName;
|
|
12347
|
+
frameName: FrameName;
|
|
12348
|
+
}) => Promise<boolean>;
|
|
12298
12349
|
/**
|
|
12299
12350
|
* Checks if breakeven threshold has been reached for the current pending signal.
|
|
12300
12351
|
*
|
|
@@ -13546,6 +13597,46 @@ declare class LiveUtils {
|
|
|
13546
13597
|
strategyName: StrategyName;
|
|
13547
13598
|
exchangeName: ExchangeName;
|
|
13548
13599
|
}) => Promise<IScheduledSignalRow>;
|
|
13600
|
+
/**
|
|
13601
|
+
* Returns true if there is NO active pending signal for the given symbol.
|
|
13602
|
+
*
|
|
13603
|
+
* Inverse of strategyCoreService.hasPendingSignal. Use to guard signal generation logic.
|
|
13604
|
+
*
|
|
13605
|
+
* @param symbol - Trading pair symbol
|
|
13606
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
13607
|
+
* @returns Promise<boolean> - true if no pending signal exists, false if one does
|
|
13608
|
+
*
|
|
13609
|
+
* @example
|
|
13610
|
+
* ```typescript
|
|
13611
|
+
* if (await Live.hasNoPendingSignal("BTCUSDT", { strategyName, exchangeName })) {
|
|
13612
|
+
* // safe to open a new position
|
|
13613
|
+
* }
|
|
13614
|
+
* ```
|
|
13615
|
+
*/
|
|
13616
|
+
hasNoPendingSignal: (symbol: string, context: {
|
|
13617
|
+
strategyName: StrategyName;
|
|
13618
|
+
exchangeName: ExchangeName;
|
|
13619
|
+
}) => Promise<boolean>;
|
|
13620
|
+
/**
|
|
13621
|
+
* Returns true if there is NO active scheduled signal for the given symbol.
|
|
13622
|
+
*
|
|
13623
|
+
* Inverse of strategyCoreService.hasScheduledSignal. Use to guard signal generation logic.
|
|
13624
|
+
*
|
|
13625
|
+
* @param symbol - Trading pair symbol
|
|
13626
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
13627
|
+
* @returns Promise<boolean> - true if no scheduled signal exists, false if one does
|
|
13628
|
+
*
|
|
13629
|
+
* @example
|
|
13630
|
+
* ```typescript
|
|
13631
|
+
* if (await Live.hasNoScheduledSignal("BTCUSDT", { strategyName, exchangeName })) {
|
|
13632
|
+
* // safe to schedule a new signal
|
|
13633
|
+
* }
|
|
13634
|
+
* ```
|
|
13635
|
+
*/
|
|
13636
|
+
hasNoScheduledSignal: (symbol: string, context: {
|
|
13637
|
+
strategyName: StrategyName;
|
|
13638
|
+
exchangeName: ExchangeName;
|
|
13639
|
+
}) => Promise<boolean>;
|
|
13549
13640
|
/**
|
|
13550
13641
|
* Checks if breakeven threshold has been reached for the current pending signal.
|
|
13551
13642
|
*
|
|
@@ -22432,6 +22523,19 @@ declare class StrategyConnectionService implements TStrategy$1 {
|
|
|
22432
22523
|
exchangeName: ExchangeName;
|
|
22433
22524
|
frameName: FrameName;
|
|
22434
22525
|
}) => Promise<boolean>;
|
|
22526
|
+
/**
|
|
22527
|
+
* Checks if there is an active scheduled signal for the strategy.
|
|
22528
|
+
* Delegates to ClientStrategy.hasScheduledSignal() which checks if there is a waiting position signal
|
|
22529
|
+
* @param backtest - Whether running in backtest mode
|
|
22530
|
+
* @param symbol - Trading pair symbol
|
|
22531
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
22532
|
+
* @returns Promise resolving to true if there is a waiting scheduled signal, false otherwise
|
|
22533
|
+
*/
|
|
22534
|
+
hasScheduledSignal: (backtest: boolean, symbol: string, context: {
|
|
22535
|
+
strategyName: StrategyName;
|
|
22536
|
+
exchangeName: ExchangeName;
|
|
22537
|
+
frameName: FrameName;
|
|
22538
|
+
}) => Promise<boolean>;
|
|
22435
22539
|
/**
|
|
22436
22540
|
* Returns the original estimated duration for the current pending signal.
|
|
22437
22541
|
*
|
|
@@ -24186,6 +24290,21 @@ declare class StrategyCoreService implements TStrategy {
|
|
|
24186
24290
|
exchangeName: ExchangeName;
|
|
24187
24291
|
frameName: FrameName;
|
|
24188
24292
|
}) => Promise<boolean>;
|
|
24293
|
+
/**
|
|
24294
|
+
* Checks if there is a waiting scheduled signal for the symbol.
|
|
24295
|
+
* Validates strategy existence and delegates to connection service
|
|
24296
|
+
* to check if a scheduled signal exists for the symbol.
|
|
24297
|
+
* Does not require execution context as this is a state query operation.
|
|
24298
|
+
* @param backtest - Whether running in backtest mode
|
|
24299
|
+
* @param symbol - Trading pair symbol
|
|
24300
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
24301
|
+
* @returns Promise<boolean> - true if scheduled signal exists, false otherwise
|
|
24302
|
+
*/
|
|
24303
|
+
hasScheduledSignal: (backtest: boolean, symbol: string, context: {
|
|
24304
|
+
strategyName: StrategyName;
|
|
24305
|
+
exchangeName: ExchangeName;
|
|
24306
|
+
frameName: FrameName;
|
|
24307
|
+
}) => Promise<boolean>;
|
|
24189
24308
|
/**
|
|
24190
24309
|
* Returns the original estimated duration for the current pending signal.
|
|
24191
24310
|
*
|