backtest-kit 6.15.0 → 7.0.0
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/README.md +4 -2
- package/build/index.cjs +422 -13
- package/build/index.mjs +420 -14
- package/package.json +2 -2
- package/types.d.ts +233 -7
package/build/index.cjs
CHANGED
|
@@ -734,6 +734,11 @@ const schedulePingSubject = new functoolsKit.Subject();
|
|
|
734
734
|
* Allows users to track active signal lifecycle and implement custom dynamic management logic.
|
|
735
735
|
*/
|
|
736
736
|
const activePingSubject = new functoolsKit.Subject();
|
|
737
|
+
/**
|
|
738
|
+
* Idle ping emitter for strategy idle state events.
|
|
739
|
+
* Emits every tick when there is no pending or scheduled signal being monitored.
|
|
740
|
+
*/
|
|
741
|
+
const idlePingSubject = new functoolsKit.Subject();
|
|
737
742
|
/**
|
|
738
743
|
* Strategy management signal emitter.
|
|
739
744
|
* Emits when strategy management actions are executed:
|
|
@@ -785,6 +790,7 @@ var emitters = /*#__PURE__*/Object.freeze({
|
|
|
785
790
|
errorEmitter: errorEmitter,
|
|
786
791
|
exitEmitter: exitEmitter,
|
|
787
792
|
highestProfitSubject: highestProfitSubject,
|
|
793
|
+
idlePingSubject: idlePingSubject,
|
|
788
794
|
maxDrawdownSubject: maxDrawdownSubject,
|
|
789
795
|
partialLossSubject: partialLossSubject,
|
|
790
796
|
partialProfitSubject: partialProfitSubject,
|
|
@@ -930,7 +936,6 @@ const INTERVAL_MINUTES$9 = {
|
|
|
930
936
|
"6h": 360,
|
|
931
937
|
"8h": 480,
|
|
932
938
|
"1d": 1440,
|
|
933
|
-
"1w": 10080,
|
|
934
939
|
};
|
|
935
940
|
const MS_PER_MINUTE$7 = 60000;
|
|
936
941
|
const PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_PERSIST_SIGNAL_ADAPTER = "PersistSignalUtils.usePersistSignalAdapter";
|
|
@@ -3110,7 +3115,6 @@ const INTERVAL_MINUTES$8 = {
|
|
|
3110
3115
|
"6h": 360,
|
|
3111
3116
|
"8h": 480,
|
|
3112
3117
|
"1d": 1440,
|
|
3113
|
-
"1w": 10080,
|
|
3114
3118
|
};
|
|
3115
3119
|
/**
|
|
3116
3120
|
* Aligns timestamp down to the nearest interval boundary.
|
|
@@ -6048,6 +6052,27 @@ const CALL_ACTIVE_PING_CALLBACKS_FN = functoolsKit.trycatch(beginTime(async (sel
|
|
|
6048
6052
|
errorEmitter.next(error);
|
|
6049
6053
|
},
|
|
6050
6054
|
});
|
|
6055
|
+
const CALL_IDLE_PING_CALLBACKS_FN = functoolsKit.trycatch(beginTime(async (self, symbol, timestamp, backtest, currentPrice) => {
|
|
6056
|
+
await ExecutionContextService.runInContext(async () => {
|
|
6057
|
+
// Call system onIdlePing callback (emits to idlePingSubject)
|
|
6058
|
+
await self.params.onIdlePing(self.params.execution.context.symbol, self.params.method.context.strategyName, self.params.method.context.exchangeName, currentPrice, self.params.execution.context.backtest, timestamp);
|
|
6059
|
+
}, {
|
|
6060
|
+
when: new Date(timestamp),
|
|
6061
|
+
symbol: symbol,
|
|
6062
|
+
backtest: backtest,
|
|
6063
|
+
});
|
|
6064
|
+
}), {
|
|
6065
|
+
fallback: (error, self) => {
|
|
6066
|
+
const message = "ClientStrategy CALL_IDLE_PING_CALLBACKS_FN thrown";
|
|
6067
|
+
const payload = {
|
|
6068
|
+
error: functoolsKit.errorData(error),
|
|
6069
|
+
message: functoolsKit.getErrorMessage(error),
|
|
6070
|
+
};
|
|
6071
|
+
self.params.logger.warn(message, payload);
|
|
6072
|
+
console.warn(message, payload);
|
|
6073
|
+
errorEmitter.next(error);
|
|
6074
|
+
},
|
|
6075
|
+
});
|
|
6051
6076
|
const CALL_ACTIVE_CALLBACKS_FN = functoolsKit.trycatch(beginTime(async (self, symbol, signal, currentPrice, timestamp, backtest) => {
|
|
6052
6077
|
await ExecutionContextService.runInContext(async () => {
|
|
6053
6078
|
if (self.params.callbacks?.onActive) {
|
|
@@ -6703,6 +6728,7 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice, backt
|
|
|
6703
6728
|
};
|
|
6704
6729
|
const RETURN_IDLE_FN = async (self, currentPrice) => {
|
|
6705
6730
|
const currentTime = self.params.execution.context.when.getTime();
|
|
6731
|
+
await CALL_IDLE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, currentTime, self.params.execution.context.backtest, currentPrice);
|
|
6706
6732
|
await CALL_IDLE_CALLBACKS_FN(self, self.params.execution.context.symbol, currentPrice, currentTime, self.params.execution.context.backtest);
|
|
6707
6733
|
const result = {
|
|
6708
6734
|
action: "idle",
|
|
@@ -10375,11 +10401,44 @@ const CREATE_COMMIT_SCHEDULE_PING_FN = (self) => functoolsKit.trycatch(async (sy
|
|
|
10375
10401
|
},
|
|
10376
10402
|
defaultValue: null,
|
|
10377
10403
|
});
|
|
10404
|
+
/**
|
|
10405
|
+
* Creates a callback function for emitting idle ping events.
|
|
10406
|
+
*
|
|
10407
|
+
* Called by ClientStrategy when no active or scheduled signals are present.
|
|
10408
|
+
*
|
|
10409
|
+
* @param self - Reference to StrategyConnectionService instance
|
|
10410
|
+
* @returns Callback function for idle ping events
|
|
10411
|
+
*/
|
|
10412
|
+
const CREATE_COMMIT_IDLE_PING_FN = (self) => functoolsKit.trycatch(async (symbol, strategyName, exchangeName, currentPrice, backtest, timestamp) => {
|
|
10413
|
+
const frameName = self.methodContextService.context.frameName;
|
|
10414
|
+
const event = {
|
|
10415
|
+
symbol,
|
|
10416
|
+
strategyName,
|
|
10417
|
+
exchangeName,
|
|
10418
|
+
frameName,
|
|
10419
|
+
currentPrice,
|
|
10420
|
+
backtest,
|
|
10421
|
+
timestamp,
|
|
10422
|
+
};
|
|
10423
|
+
await idlePingSubject.next(event);
|
|
10424
|
+
await self.actionCoreService.pingIdle(backtest, event, { strategyName, exchangeName, frameName });
|
|
10425
|
+
}, {
|
|
10426
|
+
fallback: (error) => {
|
|
10427
|
+
const message = "StrategyConnectionService CREATE_COMMIT_IDLE_PING_FN thrown";
|
|
10428
|
+
const payload = {
|
|
10429
|
+
error: functoolsKit.errorData(error),
|
|
10430
|
+
message: functoolsKit.getErrorMessage(error),
|
|
10431
|
+
};
|
|
10432
|
+
self.loggerService.warn(message, payload);
|
|
10433
|
+
console.warn(message, payload);
|
|
10434
|
+
errorEmitter.next(error);
|
|
10435
|
+
},
|
|
10436
|
+
defaultValue: null,
|
|
10437
|
+
});
|
|
10378
10438
|
/**
|
|
10379
10439
|
* Creates a callback function for emitting active ping events.
|
|
10380
10440
|
*
|
|
10381
10441
|
* Called by ClientStrategy when an active pending signal is being monitored every minute.
|
|
10382
|
-
* Placeholder for future activePingSubject implementation.
|
|
10383
10442
|
*
|
|
10384
10443
|
* @param self - Reference to StrategyConnectionService instance
|
|
10385
10444
|
* @returns Callback function for active ping events
|
|
@@ -10626,6 +10685,7 @@ class StrategyConnectionService {
|
|
|
10626
10685
|
onInit: CREATE_COMMIT_INIT_FN(this),
|
|
10627
10686
|
onSchedulePing: CREATE_COMMIT_SCHEDULE_PING_FN(this),
|
|
10628
10687
|
onActivePing: CREATE_COMMIT_ACTIVE_PING_FN(this),
|
|
10688
|
+
onIdlePing: CREATE_COMMIT_IDLE_PING_FN(this),
|
|
10629
10689
|
onDispose: CREATE_COMMIT_DISPOSE_FN(this),
|
|
10630
10690
|
onCommit: CREATE_COMMIT_FN(this),
|
|
10631
10691
|
onSignalSync: CREATE_SYNC_FN(this, strategyName, exchangeName, frameName, backtest),
|
|
@@ -11977,8 +12037,6 @@ const INTERVAL_MINUTES$6 = {
|
|
|
11977
12037
|
"8h": 480,
|
|
11978
12038
|
"12h": 720,
|
|
11979
12039
|
"1d": 1440,
|
|
11980
|
-
"1w": 10080,
|
|
11981
|
-
"1M": 43200,
|
|
11982
12040
|
};
|
|
11983
12041
|
/**
|
|
11984
12042
|
* Wrapper to call onTimeframe callback with error handling.
|
|
@@ -12044,7 +12102,7 @@ const GET_TIMEFRAME_FN = async (symbol, self) => {
|
|
|
12044
12102
|
* Features:
|
|
12045
12103
|
* - Generates timestamp arrays for backtest iteration
|
|
12046
12104
|
* - Singleshot caching prevents redundant generation
|
|
12047
|
-
* - Configurable interval spacing (1m to
|
|
12105
|
+
* - Configurable interval spacing (1m to 1d)
|
|
12048
12106
|
* - Callback support for validation and logging
|
|
12049
12107
|
*
|
|
12050
12108
|
* Used by BacktestLogicPrivateService to iterate through historical periods.
|
|
@@ -12398,7 +12456,6 @@ const INTERVAL_MINUTES$5 = {
|
|
|
12398
12456
|
"6h": 360,
|
|
12399
12457
|
"8h": 480,
|
|
12400
12458
|
"1d": 1440,
|
|
12401
|
-
"1w": 10080,
|
|
12402
12459
|
};
|
|
12403
12460
|
/**
|
|
12404
12461
|
* Aligns timestamp down to the nearest interval boundary.
|
|
@@ -13104,6 +13161,34 @@ const CALL_PING_SCHEDULED_FN = functoolsKit.trycatch(async (event, self) => {
|
|
|
13104
13161
|
},
|
|
13105
13162
|
defaultValue: null,
|
|
13106
13163
|
});
|
|
13164
|
+
/**
|
|
13165
|
+
* Wrapper to call pingIdle method with error capture.
|
|
13166
|
+
*/
|
|
13167
|
+
const CALL_PING_IDLE_FN = functoolsKit.trycatch(async (event, self) => {
|
|
13168
|
+
if (!self._target.pingIdle) {
|
|
13169
|
+
return;
|
|
13170
|
+
}
|
|
13171
|
+
if (await self.params.strategy.hasPendingSignal(event.backtest, event.symbol, {
|
|
13172
|
+
strategyName: event.strategyName,
|
|
13173
|
+
exchangeName: event.exchangeName,
|
|
13174
|
+
frameName: event.frameName,
|
|
13175
|
+
})) {
|
|
13176
|
+
return;
|
|
13177
|
+
}
|
|
13178
|
+
return await self._target.pingIdle(event);
|
|
13179
|
+
}, {
|
|
13180
|
+
fallback: (error) => {
|
|
13181
|
+
const message = "ActionProxy.pingIdle thrown";
|
|
13182
|
+
const payload = {
|
|
13183
|
+
error: functoolsKit.errorData(error),
|
|
13184
|
+
message: functoolsKit.getErrorMessage(error),
|
|
13185
|
+
};
|
|
13186
|
+
LOGGER_SERVICE$4.warn(message, payload);
|
|
13187
|
+
console.warn(message, payload);
|
|
13188
|
+
errorEmitter.next(error);
|
|
13189
|
+
},
|
|
13190
|
+
defaultValue: null,
|
|
13191
|
+
});
|
|
13107
13192
|
/**
|
|
13108
13193
|
* Wrapper to call pingActive method with error capture.
|
|
13109
13194
|
*/
|
|
@@ -13342,6 +13427,18 @@ class ActionProxy {
|
|
|
13342
13427
|
async pingActive(event) {
|
|
13343
13428
|
return await CALL_PING_ACTIVE_FN(event, this);
|
|
13344
13429
|
}
|
|
13430
|
+
/**
|
|
13431
|
+
* Handles idle ping events with error capture.
|
|
13432
|
+
*
|
|
13433
|
+
* Wraps the user's pingIdle() method to catch and log any errors.
|
|
13434
|
+
* Called every tick while no signal is pending or scheduled.
|
|
13435
|
+
*
|
|
13436
|
+
* @param event - Idle ping data with symbol, strategy info, current price, timestamp
|
|
13437
|
+
* @returns Promise resolving to user's pingIdle() result or null on error
|
|
13438
|
+
*/
|
|
13439
|
+
async pingIdle(event) {
|
|
13440
|
+
return await CALL_PING_IDLE_FN(event, this);
|
|
13441
|
+
}
|
|
13345
13442
|
/**
|
|
13346
13443
|
* Handles risk rejection events with error capture.
|
|
13347
13444
|
*
|
|
@@ -13529,6 +13626,23 @@ const CALL_PING_SCHEDULED_CALLBACK_FN = functoolsKit.trycatch(async (self, event
|
|
|
13529
13626
|
errorEmitter.next(error);
|
|
13530
13627
|
},
|
|
13531
13628
|
});
|
|
13629
|
+
/** Wrapper to call idle ping callback with error handling */
|
|
13630
|
+
const CALL_PING_IDLE_CALLBACK_FN = functoolsKit.trycatch(async (self, event, strategyName, frameName, backtest) => {
|
|
13631
|
+
if (self.params.callbacks?.onPingIdle) {
|
|
13632
|
+
await self.params.callbacks.onPingIdle(event, self.params.actionName, strategyName, frameName, backtest);
|
|
13633
|
+
}
|
|
13634
|
+
}, {
|
|
13635
|
+
fallback: (error, self) => {
|
|
13636
|
+
const message = "ClientAction CALL_PING_IDLE_CALLBACK_FN thrown";
|
|
13637
|
+
const payload = {
|
|
13638
|
+
error: functoolsKit.errorData(error),
|
|
13639
|
+
message: functoolsKit.getErrorMessage(error),
|
|
13640
|
+
};
|
|
13641
|
+
self.params.logger.warn(message, payload);
|
|
13642
|
+
console.warn(message, payload);
|
|
13643
|
+
errorEmitter.next(error);
|
|
13644
|
+
},
|
|
13645
|
+
});
|
|
13532
13646
|
/** Wrapper to call active ping callback with error handling */
|
|
13533
13647
|
const CALL_PING_ACTIVE_CALLBACK_FN = functoolsKit.trycatch(async (self, event, strategyName, frameName, backtest) => {
|
|
13534
13648
|
if (self.params.callbacks?.onPingActive) {
|
|
@@ -13895,6 +14009,24 @@ class ClientAction {
|
|
|
13895
14009
|
await CALL_PING_ACTIVE_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
|
|
13896
14010
|
}
|
|
13897
14011
|
;
|
|
14012
|
+
/**
|
|
14013
|
+
* Handles idle ping events when no signal is active.
|
|
14014
|
+
*/
|
|
14015
|
+
async pingIdle(event) {
|
|
14016
|
+
this.params.logger.debug("ClientAction pingIdle", {
|
|
14017
|
+
actionName: this.params.actionName,
|
|
14018
|
+
strategyName: this.params.strategyName,
|
|
14019
|
+
frameName: this.params.frameName,
|
|
14020
|
+
});
|
|
14021
|
+
if (!this._handlerInstance) {
|
|
14022
|
+
await this.waitForInit();
|
|
14023
|
+
}
|
|
14024
|
+
// Call handler method if defined
|
|
14025
|
+
await this._handlerInstance?.pingIdle(event);
|
|
14026
|
+
// Call callback if defined
|
|
14027
|
+
await CALL_PING_IDLE_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
|
|
14028
|
+
}
|
|
14029
|
+
;
|
|
13898
14030
|
/**
|
|
13899
14031
|
* Handles risk rejection events when signals fail risk validation.
|
|
13900
14032
|
*/
|
|
@@ -14147,6 +14279,21 @@ class ActionConnectionService {
|
|
|
14147
14279
|
const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
14148
14280
|
await action.pingActive(event);
|
|
14149
14281
|
};
|
|
14282
|
+
/**
|
|
14283
|
+
* Routes idle ping event to appropriate ClientAction instance.
|
|
14284
|
+
*
|
|
14285
|
+
* @param event - Idle ping event data
|
|
14286
|
+
* @param backtest - Whether running in backtest mode
|
|
14287
|
+
* @param context - Execution context with action name, strategy name, exchange name, frame name
|
|
14288
|
+
*/
|
|
14289
|
+
this.pingIdle = async (event, backtest, context) => {
|
|
14290
|
+
this.loggerService.log("actionConnectionService pingIdle", {
|
|
14291
|
+
backtest,
|
|
14292
|
+
context,
|
|
14293
|
+
});
|
|
14294
|
+
const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
14295
|
+
await action.pingIdle(event);
|
|
14296
|
+
};
|
|
14150
14297
|
/**
|
|
14151
14298
|
* Routes riskRejection event to appropriate ClientAction instance.
|
|
14152
14299
|
*
|
|
@@ -16250,6 +16397,27 @@ class ActionCoreService {
|
|
|
16250
16397
|
await this.actionConnectionService.pingActive(event, backtest, { actionName, ...context });
|
|
16251
16398
|
}
|
|
16252
16399
|
};
|
|
16400
|
+
/**
|
|
16401
|
+
* Routes idle ping event to all registered actions for the strategy.
|
|
16402
|
+
*
|
|
16403
|
+
* Retrieves action list from strategy schema (IStrategySchema.actions)
|
|
16404
|
+
* and invokes the pingIdle handler on each ClientAction instance sequentially.
|
|
16405
|
+
* Called every tick when there is no pending or scheduled signal being monitored.
|
|
16406
|
+
*
|
|
16407
|
+
* @param backtest - Whether running in backtest mode (true) or live mode (false)
|
|
16408
|
+
* @param event - Idle state monitoring data
|
|
16409
|
+
* @param context - Strategy execution context with strategyName, exchangeName, frameName
|
|
16410
|
+
*/
|
|
16411
|
+
this.pingIdle = async (backtest, event, context) => {
|
|
16412
|
+
this.loggerService.log("actionCoreService pingIdle", {
|
|
16413
|
+
context,
|
|
16414
|
+
});
|
|
16415
|
+
await this.validate(context);
|
|
16416
|
+
const { actions = [] } = this.strategySchemaService.get(context.strategyName);
|
|
16417
|
+
for (const actionName of actions) {
|
|
16418
|
+
await this.actionConnectionService.pingIdle(event, backtest, { actionName, ...context });
|
|
16419
|
+
}
|
|
16420
|
+
};
|
|
16253
16421
|
/**
|
|
16254
16422
|
* Routes risk rejection event to all registered actions for the strategy.
|
|
16255
16423
|
*
|
|
@@ -17659,7 +17827,6 @@ const INTERVAL_MINUTES$4 = {
|
|
|
17659
17827
|
"6h": 360,
|
|
17660
17828
|
"8h": 480,
|
|
17661
17829
|
"1d": 1440,
|
|
17662
|
-
"1w": 10080,
|
|
17663
17830
|
};
|
|
17664
17831
|
const createEmitter = functoolsKit.memoize(([interval]) => `${interval}`, (interval) => {
|
|
17665
17832
|
const tickSubject = new functoolsKit.Subject();
|
|
@@ -32872,7 +33039,6 @@ const INTERVAL_MINUTES$3 = {
|
|
|
32872
33039
|
"6h": 360,
|
|
32873
33040
|
"8h": 480,
|
|
32874
33041
|
"1d": 1440,
|
|
32875
|
-
"1w": 10080,
|
|
32876
33042
|
};
|
|
32877
33043
|
/**
|
|
32878
33044
|
* Aligns timestamp down to the nearest interval boundary.
|
|
@@ -33623,7 +33789,6 @@ const INTERVAL_MINUTES$2 = {
|
|
|
33623
33789
|
"6h": 360,
|
|
33624
33790
|
"8h": 480,
|
|
33625
33791
|
"1d": 1440,
|
|
33626
|
-
"1w": 10080,
|
|
33627
33792
|
};
|
|
33628
33793
|
const ALIGN_TO_INTERVAL_FN = (timestamp, intervalMinutes) => {
|
|
33629
33794
|
const intervalMs = intervalMinutes * MS_PER_MINUTE$2;
|
|
@@ -37820,6 +37985,8 @@ const LISTEN_SCHEDULE_PING_METHOD_NAME = "event.listenSchedulePing";
|
|
|
37820
37985
|
const LISTEN_SCHEDULE_PING_ONCE_METHOD_NAME = "event.listenSchedulePingOnce";
|
|
37821
37986
|
const LISTEN_ACTIVE_PING_METHOD_NAME = "event.listenActivePing";
|
|
37822
37987
|
const LISTEN_ACTIVE_PING_ONCE_METHOD_NAME = "event.listenActivePingOnce";
|
|
37988
|
+
const LISTEN_IDLE_PING_METHOD_NAME = "event.listenIdlePing";
|
|
37989
|
+
const LISTEN_IDLE_PING_ONCE_METHOD_NAME = "event.listenIdlePingOnce";
|
|
37823
37990
|
const LISTEN_STRATEGY_COMMIT_METHOD_NAME = "event.listenStrategyCommit";
|
|
37824
37991
|
const LISTEN_STRATEGY_COMMIT_ONCE_METHOD_NAME = "event.listenStrategyCommitOnce";
|
|
37825
37992
|
const LISTEN_SYNC_METHOD_NAME = "event.listenSync";
|
|
@@ -38995,6 +39162,45 @@ function listenActivePingOnce(filterFn, fn) {
|
|
|
38995
39162
|
};
|
|
38996
39163
|
return disposeFn = listenActivePing(wrappedFn);
|
|
38997
39164
|
}
|
|
39165
|
+
/**
|
|
39166
|
+
* Subscribes to idle ping events with queued async processing.
|
|
39167
|
+
*
|
|
39168
|
+
* Emits every tick when there is no pending or scheduled signal being monitored.
|
|
39169
|
+
*
|
|
39170
|
+
* @param fn - Callback function to handle idle ping events
|
|
39171
|
+
* @returns Unsubscribe function to stop listening
|
|
39172
|
+
*/
|
|
39173
|
+
function listenIdlePing(fn) {
|
|
39174
|
+
backtest.loggerService.log(LISTEN_IDLE_PING_METHOD_NAME);
|
|
39175
|
+
const wrappedFn = async (event) => {
|
|
39176
|
+
if (await functoolsKit.not(backtest.strategyCoreService.hasPendingSignal(event.backtest, event.symbol, {
|
|
39177
|
+
strategyName: event.strategyName,
|
|
39178
|
+
exchangeName: event.exchangeName,
|
|
39179
|
+
frameName: event.frameName,
|
|
39180
|
+
}))) {
|
|
39181
|
+
await fn(event);
|
|
39182
|
+
}
|
|
39183
|
+
};
|
|
39184
|
+
return idlePingSubject.subscribe(functoolsKit.queued(wrappedFn));
|
|
39185
|
+
}
|
|
39186
|
+
/**
|
|
39187
|
+
* Subscribes to filtered idle ping events with one-time execution.
|
|
39188
|
+
*
|
|
39189
|
+
* @param filterFn - Predicate to filter events
|
|
39190
|
+
* @param fn - Callback function to handle the matching event
|
|
39191
|
+
* @returns Unsubscribe function to cancel the listener before it fires
|
|
39192
|
+
*/
|
|
39193
|
+
function listenIdlePingOnce(filterFn, fn) {
|
|
39194
|
+
backtest.loggerService.log(LISTEN_IDLE_PING_ONCE_METHOD_NAME);
|
|
39195
|
+
let disposeFn;
|
|
39196
|
+
const wrappedFn = async (event) => {
|
|
39197
|
+
if (filterFn(event)) {
|
|
39198
|
+
await fn(event);
|
|
39199
|
+
disposeFn && disposeFn();
|
|
39200
|
+
}
|
|
39201
|
+
};
|
|
39202
|
+
return disposeFn = listenIdlePing(wrappedFn);
|
|
39203
|
+
}
|
|
38998
39204
|
/**
|
|
38999
39205
|
* Subscribes to strategy management events with queued async processing.
|
|
39000
39206
|
*
|
|
@@ -45205,7 +45411,7 @@ function addExchangeSchema(exchangeSchema) {
|
|
|
45205
45411
|
*
|
|
45206
45412
|
* @param frameSchema - Frame configuration object
|
|
45207
45413
|
* @param frameSchema.frameName - Unique frame identifier
|
|
45208
|
-
* @param frameSchema.interval - Timeframe interval ("1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h" | "12h" | "1d"
|
|
45414
|
+
* @param frameSchema.interval - Timeframe interval ("1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h" | "12h" | "1d")
|
|
45209
45415
|
* @param frameSchema.startDate - Start date for timeframe generation
|
|
45210
45416
|
* @param frameSchema.endDate - End date for timeframe generation
|
|
45211
45417
|
* @param frameSchema.callbacks - Optional callback for timeframe events
|
|
@@ -45952,6 +46158,7 @@ const RECENT_LIVE_ADAPTER_METHOD_NAME_CLEAR = "RecentLiveAdapter.clear";
|
|
|
45952
46158
|
const RECENT_ADAPTER_METHOD_NAME_ENABLE = "RecentAdapter.enable";
|
|
45953
46159
|
const RECENT_ADAPTER_METHOD_NAME_DISABLE = "RecentAdapter.disable";
|
|
45954
46160
|
const RECENT_ADAPTER_METHOD_NAME_GET_LATEST_SIGNAL = "RecentAdapter.getLatestSignal";
|
|
46161
|
+
const RECENT_ADAPTER_METHOD_NAME_GET_MINUTES_SINCE_LATEST_SIGNAL = "RecentAdapter.getMinutesSinceLatestSignalCreated";
|
|
45955
46162
|
/**
|
|
45956
46163
|
* Builds a composite storage key from context parts.
|
|
45957
46164
|
* Includes backtest flag as the last segment to prevent live/backtest collisions.
|
|
@@ -46010,6 +46217,23 @@ class RecentPersistBacktestUtils {
|
|
|
46010
46217
|
});
|
|
46011
46218
|
return await PersistRecentAdapter.readRecentData(symbol, strategyName, exchangeName, frameName, backtest$1);
|
|
46012
46219
|
};
|
|
46220
|
+
/**
|
|
46221
|
+
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
46222
|
+
* @param timestamp - Current timestamp in milliseconds
|
|
46223
|
+
* @param symbol - Trading pair symbol
|
|
46224
|
+
* @param strategyName - Strategy identifier
|
|
46225
|
+
* @param exchangeName - Exchange identifier
|
|
46226
|
+
* @param frameName - Frame identifier
|
|
46227
|
+
* @param backtest - Flag indicating if the context is backtest or live
|
|
46228
|
+
* @returns Whole minutes since the latest signal was created, or null if no signal found
|
|
46229
|
+
*/
|
|
46230
|
+
this.getMinutesSinceLatestSignalCreated = async (timestamp, symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
46231
|
+
const signal = await this.getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest);
|
|
46232
|
+
if (!signal) {
|
|
46233
|
+
return null;
|
|
46234
|
+
}
|
|
46235
|
+
return Math.floor((timestamp - signal.timestamp) / (1000 * 60));
|
|
46236
|
+
};
|
|
46013
46237
|
}
|
|
46014
46238
|
}
|
|
46015
46239
|
/**
|
|
@@ -46052,6 +46276,23 @@ class RecentMemoryBacktestUtils {
|
|
|
46052
46276
|
backtest.loggerService.info(RECENT_MEMORY_BACKTEST_METHOD_NAME_GET_LATEST_SIGNAL, { key });
|
|
46053
46277
|
return this._signals.get(key) ?? null;
|
|
46054
46278
|
};
|
|
46279
|
+
/**
|
|
46280
|
+
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
46281
|
+
* @param timestamp - Current timestamp in milliseconds
|
|
46282
|
+
* @param symbol - Trading pair symbol
|
|
46283
|
+
* @param strategyName - Strategy identifier
|
|
46284
|
+
* @param exchangeName - Exchange identifier
|
|
46285
|
+
* @param frameName - Frame identifier
|
|
46286
|
+
* @param backtest - Flag indicating if the context is backtest or live
|
|
46287
|
+
* @returns Whole minutes since the latest signal was created, or null if no signal found
|
|
46288
|
+
*/
|
|
46289
|
+
this.getMinutesSinceLatestSignalCreated = async (timestamp, symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
46290
|
+
const signal = await this.getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest);
|
|
46291
|
+
if (!signal) {
|
|
46292
|
+
return null;
|
|
46293
|
+
}
|
|
46294
|
+
return Math.floor((timestamp - signal.timestamp) / (1000 * 60));
|
|
46295
|
+
};
|
|
46055
46296
|
}
|
|
46056
46297
|
}
|
|
46057
46298
|
/**
|
|
@@ -46095,6 +46336,23 @@ class RecentPersistLiveUtils {
|
|
|
46095
46336
|
});
|
|
46096
46337
|
return await PersistRecentAdapter.readRecentData(symbol, strategyName, exchangeName, frameName, backtest$1);
|
|
46097
46338
|
};
|
|
46339
|
+
/**
|
|
46340
|
+
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
46341
|
+
* @param timestamp - Current timestamp in milliseconds
|
|
46342
|
+
* @param symbol - Trading pair symbol
|
|
46343
|
+
* @param strategyName - Strategy identifier
|
|
46344
|
+
* @param exchangeName - Exchange identifier
|
|
46345
|
+
* @param frameName - Frame identifier
|
|
46346
|
+
* @param backtest - Flag indicating if the context is backtest or live
|
|
46347
|
+
* @returns Whole minutes since the latest signal was created, or null if no signal found
|
|
46348
|
+
*/
|
|
46349
|
+
this.getMinutesSinceLatestSignalCreated = async (timestamp, symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
46350
|
+
const signal = await this.getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest);
|
|
46351
|
+
if (!signal) {
|
|
46352
|
+
return null;
|
|
46353
|
+
}
|
|
46354
|
+
return Math.floor((timestamp - signal.timestamp) / (1000 * 60));
|
|
46355
|
+
};
|
|
46098
46356
|
}
|
|
46099
46357
|
}
|
|
46100
46358
|
/**
|
|
@@ -46137,6 +46395,23 @@ class RecentMemoryLiveUtils {
|
|
|
46137
46395
|
backtest.loggerService.info(RECENT_MEMORY_LIVE_METHOD_NAME_GET_LATEST_SIGNAL, { key });
|
|
46138
46396
|
return this._signals.get(key) ?? null;
|
|
46139
46397
|
};
|
|
46398
|
+
/**
|
|
46399
|
+
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
46400
|
+
* @param timestamp - Current timestamp in milliseconds
|
|
46401
|
+
* @param symbol - Trading pair symbol
|
|
46402
|
+
* @param strategyName - Strategy identifier
|
|
46403
|
+
* @param exchangeName - Exchange identifier
|
|
46404
|
+
* @param frameName - Frame identifier
|
|
46405
|
+
* @param backtest - Flag indicating if the context is backtest or live
|
|
46406
|
+
* @returns Whole minutes since the latest signal was created, or null if no signal found
|
|
46407
|
+
*/
|
|
46408
|
+
this.getMinutesSinceLatestSignalCreated = async (timestamp, symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
46409
|
+
const signal = await this.getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest);
|
|
46410
|
+
if (!signal) {
|
|
46411
|
+
return null;
|
|
46412
|
+
}
|
|
46413
|
+
return Math.floor((timestamp - signal.timestamp) / (1000 * 60));
|
|
46414
|
+
};
|
|
46140
46415
|
}
|
|
46141
46416
|
}
|
|
46142
46417
|
/**
|
|
@@ -46183,6 +46458,32 @@ class RecentBacktestAdapter {
|
|
|
46183
46458
|
});
|
|
46184
46459
|
return await this._recentBacktestUtils.getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1);
|
|
46185
46460
|
};
|
|
46461
|
+
/**
|
|
46462
|
+
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
46463
|
+
* Proxies call to the underlying storage adapter.
|
|
46464
|
+
* @param timestamp - Current timestamp in milliseconds
|
|
46465
|
+
* @param symbol - Trading pair symbol
|
|
46466
|
+
* @param strategyName - Strategy identifier
|
|
46467
|
+
* @param exchangeName - Exchange identifier
|
|
46468
|
+
* @param frameName - Frame identifier
|
|
46469
|
+
* @param backtest - Flag indicating if the context is backtest or live
|
|
46470
|
+
* @returns Whole minutes since the latest signal was created, or null if no signal found
|
|
46471
|
+
*/
|
|
46472
|
+
this.getMinutesSinceLatestSignalCreated = async (timestamp, symbol, strategyName, exchangeName, frameName, backtest$1) => {
|
|
46473
|
+
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_GET_LATEST_SIGNAL, {
|
|
46474
|
+
symbol,
|
|
46475
|
+
strategyName,
|
|
46476
|
+
exchangeName,
|
|
46477
|
+
frameName,
|
|
46478
|
+
backtest: backtest$1,
|
|
46479
|
+
timestamp,
|
|
46480
|
+
});
|
|
46481
|
+
const signal = await this._recentBacktestUtils.getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1);
|
|
46482
|
+
if (!signal) {
|
|
46483
|
+
return null;
|
|
46484
|
+
}
|
|
46485
|
+
return Math.floor((timestamp - signal.timestamp) / (1000 * 60));
|
|
46486
|
+
};
|
|
46186
46487
|
/**
|
|
46187
46488
|
* Sets the storage adapter constructor.
|
|
46188
46489
|
* All future storage operations will use this adapter.
|
|
@@ -46261,6 +46562,32 @@ class RecentLiveAdapter {
|
|
|
46261
46562
|
});
|
|
46262
46563
|
return await this._recentLiveUtils.getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1);
|
|
46263
46564
|
};
|
|
46565
|
+
/**
|
|
46566
|
+
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
46567
|
+
* Proxies call to the underlying storage adapter.
|
|
46568
|
+
* @param timestamp - Current timestamp in milliseconds
|
|
46569
|
+
* @param symbol - Trading pair symbol
|
|
46570
|
+
* @param strategyName - Strategy identifier
|
|
46571
|
+
* @param exchangeName - Exchange identifier
|
|
46572
|
+
* @param frameName - Frame identifier
|
|
46573
|
+
* @param backtest - Flag indicating if the context is backtest or live
|
|
46574
|
+
* @returns Whole minutes since the latest signal was created, or null if no signal found
|
|
46575
|
+
*/
|
|
46576
|
+
this.getMinutesSinceLatestSignalCreated = async (timestamp, symbol, strategyName, exchangeName, frameName, backtest$1) => {
|
|
46577
|
+
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_GET_LATEST_SIGNAL, {
|
|
46578
|
+
symbol,
|
|
46579
|
+
strategyName,
|
|
46580
|
+
exchangeName,
|
|
46581
|
+
frameName,
|
|
46582
|
+
backtest: backtest$1,
|
|
46583
|
+
timestamp,
|
|
46584
|
+
});
|
|
46585
|
+
const signal = await this._recentLiveUtils.getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1);
|
|
46586
|
+
if (!signal) {
|
|
46587
|
+
return null;
|
|
46588
|
+
}
|
|
46589
|
+
return Math.floor((timestamp - signal.timestamp) / (1000 * 60));
|
|
46590
|
+
};
|
|
46264
46591
|
/**
|
|
46265
46592
|
* Sets the storage adapter constructor.
|
|
46266
46593
|
* All future storage operations will use this adapter.
|
|
@@ -46369,6 +46696,27 @@ class RecentAdapter {
|
|
|
46369
46696
|
}
|
|
46370
46697
|
return null;
|
|
46371
46698
|
};
|
|
46699
|
+
/**
|
|
46700
|
+
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
46701
|
+
* Searches backtest storage first, then live storage.
|
|
46702
|
+
* @param timestamp - Current timestamp in milliseconds
|
|
46703
|
+
* @param symbol - Trading pair symbol
|
|
46704
|
+
* @param context - Execution context with strategyName, exchangeName, and frameName
|
|
46705
|
+
* @returns Whole minutes since the latest signal was created, or null if no signal found
|
|
46706
|
+
* @throws Error if RecentAdapter is not enabled
|
|
46707
|
+
*/
|
|
46708
|
+
this.getMinutesSinceLatestSignalCreated = async (timestamp, symbol, context) => {
|
|
46709
|
+
backtest.loggerService.info(RECENT_ADAPTER_METHOD_NAME_GET_MINUTES_SINCE_LATEST_SIGNAL, {
|
|
46710
|
+
symbol,
|
|
46711
|
+
context,
|
|
46712
|
+
timestamp,
|
|
46713
|
+
});
|
|
46714
|
+
const signal = await this.getLatestSignal(symbol, context);
|
|
46715
|
+
if (!signal) {
|
|
46716
|
+
return null;
|
|
46717
|
+
}
|
|
46718
|
+
return Math.floor((timestamp - signal.timestamp) / (1000 * 60));
|
|
46719
|
+
};
|
|
46372
46720
|
}
|
|
46373
46721
|
}
|
|
46374
46722
|
/**
|
|
@@ -46388,6 +46736,7 @@ const RecentLive = new RecentLiveAdapter();
|
|
|
46388
46736
|
const RecentBacktest = new RecentBacktestAdapter();
|
|
46389
46737
|
|
|
46390
46738
|
const GET_LATEST_SIGNAL_METHOD_NAME = "signal.getLatestSignal";
|
|
46739
|
+
const GET_MINUTES_SINCE_LATEST_SIGNAL_CREATED_METHOD_NAME = "signal.getMinutesSinceLatestSignalCreated";
|
|
46391
46740
|
/**
|
|
46392
46741
|
* Returns the latest signal (pending or closed) for the current strategy context.
|
|
46393
46742
|
*
|
|
@@ -46425,6 +46774,43 @@ async function getLatestSignal(symbol) {
|
|
|
46425
46774
|
const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
|
|
46426
46775
|
return await Recent.getLatestSignal(symbol, { exchangeName, frameName, strategyName });
|
|
46427
46776
|
}
|
|
46777
|
+
/**
|
|
46778
|
+
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
46779
|
+
*
|
|
46780
|
+
* Does not distinguish between active and closed signals — measures time since
|
|
46781
|
+
* whichever signal was recorded last. Useful for cooldown logic after a stop-loss.
|
|
46782
|
+
*
|
|
46783
|
+
* Searches backtest storage first, then live storage.
|
|
46784
|
+
* Returns null if no signal exists at all.
|
|
46785
|
+
*
|
|
46786
|
+
* Automatically detects backtest/live mode from execution context.
|
|
46787
|
+
*
|
|
46788
|
+
* @param symbol - Trading pair symbol
|
|
46789
|
+
* @param timestamp - Current timestamp in milliseconds
|
|
46790
|
+
* @returns Promise resolving to whole minutes since the latest signal was created, or null
|
|
46791
|
+
*
|
|
46792
|
+
* @example
|
|
46793
|
+
* ```typescript
|
|
46794
|
+
* import { getMinutesSinceLatestSignalCreated } from "backtest-kit";
|
|
46795
|
+
*
|
|
46796
|
+
* const minutes = await getMinutesSinceLatestSignalCreated("BTCUSDT");
|
|
46797
|
+
* if (minutes !== null && minutes < 24 * 60) {
|
|
46798
|
+
* return; // cooldown — skip new signal for 24 hours after last signal
|
|
46799
|
+
* }
|
|
46800
|
+
* ```
|
|
46801
|
+
*/
|
|
46802
|
+
async function getMinutesSinceLatestSignalCreated(symbol) {
|
|
46803
|
+
backtest.loggerService.info(GET_MINUTES_SINCE_LATEST_SIGNAL_CREATED_METHOD_NAME, { symbol });
|
|
46804
|
+
if (!ExecutionContextService.hasContext()) {
|
|
46805
|
+
throw new Error("getMinutesSinceLatestSignalCreated requires an execution context");
|
|
46806
|
+
}
|
|
46807
|
+
if (!MethodContextService.hasContext()) {
|
|
46808
|
+
throw new Error("getMinutesSinceLatestSignalCreated requires a method context");
|
|
46809
|
+
}
|
|
46810
|
+
const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
|
|
46811
|
+
const { when } = backtest.executionContextService.context;
|
|
46812
|
+
return await Recent.getMinutesSinceLatestSignalCreated(when.getTime(), symbol, { exchangeName, frameName, strategyName });
|
|
46813
|
+
}
|
|
46428
46814
|
|
|
46429
46815
|
const DEFAULT_BM25_K1 = 1.5;
|
|
46430
46816
|
const DEFAULT_BM25_B = 0.75;
|
|
@@ -49752,6 +50138,7 @@ const METHOD_NAME_CREATE_SNAPSHOT = "SessionUtils.createSnapshot";
|
|
|
49752
50138
|
/** List of all global subjects whose listeners should be snapshotted for session isolation */
|
|
49753
50139
|
const SUBJECT_ISOLATION_LIST = [
|
|
49754
50140
|
activePingSubject,
|
|
50141
|
+
idlePingSubject,
|
|
49755
50142
|
backtestScheduleOpenSubject,
|
|
49756
50143
|
breakevenSubject,
|
|
49757
50144
|
doneBacktestSubject,
|
|
@@ -56306,7 +56693,6 @@ const INTERVAL_MINUTES$1 = {
|
|
|
56306
56693
|
"6h": 360,
|
|
56307
56694
|
"8h": 480,
|
|
56308
56695
|
"1d": 1440,
|
|
56309
|
-
"1w": 10080,
|
|
56310
56696
|
};
|
|
56311
56697
|
/**
|
|
56312
56698
|
* Aligns timestamp down to the nearest interval boundary.
|
|
@@ -56941,7 +57327,6 @@ const INTERVAL_MINUTES = {
|
|
|
56941
57327
|
"6h": 360,
|
|
56942
57328
|
"8h": 480,
|
|
56943
57329
|
"1d": 1440,
|
|
56944
|
-
"1w": 10080,
|
|
56945
57330
|
};
|
|
56946
57331
|
/**
|
|
56947
57332
|
* Aligns timestamp down to the nearest interval boundary.
|
|
@@ -57872,6 +58257,7 @@ const METHOD_NAME_PARTIAL_PROFIT_AVAILABLE = "ActionBase.partialProfitAvailable"
|
|
|
57872
58257
|
const METHOD_NAME_PARTIAL_LOSS_AVAILABLE = "ActionBase.partialLossAvailable";
|
|
57873
58258
|
const METHOD_NAME_PING_SCHEDULED = "ActionBase.pingScheduled";
|
|
57874
58259
|
const METHOD_NAME_PING_ACTIVE = "ActionBase.pingActive";
|
|
58260
|
+
const METHOD_NAME_PING_IDLE = "ActionBase.pingIdle";
|
|
57875
58261
|
const METHOD_NAME_RISK_REJECTION = "ActionBase.riskRejection";
|
|
57876
58262
|
const METHOD_NAME_DISPOSE = "ActionBase.dispose";
|
|
57877
58263
|
const DEFAULT_SOURCE = "default";
|
|
@@ -58265,6 +58651,26 @@ class ActionBase {
|
|
|
58265
58651
|
source,
|
|
58266
58652
|
});
|
|
58267
58653
|
}
|
|
58654
|
+
/**
|
|
58655
|
+
* Handles idle ping events when no signal is active.
|
|
58656
|
+
*
|
|
58657
|
+
* Called every tick while no signal is pending or scheduled.
|
|
58658
|
+
* Use to monitor idle strategy state and implement entry condition logic.
|
|
58659
|
+
*
|
|
58660
|
+
* Triggered by: ActionCoreService.pingIdle() via StrategyConnectionService
|
|
58661
|
+
* Source: idlePingSubject.next() in CREATE_COMMIT_IDLE_PING_FN callback
|
|
58662
|
+
* Frequency: Every tick while no signal is pending or scheduled
|
|
58663
|
+
*
|
|
58664
|
+
* Default implementation: Logs idle ping event.
|
|
58665
|
+
*
|
|
58666
|
+
* @param event - Idle ping data with symbol, strategy info, current price, timestamp
|
|
58667
|
+
*/
|
|
58668
|
+
pingIdle(event, source = DEFAULT_SOURCE) {
|
|
58669
|
+
LOGGER_SERVICE.info(METHOD_NAME_PING_IDLE, {
|
|
58670
|
+
event,
|
|
58671
|
+
source,
|
|
58672
|
+
});
|
|
58673
|
+
}
|
|
58268
58674
|
/**
|
|
58269
58675
|
* Handles risk rejection events when signals fail risk validation.
|
|
58270
58676
|
*
|
|
@@ -58708,6 +59114,7 @@ exports.getFrameSchema = getFrameSchema;
|
|
|
58708
59114
|
exports.getLatestSignal = getLatestSignal;
|
|
58709
59115
|
exports.getMaxDrawdownDistancePnlCost = getMaxDrawdownDistancePnlCost;
|
|
58710
59116
|
exports.getMaxDrawdownDistancePnlPercentage = getMaxDrawdownDistancePnlPercentage;
|
|
59117
|
+
exports.getMinutesSinceLatestSignalCreated = getMinutesSinceLatestSignalCreated;
|
|
58711
59118
|
exports.getMode = getMode;
|
|
58712
59119
|
exports.getNextCandles = getNextCandles;
|
|
58713
59120
|
exports.getOrderBook = getOrderBook;
|
|
@@ -58780,6 +59187,8 @@ exports.listenError = listenError;
|
|
|
58780
59187
|
exports.listenExit = listenExit;
|
|
58781
59188
|
exports.listenHighestProfit = listenHighestProfit;
|
|
58782
59189
|
exports.listenHighestProfitOnce = listenHighestProfitOnce;
|
|
59190
|
+
exports.listenIdlePing = listenIdlePing;
|
|
59191
|
+
exports.listenIdlePingOnce = listenIdlePingOnce;
|
|
58783
59192
|
exports.listenMaxDrawdown = listenMaxDrawdown;
|
|
58784
59193
|
exports.listenMaxDrawdownOnce = listenMaxDrawdownOnce;
|
|
58785
59194
|
exports.listenPartialLossAvailable = listenPartialLossAvailable;
|