backtest-kit 6.13.0 → 6.14.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/build/index.cjs +558 -105
- package/build/index.mjs +556 -106
- package/package.json +2 -2
- package/types.d.ts +356 -9
package/build/index.mjs
CHANGED
|
@@ -127,6 +127,9 @@ const reportServices$1 = {
|
|
|
127
127
|
highestProfitReportService: Symbol('highestProfitReportService'),
|
|
128
128
|
maxDrawdownReportService: Symbol('maxDrawdownReportService'),
|
|
129
129
|
};
|
|
130
|
+
const helperServices$1 = {
|
|
131
|
+
notificationHelperService: Symbol('notificationHelperService'),
|
|
132
|
+
};
|
|
130
133
|
const validationServices$1 = {
|
|
131
134
|
exchangeValidationService: Symbol('exchangeValidationService'),
|
|
132
135
|
strategyValidationService: Symbol('strategyValidationService'),
|
|
@@ -152,6 +155,7 @@ const TYPES = {
|
|
|
152
155
|
...markdownServices$1,
|
|
153
156
|
...reportServices$1,
|
|
154
157
|
...validationServices$1,
|
|
158
|
+
...helperServices$1,
|
|
155
159
|
};
|
|
156
160
|
|
|
157
161
|
/**
|
|
@@ -744,6 +748,11 @@ const highestProfitSubject = new Subject();
|
|
|
744
748
|
* Allows users to track drawdown levels and implement custom risk management logic based on drawdown thresholds.
|
|
745
749
|
*/
|
|
746
750
|
const maxDrawdownSubject = new Subject();
|
|
751
|
+
/**
|
|
752
|
+
* Signal info emitter for user-defined informational notes on open positions.
|
|
753
|
+
* Emits when a strategy calls commitSignalInfo() to broadcast a custom annotation.
|
|
754
|
+
*/
|
|
755
|
+
const signalNotifySubject = new Subject();
|
|
747
756
|
|
|
748
757
|
var emitters = /*#__PURE__*/Object.freeze({
|
|
749
758
|
__proto__: null,
|
|
@@ -768,6 +777,7 @@ var emitters = /*#__PURE__*/Object.freeze({
|
|
|
768
777
|
signalBacktestEmitter: signalBacktestEmitter,
|
|
769
778
|
signalEmitter: signalEmitter,
|
|
770
779
|
signalLiveEmitter: signalLiveEmitter,
|
|
780
|
+
signalNotifySubject: signalNotifySubject,
|
|
771
781
|
strategyCommitSubject: strategyCommitSubject,
|
|
772
782
|
syncSubject: syncSubject,
|
|
773
783
|
validationSubject: validationSubject,
|
|
@@ -10270,7 +10280,7 @@ const GET_RISK_FN = (dto, backtest, exchangeName, frameName, self) => {
|
|
|
10270
10280
|
* @param backtest - Whether running in backtest mode
|
|
10271
10281
|
* @returns Unique string key for memoization
|
|
10272
10282
|
*/
|
|
10273
|
-
const CREATE_KEY_FN$
|
|
10283
|
+
const CREATE_KEY_FN$v = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
10274
10284
|
const parts = [symbol, strategyName, exchangeName];
|
|
10275
10285
|
if (frameName)
|
|
10276
10286
|
parts.push(frameName);
|
|
@@ -10537,7 +10547,7 @@ class StrategyConnectionService {
|
|
|
10537
10547
|
* @param backtest - Whether running in backtest mode
|
|
10538
10548
|
* @returns Configured ClientStrategy instance
|
|
10539
10549
|
*/
|
|
10540
|
-
this.getStrategy = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
10550
|
+
this.getStrategy = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$v(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
10541
10551
|
const { riskName = "", riskList = [], getSignal, interval = STRATEGY_DEFAULT_INTERVAL, callbacks, } = this.strategySchemaService.get(strategyName);
|
|
10542
10552
|
return new ClientStrategy({
|
|
10543
10553
|
symbol,
|
|
@@ -11458,7 +11468,7 @@ class StrategyConnectionService {
|
|
|
11458
11468
|
}
|
|
11459
11469
|
return;
|
|
11460
11470
|
}
|
|
11461
|
-
const key = CREATE_KEY_FN$
|
|
11471
|
+
const key = CREATE_KEY_FN$v(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
11462
11472
|
if (!this.getStrategy.has(key)) {
|
|
11463
11473
|
return;
|
|
11464
11474
|
}
|
|
@@ -12627,7 +12637,7 @@ class ClientRisk {
|
|
|
12627
12637
|
* @param backtest - Whether running in backtest mode
|
|
12628
12638
|
* @returns Unique string key for memoization
|
|
12629
12639
|
*/
|
|
12630
|
-
const CREATE_KEY_FN$
|
|
12640
|
+
const CREATE_KEY_FN$u = (riskName, exchangeName, frameName, backtest) => {
|
|
12631
12641
|
const parts = [riskName, exchangeName];
|
|
12632
12642
|
if (frameName)
|
|
12633
12643
|
parts.push(frameName);
|
|
@@ -12727,7 +12737,7 @@ class RiskConnectionService {
|
|
|
12727
12737
|
* @param backtest - True if backtest mode, false if live mode
|
|
12728
12738
|
* @returns Configured ClientRisk instance
|
|
12729
12739
|
*/
|
|
12730
|
-
this.getRisk = memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
12740
|
+
this.getRisk = memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$u(riskName, exchangeName, frameName, backtest), (riskName, exchangeName, frameName, backtest) => {
|
|
12731
12741
|
const schema = this.riskSchemaService.get(riskName);
|
|
12732
12742
|
return new ClientRisk({
|
|
12733
12743
|
...schema,
|
|
@@ -12796,7 +12806,7 @@ class RiskConnectionService {
|
|
|
12796
12806
|
payload,
|
|
12797
12807
|
});
|
|
12798
12808
|
if (payload) {
|
|
12799
|
-
const key = CREATE_KEY_FN$
|
|
12809
|
+
const key = CREATE_KEY_FN$u(payload.riskName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
12800
12810
|
this.getRisk.clear(key);
|
|
12801
12811
|
}
|
|
12802
12812
|
else {
|
|
@@ -13840,7 +13850,7 @@ class ClientAction {
|
|
|
13840
13850
|
* @param backtest - Whether running in backtest mode
|
|
13841
13851
|
* @returns Unique string key for memoization
|
|
13842
13852
|
*/
|
|
13843
|
-
const CREATE_KEY_FN$
|
|
13853
|
+
const CREATE_KEY_FN$t = (actionName, strategyName, exchangeName, frameName, backtest) => {
|
|
13844
13854
|
const parts = [actionName, strategyName, exchangeName];
|
|
13845
13855
|
if (frameName)
|
|
13846
13856
|
parts.push(frameName);
|
|
@@ -13892,7 +13902,7 @@ class ActionConnectionService {
|
|
|
13892
13902
|
* @param backtest - True if backtest mode, false if live mode
|
|
13893
13903
|
* @returns Configured ClientAction instance
|
|
13894
13904
|
*/
|
|
13895
|
-
this.getAction = memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
13905
|
+
this.getAction = memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$t(actionName, strategyName, exchangeName, frameName, backtest), (actionName, strategyName, exchangeName, frameName, backtest) => {
|
|
13896
13906
|
const schema = this.actionSchemaService.get(actionName);
|
|
13897
13907
|
return new ClientAction({
|
|
13898
13908
|
...schema,
|
|
@@ -14103,7 +14113,7 @@ class ActionConnectionService {
|
|
|
14103
14113
|
await Promise.all(actions.map(async (action) => await action.dispose()));
|
|
14104
14114
|
return;
|
|
14105
14115
|
}
|
|
14106
|
-
const key = CREATE_KEY_FN$
|
|
14116
|
+
const key = CREATE_KEY_FN$t(payload.actionName, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
14107
14117
|
if (!this.getAction.has(key)) {
|
|
14108
14118
|
return;
|
|
14109
14119
|
}
|
|
@@ -14114,14 +14124,14 @@ class ActionConnectionService {
|
|
|
14114
14124
|
}
|
|
14115
14125
|
}
|
|
14116
14126
|
|
|
14117
|
-
const METHOD_NAME_VALIDATE$
|
|
14127
|
+
const METHOD_NAME_VALIDATE$3 = "exchangeCoreService validate";
|
|
14118
14128
|
/**
|
|
14119
14129
|
* Creates a unique key for memoizing validate calls.
|
|
14120
14130
|
* Key format: "exchangeName"
|
|
14121
14131
|
* @param exchangeName - Exchange name
|
|
14122
14132
|
* @returns Unique string key for memoization
|
|
14123
14133
|
*/
|
|
14124
|
-
const CREATE_KEY_FN$
|
|
14134
|
+
const CREATE_KEY_FN$s = (exchangeName) => {
|
|
14125
14135
|
return exchangeName;
|
|
14126
14136
|
};
|
|
14127
14137
|
/**
|
|
@@ -14145,11 +14155,11 @@ class ExchangeCoreService {
|
|
|
14145
14155
|
* @param exchangeName - Name of the exchange to validate
|
|
14146
14156
|
* @returns Promise that resolves when validation is complete
|
|
14147
14157
|
*/
|
|
14148
|
-
this.validate = memoize(([exchangeName]) => CREATE_KEY_FN$
|
|
14149
|
-
this.loggerService.log(METHOD_NAME_VALIDATE$
|
|
14158
|
+
this.validate = memoize(([exchangeName]) => CREATE_KEY_FN$s(exchangeName), async (exchangeName) => {
|
|
14159
|
+
this.loggerService.log(METHOD_NAME_VALIDATE$3, {
|
|
14150
14160
|
exchangeName,
|
|
14151
14161
|
});
|
|
14152
|
-
this.exchangeValidationService.validate(exchangeName, METHOD_NAME_VALIDATE$
|
|
14162
|
+
this.exchangeValidationService.validate(exchangeName, METHOD_NAME_VALIDATE$3);
|
|
14153
14163
|
});
|
|
14154
14164
|
/**
|
|
14155
14165
|
* Fetches historical candles with execution context.
|
|
@@ -14390,14 +14400,14 @@ class ExchangeCoreService {
|
|
|
14390
14400
|
}
|
|
14391
14401
|
}
|
|
14392
14402
|
|
|
14393
|
-
const METHOD_NAME_VALIDATE$
|
|
14403
|
+
const METHOD_NAME_VALIDATE$2 = "strategyCoreService validate";
|
|
14394
14404
|
/**
|
|
14395
14405
|
* Creates a unique key for memoizing validate calls.
|
|
14396
14406
|
* Key format: "strategyName:exchangeName:frameName"
|
|
14397
14407
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
14398
14408
|
* @returns Unique string key for memoization
|
|
14399
14409
|
*/
|
|
14400
|
-
const CREATE_KEY_FN$
|
|
14410
|
+
const CREATE_KEY_FN$r = (context) => {
|
|
14401
14411
|
const parts = [context.strategyName, context.exchangeName];
|
|
14402
14412
|
if (context.frameName)
|
|
14403
14413
|
parts.push(context.frameName);
|
|
@@ -14429,16 +14439,16 @@ class StrategyCoreService {
|
|
|
14429
14439
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
14430
14440
|
* @returns Promise that resolves when validation is complete
|
|
14431
14441
|
*/
|
|
14432
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
14433
|
-
this.loggerService.log(METHOD_NAME_VALIDATE$
|
|
14442
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$r(context), async (context) => {
|
|
14443
|
+
this.loggerService.log(METHOD_NAME_VALIDATE$2, {
|
|
14434
14444
|
context,
|
|
14435
14445
|
});
|
|
14436
14446
|
const { riskName, riskList } = this.strategySchemaService.get(context.strategyName);
|
|
14437
|
-
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$
|
|
14438
|
-
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$
|
|
14439
|
-
context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$
|
|
14440
|
-
riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$
|
|
14441
|
-
riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$
|
|
14447
|
+
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$2);
|
|
14448
|
+
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$2);
|
|
14449
|
+
context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$2);
|
|
14450
|
+
riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$2);
|
|
14451
|
+
riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$2));
|
|
14442
14452
|
});
|
|
14443
14453
|
/**
|
|
14444
14454
|
* Retrieves the currently active pending signal for the symbol.
|
|
@@ -15767,7 +15777,7 @@ class SizingGlobalService {
|
|
|
15767
15777
|
* @param context - Context with riskName, exchangeName, frameName
|
|
15768
15778
|
* @returns Unique string key for memoization
|
|
15769
15779
|
*/
|
|
15770
|
-
const CREATE_KEY_FN$
|
|
15780
|
+
const CREATE_KEY_FN$q = (context) => {
|
|
15771
15781
|
const parts = [context.riskName, context.exchangeName];
|
|
15772
15782
|
if (context.frameName)
|
|
15773
15783
|
parts.push(context.frameName);
|
|
@@ -15793,7 +15803,7 @@ class RiskGlobalService {
|
|
|
15793
15803
|
* @param payload - Payload with riskName, exchangeName and frameName
|
|
15794
15804
|
* @returns Promise that resolves when validation is complete
|
|
15795
15805
|
*/
|
|
15796
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
15806
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$q(context), async (context) => {
|
|
15797
15807
|
this.loggerService.log("riskGlobalService validate", {
|
|
15798
15808
|
context,
|
|
15799
15809
|
});
|
|
@@ -15864,14 +15874,14 @@ class RiskGlobalService {
|
|
|
15864
15874
|
}
|
|
15865
15875
|
}
|
|
15866
15876
|
|
|
15867
|
-
const METHOD_NAME_VALIDATE = "actionCoreService validate";
|
|
15877
|
+
const METHOD_NAME_VALIDATE$1 = "actionCoreService validate";
|
|
15868
15878
|
/**
|
|
15869
15879
|
* Creates a unique key for memoizing validate calls.
|
|
15870
15880
|
* Key format: "strategyName:exchangeName:frameName"
|
|
15871
15881
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
15872
15882
|
* @returns Unique string key for memoization
|
|
15873
15883
|
*/
|
|
15874
|
-
const CREATE_KEY_FN$
|
|
15884
|
+
const CREATE_KEY_FN$p = (context) => {
|
|
15875
15885
|
const parts = [context.strategyName, context.exchangeName];
|
|
15876
15886
|
if (context.frameName)
|
|
15877
15887
|
parts.push(context.frameName);
|
|
@@ -15915,17 +15925,17 @@ class ActionCoreService {
|
|
|
15915
15925
|
* @param context - Strategy execution context with strategyName, exchangeName and frameName
|
|
15916
15926
|
* @returns Promise that resolves when all validations complete
|
|
15917
15927
|
*/
|
|
15918
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
15919
|
-
this.loggerService.log(METHOD_NAME_VALIDATE, {
|
|
15928
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$p(context), async (context) => {
|
|
15929
|
+
this.loggerService.log(METHOD_NAME_VALIDATE$1, {
|
|
15920
15930
|
context,
|
|
15921
15931
|
});
|
|
15922
15932
|
const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
|
|
15923
|
-
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE);
|
|
15924
|
-
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE);
|
|
15925
|
-
context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE);
|
|
15926
|
-
riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE);
|
|
15927
|
-
riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE));
|
|
15928
|
-
actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE));
|
|
15933
|
+
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$1);
|
|
15934
|
+
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$1);
|
|
15935
|
+
context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$1);
|
|
15936
|
+
riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1);
|
|
15937
|
+
riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1));
|
|
15938
|
+
actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE$1));
|
|
15929
15939
|
});
|
|
15930
15940
|
/**
|
|
15931
15941
|
* Initializes all ClientAction instances for the strategy.
|
|
@@ -20958,7 +20968,7 @@ const ReportWriter = new ReportWriterAdapter();
|
|
|
20958
20968
|
* @param backtest - Whether running in backtest mode
|
|
20959
20969
|
* @returns Unique string key for memoization
|
|
20960
20970
|
*/
|
|
20961
|
-
const CREATE_KEY_FN$
|
|
20971
|
+
const CREATE_KEY_FN$o = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
20962
20972
|
const parts = [symbol, strategyName, exchangeName];
|
|
20963
20973
|
if (frameName)
|
|
20964
20974
|
parts.push(frameName);
|
|
@@ -21204,7 +21214,7 @@ class BacktestMarkdownService {
|
|
|
21204
21214
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
21205
21215
|
* Each combination gets its own isolated storage instance.
|
|
21206
21216
|
*/
|
|
21207
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
21217
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$o(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$a(symbol, strategyName, exchangeName, frameName));
|
|
21208
21218
|
/**
|
|
21209
21219
|
* Processes tick events and accumulates closed signals.
|
|
21210
21220
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -21361,7 +21371,7 @@ class BacktestMarkdownService {
|
|
|
21361
21371
|
payload,
|
|
21362
21372
|
});
|
|
21363
21373
|
if (payload) {
|
|
21364
|
-
const key = CREATE_KEY_FN$
|
|
21374
|
+
const key = CREATE_KEY_FN$o(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
21365
21375
|
this.getStorage.clear(key);
|
|
21366
21376
|
}
|
|
21367
21377
|
else {
|
|
@@ -21423,7 +21433,7 @@ class BacktestMarkdownService {
|
|
|
21423
21433
|
* @param backtest - Whether running in backtest mode
|
|
21424
21434
|
* @returns Unique string key for memoization
|
|
21425
21435
|
*/
|
|
21426
|
-
const CREATE_KEY_FN$
|
|
21436
|
+
const CREATE_KEY_FN$n = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
21427
21437
|
const parts = [symbol, strategyName, exchangeName];
|
|
21428
21438
|
if (frameName)
|
|
21429
21439
|
parts.push(frameName);
|
|
@@ -21918,7 +21928,7 @@ class LiveMarkdownService {
|
|
|
21918
21928
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
21919
21929
|
* Each combination gets its own isolated storage instance.
|
|
21920
21930
|
*/
|
|
21921
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
21931
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$n(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$9(symbol, strategyName, exchangeName, frameName));
|
|
21922
21932
|
/**
|
|
21923
21933
|
* Subscribes to live signal emitter to receive tick events.
|
|
21924
21934
|
* Protected against multiple subscriptions.
|
|
@@ -22136,7 +22146,7 @@ class LiveMarkdownService {
|
|
|
22136
22146
|
payload,
|
|
22137
22147
|
});
|
|
22138
22148
|
if (payload) {
|
|
22139
|
-
const key = CREATE_KEY_FN$
|
|
22149
|
+
const key = CREATE_KEY_FN$n(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
22140
22150
|
this.getStorage.clear(key);
|
|
22141
22151
|
}
|
|
22142
22152
|
else {
|
|
@@ -22156,7 +22166,7 @@ class LiveMarkdownService {
|
|
|
22156
22166
|
* @param backtest - Whether running in backtest mode
|
|
22157
22167
|
* @returns Unique string key for memoization
|
|
22158
22168
|
*/
|
|
22159
|
-
const CREATE_KEY_FN$
|
|
22169
|
+
const CREATE_KEY_FN$m = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
22160
22170
|
const parts = [symbol, strategyName, exchangeName];
|
|
22161
22171
|
if (frameName)
|
|
22162
22172
|
parts.push(frameName);
|
|
@@ -22445,7 +22455,7 @@ class ScheduleMarkdownService {
|
|
|
22445
22455
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
22446
22456
|
* Each combination gets its own isolated storage instance.
|
|
22447
22457
|
*/
|
|
22448
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
22458
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$m(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$8(symbol, strategyName, exchangeName, frameName));
|
|
22449
22459
|
/**
|
|
22450
22460
|
* Subscribes to signal emitter to receive scheduled signal events.
|
|
22451
22461
|
* Protected against multiple subscriptions.
|
|
@@ -22648,7 +22658,7 @@ class ScheduleMarkdownService {
|
|
|
22648
22658
|
payload,
|
|
22649
22659
|
});
|
|
22650
22660
|
if (payload) {
|
|
22651
|
-
const key = CREATE_KEY_FN$
|
|
22661
|
+
const key = CREATE_KEY_FN$m(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
22652
22662
|
this.getStorage.clear(key);
|
|
22653
22663
|
}
|
|
22654
22664
|
else {
|
|
@@ -22668,7 +22678,7 @@ class ScheduleMarkdownService {
|
|
|
22668
22678
|
* @param backtest - Whether running in backtest mode
|
|
22669
22679
|
* @returns Unique string key for memoization
|
|
22670
22680
|
*/
|
|
22671
|
-
const CREATE_KEY_FN$
|
|
22681
|
+
const CREATE_KEY_FN$l = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
22672
22682
|
const parts = [symbol, strategyName, exchangeName];
|
|
22673
22683
|
if (frameName)
|
|
22674
22684
|
parts.push(frameName);
|
|
@@ -22913,7 +22923,7 @@ class PerformanceMarkdownService {
|
|
|
22913
22923
|
* Memoized function to get or create PerformanceStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
22914
22924
|
* Each combination gets its own isolated storage instance.
|
|
22915
22925
|
*/
|
|
22916
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
22926
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$l(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new PerformanceStorage(symbol, strategyName, exchangeName, frameName));
|
|
22917
22927
|
/**
|
|
22918
22928
|
* Subscribes to performance emitter to receive performance events.
|
|
22919
22929
|
* Protected against multiple subscriptions.
|
|
@@ -23080,7 +23090,7 @@ class PerformanceMarkdownService {
|
|
|
23080
23090
|
payload,
|
|
23081
23091
|
});
|
|
23082
23092
|
if (payload) {
|
|
23083
|
-
const key = CREATE_KEY_FN$
|
|
23093
|
+
const key = CREATE_KEY_FN$l(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
23084
23094
|
this.getStorage.clear(key);
|
|
23085
23095
|
}
|
|
23086
23096
|
else {
|
|
@@ -23559,7 +23569,7 @@ class WalkerMarkdownService {
|
|
|
23559
23569
|
* @param backtest - Whether running in backtest mode
|
|
23560
23570
|
* @returns Unique string key for memoization
|
|
23561
23571
|
*/
|
|
23562
|
-
const CREATE_KEY_FN$
|
|
23572
|
+
const CREATE_KEY_FN$k = (exchangeName, frameName, backtest) => {
|
|
23563
23573
|
const parts = [exchangeName];
|
|
23564
23574
|
if (frameName)
|
|
23565
23575
|
parts.push(frameName);
|
|
@@ -24006,7 +24016,7 @@ class HeatMarkdownService {
|
|
|
24006
24016
|
* Memoized function to get or create HeatmapStorage for exchange, frame and backtest mode.
|
|
24007
24017
|
* Each exchangeName + frameName + backtest mode combination gets its own isolated heatmap storage instance.
|
|
24008
24018
|
*/
|
|
24009
|
-
this.getStorage = memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
24019
|
+
this.getStorage = memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$k(exchangeName, frameName, backtest), (exchangeName, frameName, backtest) => new HeatmapStorage(exchangeName, frameName, backtest));
|
|
24010
24020
|
/**
|
|
24011
24021
|
* Subscribes to signal emitter to receive tick events.
|
|
24012
24022
|
* Protected against multiple subscriptions.
|
|
@@ -24224,7 +24234,7 @@ class HeatMarkdownService {
|
|
|
24224
24234
|
payload,
|
|
24225
24235
|
});
|
|
24226
24236
|
if (payload) {
|
|
24227
|
-
const key = CREATE_KEY_FN$
|
|
24237
|
+
const key = CREATE_KEY_FN$k(payload.exchangeName, payload.frameName, payload.backtest);
|
|
24228
24238
|
this.getStorage.clear(key);
|
|
24229
24239
|
}
|
|
24230
24240
|
else {
|
|
@@ -25255,7 +25265,7 @@ class ClientPartial {
|
|
|
25255
25265
|
* @param backtest - Whether running in backtest mode
|
|
25256
25266
|
* @returns Unique string key for memoization
|
|
25257
25267
|
*/
|
|
25258
|
-
const CREATE_KEY_FN$
|
|
25268
|
+
const CREATE_KEY_FN$j = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
|
|
25259
25269
|
/**
|
|
25260
25270
|
* Creates a callback function for emitting profit events to partialProfitSubject.
|
|
25261
25271
|
*
|
|
@@ -25377,7 +25387,7 @@ class PartialConnectionService {
|
|
|
25377
25387
|
* Key format: "signalId:backtest" or "signalId:live"
|
|
25378
25388
|
* Value: ClientPartial instance with logger and event emitters
|
|
25379
25389
|
*/
|
|
25380
|
-
this.getPartial = memoize(([signalId, backtest]) => CREATE_KEY_FN$
|
|
25390
|
+
this.getPartial = memoize(([signalId, backtest]) => CREATE_KEY_FN$j(signalId, backtest), (signalId, backtest) => {
|
|
25381
25391
|
return new ClientPartial({
|
|
25382
25392
|
signalId,
|
|
25383
25393
|
logger: this.loggerService,
|
|
@@ -25467,7 +25477,7 @@ class PartialConnectionService {
|
|
|
25467
25477
|
const partial = this.getPartial(data.id, backtest);
|
|
25468
25478
|
await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
|
|
25469
25479
|
await partial.clear(symbol, data, priceClose, backtest);
|
|
25470
|
-
const key = CREATE_KEY_FN$
|
|
25480
|
+
const key = CREATE_KEY_FN$j(data.id, backtest);
|
|
25471
25481
|
this.getPartial.clear(key);
|
|
25472
25482
|
};
|
|
25473
25483
|
}
|
|
@@ -25483,7 +25493,7 @@ class PartialConnectionService {
|
|
|
25483
25493
|
* @param backtest - Whether running in backtest mode
|
|
25484
25494
|
* @returns Unique string key for memoization
|
|
25485
25495
|
*/
|
|
25486
|
-
const CREATE_KEY_FN$
|
|
25496
|
+
const CREATE_KEY_FN$i = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
25487
25497
|
const parts = [symbol, strategyName, exchangeName];
|
|
25488
25498
|
if (frameName)
|
|
25489
25499
|
parts.push(frameName);
|
|
@@ -25706,7 +25716,7 @@ class PartialMarkdownService {
|
|
|
25706
25716
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
25707
25717
|
* Each combination gets its own isolated storage instance.
|
|
25708
25718
|
*/
|
|
25709
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
25719
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$i(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$6(symbol, strategyName, exchangeName, frameName));
|
|
25710
25720
|
/**
|
|
25711
25721
|
* Subscribes to partial profit/loss signal emitters to receive events.
|
|
25712
25722
|
* Protected against multiple subscriptions.
|
|
@@ -25916,7 +25926,7 @@ class PartialMarkdownService {
|
|
|
25916
25926
|
payload,
|
|
25917
25927
|
});
|
|
25918
25928
|
if (payload) {
|
|
25919
|
-
const key = CREATE_KEY_FN$
|
|
25929
|
+
const key = CREATE_KEY_FN$i(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
25920
25930
|
this.getStorage.clear(key);
|
|
25921
25931
|
}
|
|
25922
25932
|
else {
|
|
@@ -25932,7 +25942,7 @@ class PartialMarkdownService {
|
|
|
25932
25942
|
* @param context - Context with strategyName, exchangeName, frameName
|
|
25933
25943
|
* @returns Unique string key for memoization
|
|
25934
25944
|
*/
|
|
25935
|
-
const CREATE_KEY_FN$
|
|
25945
|
+
const CREATE_KEY_FN$h = (context) => {
|
|
25936
25946
|
const parts = [context.strategyName, context.exchangeName];
|
|
25937
25947
|
if (context.frameName)
|
|
25938
25948
|
parts.push(context.frameName);
|
|
@@ -26006,7 +26016,7 @@ class PartialGlobalService {
|
|
|
26006
26016
|
* @param context - Context with strategyName, exchangeName and frameName
|
|
26007
26017
|
* @param methodName - Name of the calling method for error tracking
|
|
26008
26018
|
*/
|
|
26009
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
26019
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$h(context), (context, methodName) => {
|
|
26010
26020
|
this.loggerService.log("partialGlobalService validate", {
|
|
26011
26021
|
context,
|
|
26012
26022
|
methodName,
|
|
@@ -26461,7 +26471,7 @@ class ClientBreakeven {
|
|
|
26461
26471
|
* @param backtest - Whether running in backtest mode
|
|
26462
26472
|
* @returns Unique string key for memoization
|
|
26463
26473
|
*/
|
|
26464
|
-
const CREATE_KEY_FN$
|
|
26474
|
+
const CREATE_KEY_FN$g = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
|
|
26465
26475
|
/**
|
|
26466
26476
|
* Creates a callback function for emitting breakeven events to breakevenSubject.
|
|
26467
26477
|
*
|
|
@@ -26547,7 +26557,7 @@ class BreakevenConnectionService {
|
|
|
26547
26557
|
* Key format: "signalId:backtest" or "signalId:live"
|
|
26548
26558
|
* Value: ClientBreakeven instance with logger and event emitter
|
|
26549
26559
|
*/
|
|
26550
|
-
this.getBreakeven = memoize(([signalId, backtest]) => CREATE_KEY_FN$
|
|
26560
|
+
this.getBreakeven = memoize(([signalId, backtest]) => CREATE_KEY_FN$g(signalId, backtest), (signalId, backtest) => {
|
|
26551
26561
|
return new ClientBreakeven({
|
|
26552
26562
|
signalId,
|
|
26553
26563
|
logger: this.loggerService,
|
|
@@ -26608,7 +26618,7 @@ class BreakevenConnectionService {
|
|
|
26608
26618
|
const breakeven = this.getBreakeven(data.id, backtest);
|
|
26609
26619
|
await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
|
|
26610
26620
|
await breakeven.clear(symbol, data, priceClose, backtest);
|
|
26611
|
-
const key = CREATE_KEY_FN$
|
|
26621
|
+
const key = CREATE_KEY_FN$g(data.id, backtest);
|
|
26612
26622
|
this.getBreakeven.clear(key);
|
|
26613
26623
|
};
|
|
26614
26624
|
}
|
|
@@ -26624,7 +26634,7 @@ class BreakevenConnectionService {
|
|
|
26624
26634
|
* @param backtest - Whether running in backtest mode
|
|
26625
26635
|
* @returns Unique string key for memoization
|
|
26626
26636
|
*/
|
|
26627
|
-
const CREATE_KEY_FN$
|
|
26637
|
+
const CREATE_KEY_FN$f = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
26628
26638
|
const parts = [symbol, strategyName, exchangeName];
|
|
26629
26639
|
if (frameName)
|
|
26630
26640
|
parts.push(frameName);
|
|
@@ -26799,7 +26809,7 @@ class BreakevenMarkdownService {
|
|
|
26799
26809
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
26800
26810
|
* Each combination gets its own isolated storage instance.
|
|
26801
26811
|
*/
|
|
26802
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
26812
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$f(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$5(symbol, strategyName, exchangeName, frameName));
|
|
26803
26813
|
/**
|
|
26804
26814
|
* Subscribes to breakeven signal emitter to receive events.
|
|
26805
26815
|
* Protected against multiple subscriptions.
|
|
@@ -26988,7 +26998,7 @@ class BreakevenMarkdownService {
|
|
|
26988
26998
|
payload,
|
|
26989
26999
|
});
|
|
26990
27000
|
if (payload) {
|
|
26991
|
-
const key = CREATE_KEY_FN$
|
|
27001
|
+
const key = CREATE_KEY_FN$f(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
26992
27002
|
this.getStorage.clear(key);
|
|
26993
27003
|
}
|
|
26994
27004
|
else {
|
|
@@ -27004,7 +27014,7 @@ class BreakevenMarkdownService {
|
|
|
27004
27014
|
* @param context - Context with strategyName, exchangeName, frameName
|
|
27005
27015
|
* @returns Unique string key for memoization
|
|
27006
27016
|
*/
|
|
27007
|
-
const CREATE_KEY_FN$
|
|
27017
|
+
const CREATE_KEY_FN$e = (context) => {
|
|
27008
27018
|
const parts = [context.strategyName, context.exchangeName];
|
|
27009
27019
|
if (context.frameName)
|
|
27010
27020
|
parts.push(context.frameName);
|
|
@@ -27078,7 +27088,7 @@ class BreakevenGlobalService {
|
|
|
27078
27088
|
* @param context - Context with strategyName, exchangeName and frameName
|
|
27079
27089
|
* @param methodName - Name of the calling method for error tracking
|
|
27080
27090
|
*/
|
|
27081
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
27091
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$e(context), (context, methodName) => {
|
|
27082
27092
|
this.loggerService.log("breakevenGlobalService validate", {
|
|
27083
27093
|
context,
|
|
27084
27094
|
methodName,
|
|
@@ -27299,7 +27309,7 @@ class ConfigValidationService {
|
|
|
27299
27309
|
* @param backtest - Whether running in backtest mode
|
|
27300
27310
|
* @returns Unique string key for memoization
|
|
27301
27311
|
*/
|
|
27302
|
-
const CREATE_KEY_FN$
|
|
27312
|
+
const CREATE_KEY_FN$d = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
27303
27313
|
const parts = [symbol, strategyName, exchangeName];
|
|
27304
27314
|
if (frameName)
|
|
27305
27315
|
parts.push(frameName);
|
|
@@ -27466,7 +27476,7 @@ class RiskMarkdownService {
|
|
|
27466
27476
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
27467
27477
|
* Each combination gets its own isolated storage instance.
|
|
27468
27478
|
*/
|
|
27469
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
27479
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$d(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$4(symbol, strategyName, exchangeName, frameName));
|
|
27470
27480
|
/**
|
|
27471
27481
|
* Subscribes to risk rejection emitter to receive rejection events.
|
|
27472
27482
|
* Protected against multiple subscriptions.
|
|
@@ -27655,7 +27665,7 @@ class RiskMarkdownService {
|
|
|
27655
27665
|
payload,
|
|
27656
27666
|
});
|
|
27657
27667
|
if (payload) {
|
|
27658
|
-
const key = CREATE_KEY_FN$
|
|
27668
|
+
const key = CREATE_KEY_FN$d(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
27659
27669
|
this.getStorage.clear(key);
|
|
27660
27670
|
}
|
|
27661
27671
|
else {
|
|
@@ -30037,7 +30047,7 @@ class HighestProfitReportService {
|
|
|
30037
30047
|
* @returns Colon-separated key string for memoization
|
|
30038
30048
|
* @internal
|
|
30039
30049
|
*/
|
|
30040
|
-
const CREATE_KEY_FN$
|
|
30050
|
+
const CREATE_KEY_FN$c = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
30041
30051
|
const parts = [symbol, strategyName, exchangeName];
|
|
30042
30052
|
if (frameName)
|
|
30043
30053
|
parts.push(frameName);
|
|
@@ -30279,7 +30289,7 @@ class StrategyMarkdownService {
|
|
|
30279
30289
|
*
|
|
30280
30290
|
* @internal
|
|
30281
30291
|
*/
|
|
30282
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
30292
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$c(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$3(symbol, strategyName, exchangeName, frameName));
|
|
30283
30293
|
/**
|
|
30284
30294
|
* Records a cancel-scheduled event when a scheduled signal is cancelled.
|
|
30285
30295
|
*
|
|
@@ -30853,7 +30863,7 @@ class StrategyMarkdownService {
|
|
|
30853
30863
|
this.clear = async (payload) => {
|
|
30854
30864
|
this.loggerService.log("strategyMarkdownService clear", { payload });
|
|
30855
30865
|
if (payload) {
|
|
30856
|
-
const key = CREATE_KEY_FN$
|
|
30866
|
+
const key = CREATE_KEY_FN$c(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
30857
30867
|
this.getStorage.clear(key);
|
|
30858
30868
|
}
|
|
30859
30869
|
else {
|
|
@@ -30961,7 +30971,7 @@ class StrategyMarkdownService {
|
|
|
30961
30971
|
* Creates a unique key for memoizing ReportStorage instances.
|
|
30962
30972
|
* Key format: "symbol:strategyName:exchangeName[:frameName]:backtest|live"
|
|
30963
30973
|
*/
|
|
30964
|
-
const CREATE_KEY_FN$
|
|
30974
|
+
const CREATE_KEY_FN$b = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
30965
30975
|
const parts = [symbol, strategyName, exchangeName];
|
|
30966
30976
|
if (frameName)
|
|
30967
30977
|
parts.push(frameName);
|
|
@@ -31154,7 +31164,7 @@ let ReportStorage$2 = class ReportStorage {
|
|
|
31154
31164
|
class SyncMarkdownService {
|
|
31155
31165
|
constructor() {
|
|
31156
31166
|
this.loggerService = inject(TYPES.loggerService);
|
|
31157
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
31167
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$b(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$2(symbol, strategyName, exchangeName, frameName, backtest));
|
|
31158
31168
|
/**
|
|
31159
31169
|
* Subscribes to `syncSubject` to start receiving `SignalSyncContract` events.
|
|
31160
31170
|
* Protected against multiple subscriptions via `singleshot` — subsequent calls
|
|
@@ -31350,7 +31360,7 @@ class SyncMarkdownService {
|
|
|
31350
31360
|
this.clear = async (payload) => {
|
|
31351
31361
|
this.loggerService.log("syncMarkdownService clear", { payload });
|
|
31352
31362
|
if (payload) {
|
|
31353
|
-
const key = CREATE_KEY_FN$
|
|
31363
|
+
const key = CREATE_KEY_FN$b(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
31354
31364
|
this.getStorage.clear(key);
|
|
31355
31365
|
}
|
|
31356
31366
|
else {
|
|
@@ -31363,7 +31373,7 @@ class SyncMarkdownService {
|
|
|
31363
31373
|
/**
|
|
31364
31374
|
* Creates a unique memoization key for a symbol-strategy-exchange-frame-backtest combination.
|
|
31365
31375
|
*/
|
|
31366
|
-
const CREATE_KEY_FN$
|
|
31376
|
+
const CREATE_KEY_FN$a = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
31367
31377
|
const parts = [symbol, strategyName, exchangeName];
|
|
31368
31378
|
if (frameName)
|
|
31369
31379
|
parts.push(frameName);
|
|
@@ -31539,7 +31549,7 @@ let ReportStorage$1 = class ReportStorage {
|
|
|
31539
31549
|
class HighestProfitMarkdownService {
|
|
31540
31550
|
constructor() {
|
|
31541
31551
|
this.loggerService = inject(TYPES.loggerService);
|
|
31542
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
31552
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$a(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$1(symbol, strategyName, exchangeName, frameName));
|
|
31543
31553
|
/**
|
|
31544
31554
|
* Subscribes to `highestProfitSubject` to start receiving `HighestProfitContract`
|
|
31545
31555
|
* events. Protected against multiple subscriptions via `singleshot` — subsequent
|
|
@@ -31705,7 +31715,7 @@ class HighestProfitMarkdownService {
|
|
|
31705
31715
|
this.clear = async (payload) => {
|
|
31706
31716
|
this.loggerService.log("highestProfitMarkdownService clear", { payload });
|
|
31707
31717
|
if (payload) {
|
|
31708
|
-
const key = CREATE_KEY_FN$
|
|
31718
|
+
const key = CREATE_KEY_FN$a(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
31709
31719
|
this.getStorage.clear(key);
|
|
31710
31720
|
}
|
|
31711
31721
|
else {
|
|
@@ -31727,7 +31737,7 @@ const LISTEN_TIMEOUT$1 = 120000;
|
|
|
31727
31737
|
* @param backtest - Whether running in backtest mode
|
|
31728
31738
|
* @returns Unique string key for memoization
|
|
31729
31739
|
*/
|
|
31730
|
-
const CREATE_KEY_FN$
|
|
31740
|
+
const CREATE_KEY_FN$9 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
31731
31741
|
const parts = [symbol, strategyName, exchangeName];
|
|
31732
31742
|
if (frameName)
|
|
31733
31743
|
parts.push(frameName);
|
|
@@ -31770,7 +31780,7 @@ class PriceMetaService {
|
|
|
31770
31780
|
* Each subject holds the latest currentPrice emitted by the strategy iterator for that key.
|
|
31771
31781
|
* Instances are cached until clear() is called.
|
|
31772
31782
|
*/
|
|
31773
|
-
this.getSource = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
31783
|
+
this.getSource = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$9(symbol, strategyName, exchangeName, frameName, backtest), () => new BehaviorSubject());
|
|
31774
31784
|
/**
|
|
31775
31785
|
* Returns the current market price for the given symbol and context.
|
|
31776
31786
|
*
|
|
@@ -31799,10 +31809,10 @@ class PriceMetaService {
|
|
|
31799
31809
|
if (source.data) {
|
|
31800
31810
|
return source.data;
|
|
31801
31811
|
}
|
|
31802
|
-
console.warn(`PriceMetaService: No currentPrice available for ${CREATE_KEY_FN$
|
|
31812
|
+
console.warn(`PriceMetaService: No currentPrice available for ${CREATE_KEY_FN$9(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}. Trying to fetch from strategy iterator as a fallback...`);
|
|
31803
31813
|
const currentPrice = await waitForNext(source, (data) => !!data, LISTEN_TIMEOUT$1);
|
|
31804
31814
|
if (typeof currentPrice === "symbol") {
|
|
31805
|
-
throw new Error(`PriceMetaService: Timeout while waiting for currentPrice for ${CREATE_KEY_FN$
|
|
31815
|
+
throw new Error(`PriceMetaService: Timeout while waiting for currentPrice for ${CREATE_KEY_FN$9(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
|
|
31806
31816
|
}
|
|
31807
31817
|
return currentPrice;
|
|
31808
31818
|
};
|
|
@@ -31844,7 +31854,7 @@ class PriceMetaService {
|
|
|
31844
31854
|
this.getSource.clear();
|
|
31845
31855
|
return;
|
|
31846
31856
|
}
|
|
31847
|
-
const key = CREATE_KEY_FN$
|
|
31857
|
+
const key = CREATE_KEY_FN$9(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
31848
31858
|
this.getSource.clear(key);
|
|
31849
31859
|
};
|
|
31850
31860
|
}
|
|
@@ -31862,7 +31872,7 @@ const LISTEN_TIMEOUT = 120000;
|
|
|
31862
31872
|
* @param backtest - Whether running in backtest mode
|
|
31863
31873
|
* @returns Unique string key for memoization
|
|
31864
31874
|
*/
|
|
31865
|
-
const CREATE_KEY_FN$
|
|
31875
|
+
const CREATE_KEY_FN$8 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
31866
31876
|
const parts = [symbol, strategyName, exchangeName];
|
|
31867
31877
|
if (frameName)
|
|
31868
31878
|
parts.push(frameName);
|
|
@@ -31905,7 +31915,7 @@ class TimeMetaService {
|
|
|
31905
31915
|
* Each subject holds the latest createdAt timestamp emitted by the strategy iterator for that key.
|
|
31906
31916
|
* Instances are cached until clear() is called.
|
|
31907
31917
|
*/
|
|
31908
|
-
this.getSource = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
31918
|
+
this.getSource = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$8(symbol, strategyName, exchangeName, frameName, backtest), () => new BehaviorSubject());
|
|
31909
31919
|
/**
|
|
31910
31920
|
* Returns the current candle timestamp (in milliseconds) for the given symbol and context.
|
|
31911
31921
|
*
|
|
@@ -31933,10 +31943,10 @@ class TimeMetaService {
|
|
|
31933
31943
|
if (source.data) {
|
|
31934
31944
|
return source.data;
|
|
31935
31945
|
}
|
|
31936
|
-
console.warn(`TimeMetaService: No timestamp available for ${CREATE_KEY_FN$
|
|
31946
|
+
console.warn(`TimeMetaService: No timestamp available for ${CREATE_KEY_FN$8(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}. Trying to fetch from strategy iterator as a fallback...`);
|
|
31937
31947
|
const timestamp = await waitForNext(source, (data) => !!data, LISTEN_TIMEOUT);
|
|
31938
31948
|
if (typeof timestamp === "symbol") {
|
|
31939
|
-
throw new Error(`TimeMetaService: Timeout while waiting for timestamp for ${CREATE_KEY_FN$
|
|
31949
|
+
throw new Error(`TimeMetaService: Timeout while waiting for timestamp for ${CREATE_KEY_FN$8(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
|
|
31940
31950
|
}
|
|
31941
31951
|
return timestamp;
|
|
31942
31952
|
};
|
|
@@ -31978,7 +31988,7 @@ class TimeMetaService {
|
|
|
31978
31988
|
this.getSource.clear();
|
|
31979
31989
|
return;
|
|
31980
31990
|
}
|
|
31981
|
-
const key = CREATE_KEY_FN$
|
|
31991
|
+
const key = CREATE_KEY_FN$8(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
31982
31992
|
this.getSource.clear(key);
|
|
31983
31993
|
};
|
|
31984
31994
|
}
|
|
@@ -32074,7 +32084,7 @@ class MaxDrawdownReportService {
|
|
|
32074
32084
|
/**
|
|
32075
32085
|
* Creates a unique memoization key for a symbol-strategy-exchange-frame-backtest combination.
|
|
32076
32086
|
*/
|
|
32077
|
-
const CREATE_KEY_FN$
|
|
32087
|
+
const CREATE_KEY_FN$7 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
32078
32088
|
const parts = [symbol, strategyName, exchangeName];
|
|
32079
32089
|
if (frameName)
|
|
32080
32090
|
parts.push(frameName);
|
|
@@ -32198,7 +32208,7 @@ class ReportStorage {
|
|
|
32198
32208
|
class MaxDrawdownMarkdownService {
|
|
32199
32209
|
constructor() {
|
|
32200
32210
|
this.loggerService = inject(TYPES.loggerService);
|
|
32201
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
32211
|
+
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$7(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage(symbol, strategyName, exchangeName, frameName));
|
|
32202
32212
|
/**
|
|
32203
32213
|
* Subscribes to `maxDrawdownSubject` to start receiving `MaxDrawdownContract`
|
|
32204
32214
|
* events. Protected against multiple subscriptions via `singleshot`.
|
|
@@ -32277,7 +32287,7 @@ class MaxDrawdownMarkdownService {
|
|
|
32277
32287
|
this.clear = async (payload) => {
|
|
32278
32288
|
this.loggerService.log("maxDrawdownMarkdownService clear", { payload });
|
|
32279
32289
|
if (payload) {
|
|
32280
|
-
const key = CREATE_KEY_FN$
|
|
32290
|
+
const key = CREATE_KEY_FN$7(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
32281
32291
|
this.getStorage.clear(key);
|
|
32282
32292
|
}
|
|
32283
32293
|
else {
|
|
@@ -32287,6 +32297,125 @@ class MaxDrawdownMarkdownService {
|
|
|
32287
32297
|
}
|
|
32288
32298
|
}
|
|
32289
32299
|
|
|
32300
|
+
const METHOD_NAME_COMMIT_SIGNAL_NOTIFY = "notificationHelperService.commitSignalNotify";
|
|
32301
|
+
const METHOD_NAME_VALIDATE = "notificationHelperService.validate";
|
|
32302
|
+
/**
|
|
32303
|
+
* Creates a unique key for memoizing validate calls.
|
|
32304
|
+
* Key format: "strategyName:exchangeName:frameName"
|
|
32305
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
32306
|
+
* @returns Unique string key for memoization
|
|
32307
|
+
*/
|
|
32308
|
+
const CREATE_KEY_FN$6 = (context) => {
|
|
32309
|
+
const parts = [context.strategyName, context.exchangeName];
|
|
32310
|
+
if (context.frameName)
|
|
32311
|
+
parts.push(context.frameName);
|
|
32312
|
+
return parts.join(":");
|
|
32313
|
+
};
|
|
32314
|
+
/**
|
|
32315
|
+
* Helper service for emitting signal info notifications.
|
|
32316
|
+
*
|
|
32317
|
+
* Handles validation (memoized per context) and emission of `signal.info` events
|
|
32318
|
+
* via `signalNotifySubject`. Used internally by the framework action pipeline —
|
|
32319
|
+
* end users interact with this via `commitSignalNotify()` in `onActivePing` callbacks.
|
|
32320
|
+
*/
|
|
32321
|
+
class NotificationHelperService {
|
|
32322
|
+
constructor() {
|
|
32323
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
32324
|
+
this.strategySchemaService = inject(TYPES.strategySchemaService);
|
|
32325
|
+
this.riskValidationService = inject(TYPES.riskValidationService);
|
|
32326
|
+
this.strategyValidationService = inject(TYPES.strategyValidationService);
|
|
32327
|
+
this.exchangeValidationService = inject(TYPES.exchangeValidationService);
|
|
32328
|
+
this.frameValidationService = inject(TYPES.frameValidationService);
|
|
32329
|
+
this.actionValidationService = inject(TYPES.actionValidationService);
|
|
32330
|
+
this.strategyCoreService = inject(TYPES.strategyCoreService);
|
|
32331
|
+
this.timeMetaService = inject(TYPES.timeMetaService);
|
|
32332
|
+
/**
|
|
32333
|
+
* Validates strategy, exchange, frame, risk, and action schemas for the given context.
|
|
32334
|
+
*
|
|
32335
|
+
* Memoized per unique `"strategyName:exchangeName[:frameName]"` key — subsequent calls
|
|
32336
|
+
* with the same context are no-ops, so validation runs at most once per context.
|
|
32337
|
+
*
|
|
32338
|
+
* @param context - Routing context: strategyName, exchangeName, frameName
|
|
32339
|
+
* @throws {Error} If any registered schema fails validation
|
|
32340
|
+
*/
|
|
32341
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$6(context), async (context) => {
|
|
32342
|
+
this.loggerService.log(METHOD_NAME_VALIDATE, {
|
|
32343
|
+
context,
|
|
32344
|
+
});
|
|
32345
|
+
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE);
|
|
32346
|
+
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE);
|
|
32347
|
+
const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
|
|
32348
|
+
context.frameName &&
|
|
32349
|
+
this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE);
|
|
32350
|
+
riskName &&
|
|
32351
|
+
this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE);
|
|
32352
|
+
riskList &&
|
|
32353
|
+
riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE));
|
|
32354
|
+
actions &&
|
|
32355
|
+
actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE));
|
|
32356
|
+
});
|
|
32357
|
+
/**
|
|
32358
|
+
* Emits a `signal.info` notification for the currently active pending signal.
|
|
32359
|
+
*
|
|
32360
|
+
* Validates all schemas (via memoized `validate`), resolves the pending signal
|
|
32361
|
+
* for the given symbol, then emits a `SignalInfoContract` via `signalNotifySubject`,
|
|
32362
|
+
* which is routed to all registered `listenSignalNotify` callbacks and persisted
|
|
32363
|
+
* by `NotificationAdapter`.
|
|
32364
|
+
*
|
|
32365
|
+
* @param payload - Optional notification fields (notificationId, notificationNote)
|
|
32366
|
+
* @param symbol - Trading pair symbol (e.g. "BTCUSDT")
|
|
32367
|
+
* @param currentPrice - Market price at the time of the call
|
|
32368
|
+
* @param context - Routing context: strategyName, exchangeName, frameName
|
|
32369
|
+
* @param backtest - true when called during a backtest run
|
|
32370
|
+
*
|
|
32371
|
+
* @throws {Error} If no active pending signal is found for the given symbol
|
|
32372
|
+
*
|
|
32373
|
+
* @example
|
|
32374
|
+
* ```typescript
|
|
32375
|
+
* // Inside onActivePing callback:
|
|
32376
|
+
* await commitSignalNotify("BTCUSDT", {
|
|
32377
|
+
* notificationNote: "RSI crossed 70, consider closing",
|
|
32378
|
+
* notificationId: "msg-123",
|
|
32379
|
+
* });
|
|
32380
|
+
* ```
|
|
32381
|
+
*/
|
|
32382
|
+
this.commitSignalNotify = async (payload, symbol, currentPrice, context, backtest) => {
|
|
32383
|
+
this.loggerService.info(METHOD_NAME_COMMIT_SIGNAL_NOTIFY, {
|
|
32384
|
+
symbol,
|
|
32385
|
+
context,
|
|
32386
|
+
backtest,
|
|
32387
|
+
currentPrice,
|
|
32388
|
+
});
|
|
32389
|
+
this.validate(context);
|
|
32390
|
+
const pendingSignal = await this.strategyCoreService.getPendingSignal(backtest, symbol, currentPrice, {
|
|
32391
|
+
strategyName: context.strategyName,
|
|
32392
|
+
exchangeName: context.exchangeName,
|
|
32393
|
+
frameName: "",
|
|
32394
|
+
});
|
|
32395
|
+
if (!pendingSignal) {
|
|
32396
|
+
throw new Error(`SignalUtils notify No pending signal found symbol=${symbol} `);
|
|
32397
|
+
}
|
|
32398
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, {
|
|
32399
|
+
strategyName: context.strategyName,
|
|
32400
|
+
exchangeName: context.exchangeName,
|
|
32401
|
+
frameName: context.frameName,
|
|
32402
|
+
}, backtest);
|
|
32403
|
+
await signalNotifySubject.next({
|
|
32404
|
+
backtest,
|
|
32405
|
+
symbol,
|
|
32406
|
+
currentPrice,
|
|
32407
|
+
data: pendingSignal,
|
|
32408
|
+
exchangeName: context.exchangeName,
|
|
32409
|
+
strategyName: context.strategyName,
|
|
32410
|
+
frameName: context.frameName,
|
|
32411
|
+
note: payload.notificationNote || pendingSignal.note,
|
|
32412
|
+
notificationId: payload.notificationId,
|
|
32413
|
+
timestamp,
|
|
32414
|
+
});
|
|
32415
|
+
};
|
|
32416
|
+
}
|
|
32417
|
+
}
|
|
32418
|
+
|
|
32290
32419
|
{
|
|
32291
32420
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
32292
32421
|
}
|
|
@@ -32375,6 +32504,9 @@ class MaxDrawdownMarkdownService {
|
|
|
32375
32504
|
provide(TYPES.highestProfitReportService, () => new HighestProfitReportService());
|
|
32376
32505
|
provide(TYPES.maxDrawdownReportService, () => new MaxDrawdownReportService());
|
|
32377
32506
|
}
|
|
32507
|
+
{
|
|
32508
|
+
provide(TYPES.notificationHelperService, () => new NotificationHelperService());
|
|
32509
|
+
}
|
|
32378
32510
|
{
|
|
32379
32511
|
provide(TYPES.exchangeValidationService, () => new ExchangeValidationService());
|
|
32380
32512
|
provide(TYPES.strategyValidationService, () => new StrategyValidationService());
|
|
@@ -32475,6 +32607,9 @@ const reportServices = {
|
|
|
32475
32607
|
highestProfitReportService: inject(TYPES.highestProfitReportService),
|
|
32476
32608
|
maxDrawdownReportService: inject(TYPES.maxDrawdownReportService),
|
|
32477
32609
|
};
|
|
32610
|
+
const helperServices = {
|
|
32611
|
+
notificationHelperService: inject(TYPES.notificationHelperService),
|
|
32612
|
+
};
|
|
32478
32613
|
const validationServices = {
|
|
32479
32614
|
exchangeValidationService: inject(TYPES.exchangeValidationService),
|
|
32480
32615
|
strategyValidationService: inject(TYPES.strategyValidationService),
|
|
@@ -32500,6 +32635,7 @@ const backtest = {
|
|
|
32500
32635
|
...markdownServices,
|
|
32501
32636
|
...reportServices,
|
|
32502
32637
|
...validationServices,
|
|
32638
|
+
...helperServices,
|
|
32503
32639
|
};
|
|
32504
32640
|
init();
|
|
32505
32641
|
|
|
@@ -35416,6 +35552,7 @@ const GET_POSITION_ENTRY_OVERLAP_METHOD_NAME = "strategy.getPositionEntryOverlap
|
|
|
35416
35552
|
const GET_POSITION_PARTIAL_OVERLAP_METHOD_NAME = "strategy.getPositionPartialOverlap";
|
|
35417
35553
|
const HAS_NO_PENDING_SIGNAL_METHOD_NAME = "strategy.hasNoPendingSignal";
|
|
35418
35554
|
const HAS_NO_SCHEDULED_SIGNAL_METHOD_NAME = "strategy.hasNoScheduledSignal";
|
|
35555
|
+
const COMMIT_SIGNAL_NOTIFY_METHOD_NAME = "strategy.commitSignalNotify";
|
|
35419
35556
|
/**
|
|
35420
35557
|
* Cancels the scheduled signal without stopping the strategy.
|
|
35421
35558
|
*
|
|
@@ -37380,6 +37517,50 @@ async function hasNoScheduledSignal(symbol) {
|
|
|
37380
37517
|
const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
|
|
37381
37518
|
return await not(backtest.strategyCoreService.hasScheduledSignal(isBacktest, symbol, { exchangeName, frameName, strategyName }));
|
|
37382
37519
|
}
|
|
37520
|
+
/**
|
|
37521
|
+
* Emits a `signal.info` notification for the currently active pending signal.
|
|
37522
|
+
*
|
|
37523
|
+
* Broadcasts a user-defined informational note without affecting position state.
|
|
37524
|
+
* Useful for annotating strategy decisions, triggering external alerts, or logging
|
|
37525
|
+
* mid-position events (e.g. RSI crossing a threshold, volume spike detected).
|
|
37526
|
+
*
|
|
37527
|
+
* Automatically reads backtest/live mode from execution context.
|
|
37528
|
+
* Automatically reads strategyName, exchangeName, frameName from method context.
|
|
37529
|
+
* Automatically fetches current price via getAveragePrice.
|
|
37530
|
+
*
|
|
37531
|
+
* @param symbol - Trading pair symbol (e.g. "BTCUSDT")
|
|
37532
|
+
* @param payload - Optional notification fields
|
|
37533
|
+
* @param payload.notificationNote - Human-readable note. Falls back to signal.note if omitted.
|
|
37534
|
+
* @param payload.notificationId - Optional correlation ID for external systems (e.g. Telegram message ID).
|
|
37535
|
+
*
|
|
37536
|
+
* @throws {Error} If called outside an execution context
|
|
37537
|
+
* @throws {Error} If called outside a method context
|
|
37538
|
+
* @throws {Error} If no active pending signal exists for the given symbol
|
|
37539
|
+
*
|
|
37540
|
+
* @example
|
|
37541
|
+
* ```typescript
|
|
37542
|
+
* import { commitSignalNotify } from "backtest-kit";
|
|
37543
|
+
*
|
|
37544
|
+
* // Inside onActivePing callback:
|
|
37545
|
+
* await commitSignalNotify("BTCUSDT", {
|
|
37546
|
+
* notificationNote: "RSI crossed 70, consider closing",
|
|
37547
|
+
* notificationId: "msg-123",
|
|
37548
|
+
* });
|
|
37549
|
+
* ```
|
|
37550
|
+
*/
|
|
37551
|
+
async function commitSignalNotify(symbol, payload = {}) {
|
|
37552
|
+
backtest.loggerService.info(COMMIT_SIGNAL_NOTIFY_METHOD_NAME, { symbol, payload });
|
|
37553
|
+
if (!ExecutionContextService.hasContext()) {
|
|
37554
|
+
throw new Error("commitSignalNotify requires an execution context");
|
|
37555
|
+
}
|
|
37556
|
+
if (!MethodContextService.hasContext()) {
|
|
37557
|
+
throw new Error("commitSignalNotify requires a method context");
|
|
37558
|
+
}
|
|
37559
|
+
const currentPrice = await getAveragePrice(symbol);
|
|
37560
|
+
const { backtest: isBacktest } = backtest.executionContextService.context;
|
|
37561
|
+
const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
|
|
37562
|
+
await backtest.notificationHelperService.commitSignalNotify(payload, symbol, currentPrice, { strategyName, exchangeName, frameName }, isBacktest);
|
|
37563
|
+
}
|
|
37383
37564
|
|
|
37384
37565
|
const STOP_STRATEGY_METHOD_NAME = "control.stopStrategy";
|
|
37385
37566
|
/**
|
|
@@ -37463,6 +37644,8 @@ const LISTEN_HIGHEST_PROFIT_METHOD_NAME = "event.listenHighestProfit";
|
|
|
37463
37644
|
const LISTEN_HIGHEST_PROFIT_ONCE_METHOD_NAME = "event.listenHighestProfitOnce";
|
|
37464
37645
|
const LISTEN_MAX_DRAWDOWN_METHOD_NAME = "event.listenMaxDrawdown";
|
|
37465
37646
|
const LISTEN_MAX_DRAWDOWN_ONCE_METHOD_NAME = "event.listenMaxDrawdownOnce";
|
|
37647
|
+
const LISTEN_SIGNAL_NOTIFY_METHOD_NAME = "event.listenSignalNotify";
|
|
37648
|
+
const LISTEN_SIGNAL_NOTIFY_ONCE_METHOD_NAME = "event.listenSignalNotifyOnce";
|
|
37466
37649
|
/**
|
|
37467
37650
|
* Subscribes to all signal events with queued async processing.
|
|
37468
37651
|
*
|
|
@@ -38854,6 +39037,46 @@ function listenMaxDrawdownOnce(filterFn, fn) {
|
|
|
38854
39037
|
};
|
|
38855
39038
|
return disposeFn = listenMaxDrawdown(wrappedFn);
|
|
38856
39039
|
}
|
|
39040
|
+
/**
|
|
39041
|
+
* Subscribes to signal info events with queued async processing.
|
|
39042
|
+
* Emits when a strategy calls commitSignalInfo() to broadcast a user-defined note for an open position.
|
|
39043
|
+
* Events are processed sequentially in order received, even if callback is async.
|
|
39044
|
+
* Uses queued wrapper to prevent concurrent execution of the callback.
|
|
39045
|
+
* @param fn - Callback function to handle signal info events
|
|
39046
|
+
* @return Unsubscribe function to stop listening to events
|
|
39047
|
+
*/
|
|
39048
|
+
function listenSignalNotify(fn) {
|
|
39049
|
+
backtest.loggerService.log(LISTEN_SIGNAL_NOTIFY_METHOD_NAME);
|
|
39050
|
+
const wrappedFn = async (event) => {
|
|
39051
|
+
if (await backtest.strategyCoreService.hasPendingSignal(event.backtest, event.symbol, {
|
|
39052
|
+
strategyName: event.strategyName,
|
|
39053
|
+
exchangeName: event.exchangeName,
|
|
39054
|
+
frameName: event.frameName,
|
|
39055
|
+
})) {
|
|
39056
|
+
await fn(event);
|
|
39057
|
+
}
|
|
39058
|
+
};
|
|
39059
|
+
return signalNotifySubject.subscribe(queued(wrappedFn));
|
|
39060
|
+
}
|
|
39061
|
+
/**
|
|
39062
|
+
* Subscribes to filtered signal info events with one-time execution.
|
|
39063
|
+
* Listens for events matching the filter predicate, then executes callback once
|
|
39064
|
+
* and automatically unsubscribes.
|
|
39065
|
+
* @param filterFn - Predicate to filter which events trigger the callback
|
|
39066
|
+
* @param fn - Callback function to handle the filtered event (called only once)
|
|
39067
|
+
* @return Unsubscribe function to cancel the listener before it fires
|
|
39068
|
+
*/
|
|
39069
|
+
function listenSignalNotifyOnce(filterFn, fn) {
|
|
39070
|
+
backtest.loggerService.log(LISTEN_SIGNAL_NOTIFY_ONCE_METHOD_NAME);
|
|
39071
|
+
let disposeFn;
|
|
39072
|
+
const wrappedFn = async (event) => {
|
|
39073
|
+
if (filterFn(event)) {
|
|
39074
|
+
await fn(event);
|
|
39075
|
+
disposeFn && disposeFn();
|
|
39076
|
+
}
|
|
39077
|
+
};
|
|
39078
|
+
return disposeFn = listenSignalNotify(wrappedFn);
|
|
39079
|
+
}
|
|
38857
39080
|
|
|
38858
39081
|
const BACKTEST_METHOD_NAME_RUN = "BacktestUtils.run";
|
|
38859
39082
|
const BACKTEST_METHOD_NAME_BACKGROUND = "BacktestUtils.background";
|
|
@@ -38910,6 +39133,7 @@ const BACKTEST_METHOD_NAME_TRAILING_STOP_COST = "BacktestUtils.commitTrailingSto
|
|
|
38910
39133
|
const BACKTEST_METHOD_NAME_TRAILING_PROFIT_COST = "BacktestUtils.commitTrailingTakeCost";
|
|
38911
39134
|
const BACKTEST_METHOD_NAME_ACTIVATE_SCHEDULED = "Backtest.commitActivateScheduled";
|
|
38912
39135
|
const BACKTEST_METHOD_NAME_AVERAGE_BUY = "Backtest.commitAverageBuy";
|
|
39136
|
+
const BACKTEST_METHOD_NAME_SIGNAL_NOTIFY = "Backtest.commitSignalNotify";
|
|
38913
39137
|
const BACKTEST_METHOD_NAME_GET_DATA = "BacktestUtils.getData";
|
|
38914
39138
|
const BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "BacktestUtils.hasNoPendingSignal";
|
|
38915
39139
|
const BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "BacktestUtils.hasNoScheduledSignal";
|
|
@@ -41265,6 +41489,33 @@ class BacktestUtils {
|
|
|
41265
41489
|
});
|
|
41266
41490
|
return await backtest.strategyCoreService.averageBuy(true, symbol, currentPrice, context, cost);
|
|
41267
41491
|
};
|
|
41492
|
+
/**
|
|
41493
|
+
* Emits a `signal.info` notification for the currently active pending signal.
|
|
41494
|
+
*
|
|
41495
|
+
* @param symbol - Trading pair symbol
|
|
41496
|
+
* @param currentPrice - Market price at the time of the call
|
|
41497
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
41498
|
+
* @param payload - Optional notification fields (notificationNote, notificationId)
|
|
41499
|
+
*
|
|
41500
|
+
* @throws {Error} If no active pending signal exists for the given symbol
|
|
41501
|
+
*
|
|
41502
|
+
* @example
|
|
41503
|
+
* ```typescript
|
|
41504
|
+
* await Backtest.commitSignalNotify("BTCUSDT", 42000, {
|
|
41505
|
+
* strategyName: "my-strategy",
|
|
41506
|
+
* exchangeName: "binance",
|
|
41507
|
+
* frameName: "1h"
|
|
41508
|
+
* }, { notificationNote: "RSI crossed 70" });
|
|
41509
|
+
* ```
|
|
41510
|
+
*/
|
|
41511
|
+
this.commitSignalNotify = async (symbol, currentPrice, context, payload = {}) => {
|
|
41512
|
+
backtest.loggerService.info(BACKTEST_METHOD_NAME_SIGNAL_NOTIFY, {
|
|
41513
|
+
symbol,
|
|
41514
|
+
currentPrice,
|
|
41515
|
+
context,
|
|
41516
|
+
});
|
|
41517
|
+
await backtest.notificationHelperService.commitSignalNotify(payload, symbol, currentPrice, context, true);
|
|
41518
|
+
};
|
|
41268
41519
|
/**
|
|
41269
41520
|
* Gets statistical data from all closed signals for a symbol-strategy pair.
|
|
41270
41521
|
*
|
|
@@ -41478,6 +41729,7 @@ const LIVE_METHOD_NAME_TRAILING_STOP_COST = "LiveUtils.commitTrailingStopCost";
|
|
|
41478
41729
|
const LIVE_METHOD_NAME_TRAILING_PROFIT_COST = "LiveUtils.commitTrailingTakeCost";
|
|
41479
41730
|
const LIVE_METHOD_NAME_ACTIVATE_SCHEDULED = "Live.commitActivateScheduled";
|
|
41480
41731
|
const LIVE_METHOD_NAME_AVERAGE_BUY = "Live.commitAverageBuy";
|
|
41732
|
+
const LIVE_METHOD_NAME_SIGNAL_NOTIFY = "Live.commitSignalNotify";
|
|
41481
41733
|
const LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "LiveUtils.hasNoPendingSignal";
|
|
41482
41734
|
const LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "LiveUtils.hasNoScheduledSignal";
|
|
41483
41735
|
/**
|
|
@@ -44174,6 +44426,36 @@ class LiveUtils {
|
|
|
44174
44426
|
frameName: "",
|
|
44175
44427
|
}, cost);
|
|
44176
44428
|
};
|
|
44429
|
+
/**
|
|
44430
|
+
* Emits a `signal.info` notification for the currently active pending signal.
|
|
44431
|
+
*
|
|
44432
|
+
* @param symbol - Trading pair symbol
|
|
44433
|
+
* @param currentPrice - Market price at the time of the call
|
|
44434
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
44435
|
+
* @param payload - Optional notification fields (notificationNote, notificationId)
|
|
44436
|
+
*
|
|
44437
|
+
* @throws {Error} If no active pending signal exists for the given symbol
|
|
44438
|
+
*
|
|
44439
|
+
* @example
|
|
44440
|
+
* ```typescript
|
|
44441
|
+
* await Live.commitSignalNotify("BTCUSDT", 42000, {
|
|
44442
|
+
* strategyName: "my-strategy",
|
|
44443
|
+
* exchangeName: "binance",
|
|
44444
|
+
* }, { notificationNote: "RSI crossed 70" });
|
|
44445
|
+
* ```
|
|
44446
|
+
*/
|
|
44447
|
+
this.commitSignalNotify = async (symbol, currentPrice, context, payload = {}) => {
|
|
44448
|
+
backtest.loggerService.info(LIVE_METHOD_NAME_SIGNAL_NOTIFY, {
|
|
44449
|
+
symbol,
|
|
44450
|
+
currentPrice,
|
|
44451
|
+
context,
|
|
44452
|
+
});
|
|
44453
|
+
await backtest.notificationHelperService.commitSignalNotify(payload, symbol, currentPrice, {
|
|
44454
|
+
strategyName: context.strategyName,
|
|
44455
|
+
exchangeName: context.exchangeName,
|
|
44456
|
+
frameName: "",
|
|
44457
|
+
}, false);
|
|
44458
|
+
};
|
|
44177
44459
|
/**
|
|
44178
44460
|
* Gets statistical data from all live trading events for a symbol-strategy pair.
|
|
44179
44461
|
*
|
|
@@ -48368,6 +48650,87 @@ class MarkdownUtils {
|
|
|
48368
48650
|
backtest.maxDrawdownMarkdownService.unsubscribe();
|
|
48369
48651
|
}
|
|
48370
48652
|
};
|
|
48653
|
+
/**
|
|
48654
|
+
* Clears markdown report data selectively.
|
|
48655
|
+
*
|
|
48656
|
+
* Clears accumulated data for specified markdown services without unsubscribing.
|
|
48657
|
+
* Use this method to reset report data for specific services while keeping them active.
|
|
48658
|
+
*
|
|
48659
|
+
* Each cleared service will:
|
|
48660
|
+
* - Clear accumulated data for all reports
|
|
48661
|
+
* - Start fresh with new data for future events
|
|
48662
|
+
* - Not affect event subscriptions or report generation status
|
|
48663
|
+
*
|
|
48664
|
+
* @param config - Service configuration object specifying which services to clear. Defaults to clearing all services.
|
|
48665
|
+
* @param config.backtest - Clear backtest result report data
|
|
48666
|
+
* @param config.breakeven - Clear breakeven event tracking data
|
|
48667
|
+
* @param config.partial - Clear partial profit/loss event tracking data
|
|
48668
|
+
* @param config.heat - Clear portfolio heatmap analysis data
|
|
48669
|
+
* @param config.walker - Clear walker strategy comparison report data
|
|
48670
|
+
* @param config.performance - Clear performance bottleneck analysis data
|
|
48671
|
+
* @param config.risk - Clear risk rejection tracking data
|
|
48672
|
+
* @param config.schedule - Clear scheduled signal tracking data
|
|
48673
|
+
* @param config.live - Clear live trading event report data
|
|
48674
|
+
* @param config.strategy - Clear strategy report data
|
|
48675
|
+
* @param config.sync - Clear sync report data
|
|
48676
|
+
* @param config.highest_profit - Clear highest profit report data
|
|
48677
|
+
* @param config.max_drawdown - Clear max drawdown report data
|
|
48678
|
+
*/
|
|
48679
|
+
this.clear = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, strategy = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET) => {
|
|
48680
|
+
LOGGER_SERVICE$1.debug(MARKDOWN_METHOD_NAME_CLEAR, {
|
|
48681
|
+
backtest: bt,
|
|
48682
|
+
breakeven,
|
|
48683
|
+
heat,
|
|
48684
|
+
live,
|
|
48685
|
+
partial,
|
|
48686
|
+
performance,
|
|
48687
|
+
risk,
|
|
48688
|
+
strategy,
|
|
48689
|
+
schedule,
|
|
48690
|
+
walker,
|
|
48691
|
+
sync,
|
|
48692
|
+
highest_profit,
|
|
48693
|
+
});
|
|
48694
|
+
if (bt) {
|
|
48695
|
+
backtest.backtestMarkdownService.clear();
|
|
48696
|
+
}
|
|
48697
|
+
if (breakeven) {
|
|
48698
|
+
backtest.breakevenMarkdownService.clear();
|
|
48699
|
+
}
|
|
48700
|
+
if (heat) {
|
|
48701
|
+
backtest.heatMarkdownService.clear();
|
|
48702
|
+
}
|
|
48703
|
+
if (live) {
|
|
48704
|
+
backtest.liveMarkdownService.clear();
|
|
48705
|
+
}
|
|
48706
|
+
if (partial) {
|
|
48707
|
+
backtest.partialMarkdownService.clear();
|
|
48708
|
+
}
|
|
48709
|
+
if (performance) {
|
|
48710
|
+
backtest.performanceMarkdownService.clear();
|
|
48711
|
+
}
|
|
48712
|
+
if (risk) {
|
|
48713
|
+
backtest.riskMarkdownService.clear();
|
|
48714
|
+
}
|
|
48715
|
+
if (strategy) {
|
|
48716
|
+
backtest.strategyMarkdownService.clear();
|
|
48717
|
+
}
|
|
48718
|
+
if (schedule) {
|
|
48719
|
+
backtest.scheduleMarkdownService.clear();
|
|
48720
|
+
}
|
|
48721
|
+
if (walker) {
|
|
48722
|
+
backtest.walkerMarkdownService.clear();
|
|
48723
|
+
}
|
|
48724
|
+
if (sync) {
|
|
48725
|
+
backtest.syncMarkdownService.clear();
|
|
48726
|
+
}
|
|
48727
|
+
if (highest_profit) {
|
|
48728
|
+
backtest.highestProfitMarkdownService.clear();
|
|
48729
|
+
}
|
|
48730
|
+
if (max_drawdown) {
|
|
48731
|
+
backtest.maxDrawdownMarkdownService.clear();
|
|
48732
|
+
}
|
|
48733
|
+
};
|
|
48371
48734
|
}
|
|
48372
48735
|
}
|
|
48373
48736
|
/**
|
|
@@ -48410,15 +48773,6 @@ class MarkdownAdapter extends MarkdownUtils {
|
|
|
48410
48773
|
LOGGER_SERVICE$1.debug(MARKDOWN_METHOD_NAME_USE_JSONL);
|
|
48411
48774
|
MarkdownWriter.useJsonl();
|
|
48412
48775
|
}
|
|
48413
|
-
/**
|
|
48414
|
-
* Clears the memoized storage cache.
|
|
48415
|
-
* Call this when process.cwd() changes between strategy iterations
|
|
48416
|
-
* so new storage instances are created with the updated base path.
|
|
48417
|
-
*/
|
|
48418
|
-
clear() {
|
|
48419
|
-
LOGGER_SERVICE$1.log(MARKDOWN_METHOD_NAME_CLEAR);
|
|
48420
|
-
MarkdownWriter.clear();
|
|
48421
|
-
}
|
|
48422
48776
|
/**
|
|
48423
48777
|
* Switches to a dummy markdown adapter that discards all writes.
|
|
48424
48778
|
* All future markdown writes will be no-ops.
|
|
@@ -49115,6 +49469,7 @@ const SUBJECT_ISOLATION_LIST = [
|
|
|
49115
49469
|
strategyCommitSubject,
|
|
49116
49470
|
syncSubject,
|
|
49117
49471
|
validationSubject,
|
|
49472
|
+
signalNotifySubject,
|
|
49118
49473
|
];
|
|
49119
49474
|
/**
|
|
49120
49475
|
* Creates a snapshot function for a given subject by clearing its internal
|
|
@@ -53960,7 +54315,44 @@ const CREATE_VALIDATION_ERROR_NOTIFICATION_FN = (error) => ({
|
|
|
53960
54315
|
message: getErrorMessage(error),
|
|
53961
54316
|
backtest: false,
|
|
53962
54317
|
});
|
|
54318
|
+
/**
|
|
54319
|
+
* Creates a notification model for signal info events.
|
|
54320
|
+
* @param data - The signal info contract data
|
|
54321
|
+
* @returns NotificationModel for signal info event
|
|
54322
|
+
*/
|
|
54323
|
+
const CREATE_SIGNAL_INFO_NOTIFICATION_FN = (data) => ({
|
|
54324
|
+
type: "signal.info",
|
|
54325
|
+
id: CREATE_KEY_FN$2(),
|
|
54326
|
+
timestamp: data.timestamp,
|
|
54327
|
+
backtest: data.backtest,
|
|
54328
|
+
symbol: data.symbol,
|
|
54329
|
+
strategyName: data.strategyName,
|
|
54330
|
+
exchangeName: data.exchangeName,
|
|
54331
|
+
signalId: data.data.id,
|
|
54332
|
+
currentPrice: data.currentPrice,
|
|
54333
|
+
position: data.data.position,
|
|
54334
|
+
priceOpen: data.data.priceOpen,
|
|
54335
|
+
priceTakeProfit: data.data.priceTakeProfit,
|
|
54336
|
+
priceStopLoss: data.data.priceStopLoss,
|
|
54337
|
+
originalPriceTakeProfit: data.data.originalPriceTakeProfit,
|
|
54338
|
+
originalPriceStopLoss: data.data.originalPriceStopLoss,
|
|
54339
|
+
originalPriceOpen: data.data.originalPriceOpen,
|
|
54340
|
+
totalEntries: data.data.totalEntries,
|
|
54341
|
+
totalPartials: data.data.totalPartials,
|
|
54342
|
+
pnl: data.data.pnl,
|
|
54343
|
+
pnlPercentage: data.data.pnl.pnlPercentage,
|
|
54344
|
+
pnlPriceOpen: data.data.pnl.priceOpen,
|
|
54345
|
+
pnlPriceClose: data.data.pnl.priceClose,
|
|
54346
|
+
pnlCost: data.data.pnl.pnlCost,
|
|
54347
|
+
pnlEntries: data.data.pnl.pnlEntries,
|
|
54348
|
+
note: data.note,
|
|
54349
|
+
notificationId: data.notificationId,
|
|
54350
|
+
scheduledAt: data.data.scheduledAt,
|
|
54351
|
+
pendingAt: data.data.pendingAt,
|
|
54352
|
+
createdAt: data.timestamp,
|
|
54353
|
+
});
|
|
53963
54354
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL = "NotificationMemoryBacktestUtils.handleSignal";
|
|
54355
|
+
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationMemoryBacktestUtils.handleSignalNotify";
|
|
53964
54356
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationMemoryBacktestUtils.handlePartialProfit";
|
|
53965
54357
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationMemoryBacktestUtils.handlePartialLoss";
|
|
53966
54358
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationMemoryBacktestUtils.handleBreakeven";
|
|
@@ -53973,6 +54365,7 @@ const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_VALIDATION_ERROR = "Notifi
|
|
|
53973
54365
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_GET_DATA = "NotificationMemoryBacktestUtils.getData";
|
|
53974
54366
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_DISPOSE = "NotificationMemoryBacktestUtils.dispose";
|
|
53975
54367
|
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL = "NotificationMemoryLiveUtils.handleSignal";
|
|
54368
|
+
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationMemoryLiveUtils.handleSignalNotify";
|
|
53976
54369
|
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationMemoryLiveUtils.handlePartialProfit";
|
|
53977
54370
|
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationMemoryLiveUtils.handlePartialLoss";
|
|
53978
54371
|
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationMemoryLiveUtils.handleBreakeven";
|
|
@@ -54001,6 +54394,7 @@ const NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_CLEAR = "NotificationLiveAdapter.cle
|
|
|
54001
54394
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "NotificationPersistBacktestUtils.waitForInit";
|
|
54002
54395
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_UPDATE_NOTIFICATIONS = "NotificationPersistBacktestUtils._updateNotifications";
|
|
54003
54396
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL = "NotificationPersistBacktestUtils.handleSignal";
|
|
54397
|
+
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationPersistBacktestUtils.handleSignalNotify";
|
|
54004
54398
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationPersistBacktestUtils.handlePartialProfit";
|
|
54005
54399
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationPersistBacktestUtils.handlePartialLoss";
|
|
54006
54400
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationPersistBacktestUtils.handleBreakeven";
|
|
@@ -54015,6 +54409,7 @@ const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_DISPOSE = "NotificationPersistBa
|
|
|
54015
54409
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_WAIT_FOR_INIT = "NotificationPersistLiveUtils.waitForInit";
|
|
54016
54410
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_UPDATE_NOTIFICATIONS = "NotificationPersistLiveUtils._updateNotifications";
|
|
54017
54411
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL = "NotificationPersistLiveUtils.handleSignal";
|
|
54412
|
+
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationPersistLiveUtils.handleSignalNotify";
|
|
54018
54413
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationPersistLiveUtils.handlePartialProfit";
|
|
54019
54414
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationPersistLiveUtils.handlePartialLoss";
|
|
54020
54415
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationPersistLiveUtils.handleBreakeven";
|
|
@@ -54057,6 +54452,12 @@ class NotificationMemoryBacktestUtils {
|
|
|
54057
54452
|
this._addNotification(notification);
|
|
54058
54453
|
}
|
|
54059
54454
|
};
|
|
54455
|
+
this.handleSignalNotify = async (data) => {
|
|
54456
|
+
backtest.loggerService.info(NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
|
|
54457
|
+
signalId: data.data.id,
|
|
54458
|
+
});
|
|
54459
|
+
this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
|
|
54460
|
+
};
|
|
54060
54461
|
/**
|
|
54061
54462
|
* Handles partial profit availability event.
|
|
54062
54463
|
* @param data - The partial profit contract data
|
|
@@ -54201,6 +54602,8 @@ class NotificationDummyBacktestUtils {
|
|
|
54201
54602
|
*/
|
|
54202
54603
|
this.handleSignal = async () => {
|
|
54203
54604
|
};
|
|
54605
|
+
this.handleSignalNotify = async () => {
|
|
54606
|
+
};
|
|
54204
54607
|
/**
|
|
54205
54608
|
* No-op handler for partial profit event.
|
|
54206
54609
|
*/
|
|
@@ -54308,6 +54711,14 @@ class NotificationPersistBacktestUtils {
|
|
|
54308
54711
|
await this._updateNotifications();
|
|
54309
54712
|
}
|
|
54310
54713
|
};
|
|
54714
|
+
this.handleSignalNotify = async (data) => {
|
|
54715
|
+
backtest.loggerService.info(NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
|
|
54716
|
+
signalId: data.data.id,
|
|
54717
|
+
});
|
|
54718
|
+
await this.waitForInit();
|
|
54719
|
+
this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
|
|
54720
|
+
await this._updateNotifications();
|
|
54721
|
+
};
|
|
54311
54722
|
/**
|
|
54312
54723
|
* Handles partial profit availability event.
|
|
54313
54724
|
* @param data - The partial profit contract data
|
|
@@ -54509,6 +54920,12 @@ class NotificationMemoryLiveUtils {
|
|
|
54509
54920
|
this._addNotification(notification);
|
|
54510
54921
|
}
|
|
54511
54922
|
};
|
|
54923
|
+
this.handleSignalNotify = async (data) => {
|
|
54924
|
+
backtest.loggerService.info(NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
|
|
54925
|
+
signalId: data.data.id,
|
|
54926
|
+
});
|
|
54927
|
+
this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
|
|
54928
|
+
};
|
|
54512
54929
|
/**
|
|
54513
54930
|
* Handles partial profit availability event.
|
|
54514
54931
|
* @param data - The partial profit contract data
|
|
@@ -54653,6 +55070,8 @@ class NotificationDummyLiveUtils {
|
|
|
54653
55070
|
*/
|
|
54654
55071
|
this.handleSignal = async () => {
|
|
54655
55072
|
};
|
|
55073
|
+
this.handleSignalNotify = async () => {
|
|
55074
|
+
};
|
|
54656
55075
|
/**
|
|
54657
55076
|
* No-op handler for partial profit event.
|
|
54658
55077
|
*/
|
|
@@ -54761,6 +55180,14 @@ class NotificationPersistLiveUtils {
|
|
|
54761
55180
|
await this._updateNotifications();
|
|
54762
55181
|
}
|
|
54763
55182
|
};
|
|
55183
|
+
this.handleSignalNotify = async (data) => {
|
|
55184
|
+
backtest.loggerService.info(NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
|
|
55185
|
+
signalId: data.data.id,
|
|
55186
|
+
});
|
|
55187
|
+
await this.waitForInit();
|
|
55188
|
+
this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
|
|
55189
|
+
await this._updateNotifications();
|
|
55190
|
+
};
|
|
54764
55191
|
/**
|
|
54765
55192
|
* Handles partial profit availability event.
|
|
54766
55193
|
* @param data - The partial profit contract data
|
|
@@ -54954,6 +55381,9 @@ class NotificationBacktestAdapter {
|
|
|
54954
55381
|
this.handleSignal = async (data) => {
|
|
54955
55382
|
return await this._notificationBacktestUtils.handleSignal(data);
|
|
54956
55383
|
};
|
|
55384
|
+
this.handleSignalNotify = async (data) => {
|
|
55385
|
+
return await this._notificationBacktestUtils.handleSignalNotify(data);
|
|
55386
|
+
};
|
|
54957
55387
|
/**
|
|
54958
55388
|
* Handles partial profit availability event.
|
|
54959
55389
|
* Proxies call to the underlying notification adapter.
|
|
@@ -55109,6 +55539,9 @@ class NotificationLiveAdapter {
|
|
|
55109
55539
|
this.handleSignal = async (data) => {
|
|
55110
55540
|
return await this._notificationLiveUtils.handleSignal(data);
|
|
55111
55541
|
};
|
|
55542
|
+
this.handleSignalNotify = async (data) => {
|
|
55543
|
+
return await this._notificationLiveUtils.handleSignalNotify(data);
|
|
55544
|
+
};
|
|
55112
55545
|
/**
|
|
55113
55546
|
* Handles partial profit availability event.
|
|
55114
55547
|
* Proxies call to the underlying notification adapter.
|
|
@@ -55287,7 +55720,10 @@ class NotificationAdapter {
|
|
|
55287
55720
|
const unBacktestError = errorEmitter.subscribe((error) => NotificationBacktest.handleError(error));
|
|
55288
55721
|
const unBacktestExit = exitEmitter.subscribe((error) => NotificationBacktest.handleCriticalError(error));
|
|
55289
55722
|
const unBacktestValidation = validationSubject.subscribe((error) => NotificationBacktest.handleValidationError(error));
|
|
55290
|
-
|
|
55723
|
+
const unBacktestSignalNotify = signalNotifySubject
|
|
55724
|
+
.filter(({ backtest }) => backtest)
|
|
55725
|
+
.connect((data) => NotificationBacktest.handleSignalNotify(data));
|
|
55726
|
+
unBacktest = compose(() => unBacktestSignal(), () => unBacktestPartialProfit(), () => unBacktestPartialLoss(), () => unBacktestBreakeven(), () => unBacktestStrategyCommit(), () => unBacktestSync(), () => unBacktestRisk(), () => unBacktestError(), () => unBacktestExit(), () => unBacktestValidation(), () => unBacktestSignalNotify());
|
|
55291
55727
|
}
|
|
55292
55728
|
{
|
|
55293
55729
|
const unLiveSignal = signalLiveEmitter.subscribe((data) => NotificationLive.handleSignal(data));
|
|
@@ -55312,7 +55748,10 @@ class NotificationAdapter {
|
|
|
55312
55748
|
const unLiveError = errorEmitter.subscribe((error) => NotificationLive.handleError(error));
|
|
55313
55749
|
const unLiveExit = exitEmitter.subscribe((error) => NotificationLive.handleCriticalError(error));
|
|
55314
55750
|
const unLiveValidation = validationSubject.subscribe((error) => NotificationLive.handleValidationError(error));
|
|
55315
|
-
|
|
55751
|
+
const unLiveSignalNotify = signalNotifySubject
|
|
55752
|
+
.filter(({ backtest }) => !backtest)
|
|
55753
|
+
.connect((data) => NotificationLive.handleSignalNotify(data));
|
|
55754
|
+
unLive = compose(() => unLiveSignal(), () => unLivePartialProfit(), () => unLivePartialLoss(), () => unLiveBreakeven(), () => unLiveStrategyCommit(), () => unLiveSync(), () => unLiveRisk(), () => unLiveError(), () => unLiveExit(), () => unLiveValidation(), () => unLiveSignalNotify());
|
|
55316
55755
|
}
|
|
55317
55756
|
return () => {
|
|
55318
55757
|
unLive();
|
|
@@ -55550,11 +55989,17 @@ class CacheFnInstance {
|
|
|
55550
55989
|
return cached;
|
|
55551
55990
|
}
|
|
55552
55991
|
}
|
|
55992
|
+
const value = this.fn(...args);
|
|
55553
55993
|
const newCache = {
|
|
55554
55994
|
when: currentWhen,
|
|
55555
|
-
value
|
|
55995
|
+
value,
|
|
55556
55996
|
};
|
|
55557
55997
|
this._cacheMap.set(key, newCache);
|
|
55998
|
+
if (value && value instanceof Promise) {
|
|
55999
|
+
value.catch(() => {
|
|
56000
|
+
this._cacheMap.delete(key);
|
|
56001
|
+
});
|
|
56002
|
+
}
|
|
55558
56003
|
return newCache;
|
|
55559
56004
|
};
|
|
55560
56005
|
/**
|
|
@@ -56135,7 +56580,7 @@ class IntervalFnInstance {
|
|
|
56135
56580
|
* within the same interval or when `fn` itself returned `null`
|
|
56136
56581
|
* @throws Error if method context, execution context, or interval is missing
|
|
56137
56582
|
*/
|
|
56138
|
-
this.run =
|
|
56583
|
+
this.run = (...args) => {
|
|
56139
56584
|
backtest.loggerService.debug(INTERVAL_METHOD_NAME_RUN, { args });
|
|
56140
56585
|
const step = INTERVAL_MINUTES[this.interval];
|
|
56141
56586
|
{
|
|
@@ -56157,10 +56602,15 @@ class IntervalFnInstance {
|
|
|
56157
56602
|
if (this._stateMap.get(stateKey) === currentAligned) {
|
|
56158
56603
|
return null;
|
|
56159
56604
|
}
|
|
56160
|
-
const result =
|
|
56605
|
+
const result = this.fn.apply(null, args);
|
|
56161
56606
|
if (result !== null) {
|
|
56162
56607
|
this._stateMap.set(stateKey, currentAligned);
|
|
56163
56608
|
}
|
|
56609
|
+
if (result && result instanceof Promise) {
|
|
56610
|
+
result.catch(() => {
|
|
56611
|
+
this._stateMap.delete(stateKey);
|
|
56612
|
+
});
|
|
56613
|
+
}
|
|
56164
56614
|
return result;
|
|
56165
56615
|
};
|
|
56166
56616
|
/**
|
|
@@ -57691,4 +58141,4 @@ const validateSignal = (signal, currentPrice) => {
|
|
|
57691
58141
|
return !errors.length;
|
|
57692
58142
|
};
|
|
57693
58143
|
|
|
57694
|
-
export { ActionBase, Backtest, Breakeven, Broker, BrokerBase, Cache, Constant, Dump, Exchange, ExecutionContextService, Heat, HighestProfit, Interval, Live, Log, Markdown, MarkdownFileBase, MarkdownFolderBase, MarkdownWriter, MaxDrawdown, Memory, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistIntervalAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistMemoryAdapter, PersistNotificationAdapter, PersistPartialAdapter, PersistRecentAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, Position, PositionSize, Recent, RecentBacktest, RecentLive, Reflect$1 as Reflect, Report, ReportBase, ReportWriter, Risk, Schedule, Session, Storage, StorageBacktest, StorageLive, Strategy, Sync, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialLossCost, commitPartialProfit, commitPartialProfitCost, commitTrailingStop, commitTrailingStopCost, commitTrailingTake, commitTrailingTakeCost, dumpAgentAnswer, dumpError, dumpJson, dumpRecord, dumpTable, dumpText, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getBreakeven, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getEffectivePriceOpen, getExchangeSchema, getFrameSchema, getLatestSignal, getMaxDrawdownDistancePnlCost, getMaxDrawdownDistancePnlPercentage, getMode, getNextCandles, getOrderBook, getPendingSignal, getPositionCountdownMinutes, getPositionDrawdownMinutes, getPositionEffectivePrice, getPositionEntries, getPositionEntryOverlap, getPositionEstimateMinutes, getPositionHighestMaxDrawdownPnlCost, getPositionHighestMaxDrawdownPnlPercentage, getPositionHighestPnlCost, getPositionHighestPnlPercentage, getPositionHighestProfitBreakeven, getPositionHighestProfitDistancePnlCost, getPositionHighestProfitDistancePnlPercentage, getPositionHighestProfitMinutes, getPositionHighestProfitPrice, getPositionHighestProfitTimestamp, getPositionInvestedCost, getPositionInvestedCount, getPositionLevels, getPositionMaxDrawdownMinutes, getPositionMaxDrawdownPnlCost, getPositionMaxDrawdownPnlPercentage, getPositionMaxDrawdownPrice, getPositionMaxDrawdownTimestamp, getPositionPartialOverlap, getPositionPartials, getPositionPnlCost, getPositionPnlPercent, getRawCandles, getRiskSchema, getScheduledSignal, getSizingSchema, getStrategySchema, getSymbol, getTimestamp, getTotalClosed, getTotalCostClosed, getTotalPercentClosed, getWalkerSchema, hasNoPendingSignal, hasNoScheduledSignal, hasTradeContext, investedCostToPercent, backtest as lib, listExchangeSchema, listFrameSchema, listMemory, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenHighestProfit, listenHighestProfitOnce, listenMaxDrawdown, listenMaxDrawdownOnce, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenSync, listenSyncOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, percentDiff, percentToCloseCost, percentValue, readMemory, removeMemory, roundTicks, runInMockContext, searchMemory, set, setColumns, setConfig, setLogger, shutdown, slPercentShiftToPrice, slPriceToPercentShift, stopStrategy, toProfitLossDto, tpPercentShiftToPrice, tpPriceToPercentShift, validate, validateCommonSignal, validatePendingSignal, validateScheduledSignal, validateSignal, waitForCandle, warmCandles, writeMemory };
|
|
58144
|
+
export { ActionBase, Backtest, Breakeven, Broker, BrokerBase, Cache, Constant, Dump, Exchange, ExecutionContextService, Heat, HighestProfit, Interval, Live, Log, Markdown, MarkdownFileBase, MarkdownFolderBase, MarkdownWriter, MaxDrawdown, Memory, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistIntervalAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistMemoryAdapter, PersistNotificationAdapter, PersistPartialAdapter, PersistRecentAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, Position, PositionSize, Recent, RecentBacktest, RecentLive, Reflect$1 as Reflect, Report, ReportBase, ReportWriter, Risk, Schedule, Session, Storage, StorageBacktest, StorageLive, Strategy, Sync, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialLossCost, commitPartialProfit, commitPartialProfitCost, commitSignalNotify, commitTrailingStop, commitTrailingStopCost, commitTrailingTake, commitTrailingTakeCost, dumpAgentAnswer, dumpError, dumpJson, dumpRecord, dumpTable, dumpText, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getBreakeven, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getEffectivePriceOpen, getExchangeSchema, getFrameSchema, getLatestSignal, getMaxDrawdownDistancePnlCost, getMaxDrawdownDistancePnlPercentage, getMode, getNextCandles, getOrderBook, getPendingSignal, getPositionCountdownMinutes, getPositionDrawdownMinutes, getPositionEffectivePrice, getPositionEntries, getPositionEntryOverlap, getPositionEstimateMinutes, getPositionHighestMaxDrawdownPnlCost, getPositionHighestMaxDrawdownPnlPercentage, getPositionHighestPnlCost, getPositionHighestPnlPercentage, getPositionHighestProfitBreakeven, getPositionHighestProfitDistancePnlCost, getPositionHighestProfitDistancePnlPercentage, getPositionHighestProfitMinutes, getPositionHighestProfitPrice, getPositionHighestProfitTimestamp, getPositionInvestedCost, getPositionInvestedCount, getPositionLevels, getPositionMaxDrawdownMinutes, getPositionMaxDrawdownPnlCost, getPositionMaxDrawdownPnlPercentage, getPositionMaxDrawdownPrice, getPositionMaxDrawdownTimestamp, getPositionPartialOverlap, getPositionPartials, getPositionPnlCost, getPositionPnlPercent, getRawCandles, getRiskSchema, getScheduledSignal, getSizingSchema, getStrategySchema, getSymbol, getTimestamp, getTotalClosed, getTotalCostClosed, getTotalPercentClosed, getWalkerSchema, hasNoPendingSignal, hasNoScheduledSignal, hasTradeContext, investedCostToPercent, backtest as lib, listExchangeSchema, listFrameSchema, listMemory, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenHighestProfit, listenHighestProfitOnce, listenMaxDrawdown, listenMaxDrawdownOnce, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalNotify, listenSignalNotifyOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenSync, listenSyncOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, percentDiff, percentToCloseCost, percentValue, readMemory, removeMemory, roundTicks, runInMockContext, searchMemory, set, setColumns, setConfig, setLogger, shutdown, slPercentShiftToPrice, slPriceToPercentShift, stopStrategy, toProfitLossDto, tpPercentShiftToPrice, tpPriceToPercentShift, validate, validateCommonSignal, validatePendingSignal, validateScheduledSignal, validateSignal, waitForCandle, warmCandles, writeMemory };
|