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.cjs
CHANGED
|
@@ -147,6 +147,9 @@ const reportServices$1 = {
|
|
|
147
147
|
highestProfitReportService: Symbol('highestProfitReportService'),
|
|
148
148
|
maxDrawdownReportService: Symbol('maxDrawdownReportService'),
|
|
149
149
|
};
|
|
150
|
+
const helperServices$1 = {
|
|
151
|
+
notificationHelperService: Symbol('notificationHelperService'),
|
|
152
|
+
};
|
|
150
153
|
const validationServices$1 = {
|
|
151
154
|
exchangeValidationService: Symbol('exchangeValidationService'),
|
|
152
155
|
strategyValidationService: Symbol('strategyValidationService'),
|
|
@@ -172,6 +175,7 @@ const TYPES = {
|
|
|
172
175
|
...markdownServices$1,
|
|
173
176
|
...reportServices$1,
|
|
174
177
|
...validationServices$1,
|
|
178
|
+
...helperServices$1,
|
|
175
179
|
};
|
|
176
180
|
|
|
177
181
|
/**
|
|
@@ -764,6 +768,11 @@ const highestProfitSubject = new functoolsKit.Subject();
|
|
|
764
768
|
* Allows users to track drawdown levels and implement custom risk management logic based on drawdown thresholds.
|
|
765
769
|
*/
|
|
766
770
|
const maxDrawdownSubject = new functoolsKit.Subject();
|
|
771
|
+
/**
|
|
772
|
+
* Signal info emitter for user-defined informational notes on open positions.
|
|
773
|
+
* Emits when a strategy calls commitSignalInfo() to broadcast a custom annotation.
|
|
774
|
+
*/
|
|
775
|
+
const signalNotifySubject = new functoolsKit.Subject();
|
|
767
776
|
|
|
768
777
|
var emitters = /*#__PURE__*/Object.freeze({
|
|
769
778
|
__proto__: null,
|
|
@@ -788,6 +797,7 @@ var emitters = /*#__PURE__*/Object.freeze({
|
|
|
788
797
|
signalBacktestEmitter: signalBacktestEmitter,
|
|
789
798
|
signalEmitter: signalEmitter,
|
|
790
799
|
signalLiveEmitter: signalLiveEmitter,
|
|
800
|
+
signalNotifySubject: signalNotifySubject,
|
|
791
801
|
strategyCommitSubject: strategyCommitSubject,
|
|
792
802
|
syncSubject: syncSubject,
|
|
793
803
|
validationSubject: validationSubject,
|
|
@@ -10290,7 +10300,7 @@ const GET_RISK_FN = (dto, backtest, exchangeName, frameName, self) => {
|
|
|
10290
10300
|
* @param backtest - Whether running in backtest mode
|
|
10291
10301
|
* @returns Unique string key for memoization
|
|
10292
10302
|
*/
|
|
10293
|
-
const CREATE_KEY_FN$
|
|
10303
|
+
const CREATE_KEY_FN$v = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
10294
10304
|
const parts = [symbol, strategyName, exchangeName];
|
|
10295
10305
|
if (frameName)
|
|
10296
10306
|
parts.push(frameName);
|
|
@@ -10557,7 +10567,7 @@ class StrategyConnectionService {
|
|
|
10557
10567
|
* @param backtest - Whether running in backtest mode
|
|
10558
10568
|
* @returns Configured ClientStrategy instance
|
|
10559
10569
|
*/
|
|
10560
|
-
this.getStrategy = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
10570
|
+
this.getStrategy = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$v(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
10561
10571
|
const { riskName = "", riskList = [], getSignal, interval = STRATEGY_DEFAULT_INTERVAL, callbacks, } = this.strategySchemaService.get(strategyName);
|
|
10562
10572
|
return new ClientStrategy({
|
|
10563
10573
|
symbol,
|
|
@@ -11478,7 +11488,7 @@ class StrategyConnectionService {
|
|
|
11478
11488
|
}
|
|
11479
11489
|
return;
|
|
11480
11490
|
}
|
|
11481
|
-
const key = CREATE_KEY_FN$
|
|
11491
|
+
const key = CREATE_KEY_FN$v(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
11482
11492
|
if (!this.getStrategy.has(key)) {
|
|
11483
11493
|
return;
|
|
11484
11494
|
}
|
|
@@ -12647,7 +12657,7 @@ class ClientRisk {
|
|
|
12647
12657
|
* @param backtest - Whether running in backtest mode
|
|
12648
12658
|
* @returns Unique string key for memoization
|
|
12649
12659
|
*/
|
|
12650
|
-
const CREATE_KEY_FN$
|
|
12660
|
+
const CREATE_KEY_FN$u = (riskName, exchangeName, frameName, backtest) => {
|
|
12651
12661
|
const parts = [riskName, exchangeName];
|
|
12652
12662
|
if (frameName)
|
|
12653
12663
|
parts.push(frameName);
|
|
@@ -12747,7 +12757,7 @@ class RiskConnectionService {
|
|
|
12747
12757
|
* @param backtest - True if backtest mode, false if live mode
|
|
12748
12758
|
* @returns Configured ClientRisk instance
|
|
12749
12759
|
*/
|
|
12750
|
-
this.getRisk = functoolsKit.memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
12760
|
+
this.getRisk = functoolsKit.memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$u(riskName, exchangeName, frameName, backtest), (riskName, exchangeName, frameName, backtest) => {
|
|
12751
12761
|
const schema = this.riskSchemaService.get(riskName);
|
|
12752
12762
|
return new ClientRisk({
|
|
12753
12763
|
...schema,
|
|
@@ -12816,7 +12826,7 @@ class RiskConnectionService {
|
|
|
12816
12826
|
payload,
|
|
12817
12827
|
});
|
|
12818
12828
|
if (payload) {
|
|
12819
|
-
const key = CREATE_KEY_FN$
|
|
12829
|
+
const key = CREATE_KEY_FN$u(payload.riskName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
12820
12830
|
this.getRisk.clear(key);
|
|
12821
12831
|
}
|
|
12822
12832
|
else {
|
|
@@ -13860,7 +13870,7 @@ class ClientAction {
|
|
|
13860
13870
|
* @param backtest - Whether running in backtest mode
|
|
13861
13871
|
* @returns Unique string key for memoization
|
|
13862
13872
|
*/
|
|
13863
|
-
const CREATE_KEY_FN$
|
|
13873
|
+
const CREATE_KEY_FN$t = (actionName, strategyName, exchangeName, frameName, backtest) => {
|
|
13864
13874
|
const parts = [actionName, strategyName, exchangeName];
|
|
13865
13875
|
if (frameName)
|
|
13866
13876
|
parts.push(frameName);
|
|
@@ -13912,7 +13922,7 @@ class ActionConnectionService {
|
|
|
13912
13922
|
* @param backtest - True if backtest mode, false if live mode
|
|
13913
13923
|
* @returns Configured ClientAction instance
|
|
13914
13924
|
*/
|
|
13915
|
-
this.getAction = functoolsKit.memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
13925
|
+
this.getAction = functoolsKit.memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$t(actionName, strategyName, exchangeName, frameName, backtest), (actionName, strategyName, exchangeName, frameName, backtest) => {
|
|
13916
13926
|
const schema = this.actionSchemaService.get(actionName);
|
|
13917
13927
|
return new ClientAction({
|
|
13918
13928
|
...schema,
|
|
@@ -14123,7 +14133,7 @@ class ActionConnectionService {
|
|
|
14123
14133
|
await Promise.all(actions.map(async (action) => await action.dispose()));
|
|
14124
14134
|
return;
|
|
14125
14135
|
}
|
|
14126
|
-
const key = CREATE_KEY_FN$
|
|
14136
|
+
const key = CREATE_KEY_FN$t(payload.actionName, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
14127
14137
|
if (!this.getAction.has(key)) {
|
|
14128
14138
|
return;
|
|
14129
14139
|
}
|
|
@@ -14134,14 +14144,14 @@ class ActionConnectionService {
|
|
|
14134
14144
|
}
|
|
14135
14145
|
}
|
|
14136
14146
|
|
|
14137
|
-
const METHOD_NAME_VALIDATE$
|
|
14147
|
+
const METHOD_NAME_VALIDATE$3 = "exchangeCoreService validate";
|
|
14138
14148
|
/**
|
|
14139
14149
|
* Creates a unique key for memoizing validate calls.
|
|
14140
14150
|
* Key format: "exchangeName"
|
|
14141
14151
|
* @param exchangeName - Exchange name
|
|
14142
14152
|
* @returns Unique string key for memoization
|
|
14143
14153
|
*/
|
|
14144
|
-
const CREATE_KEY_FN$
|
|
14154
|
+
const CREATE_KEY_FN$s = (exchangeName) => {
|
|
14145
14155
|
return exchangeName;
|
|
14146
14156
|
};
|
|
14147
14157
|
/**
|
|
@@ -14165,11 +14175,11 @@ class ExchangeCoreService {
|
|
|
14165
14175
|
* @param exchangeName - Name of the exchange to validate
|
|
14166
14176
|
* @returns Promise that resolves when validation is complete
|
|
14167
14177
|
*/
|
|
14168
|
-
this.validate = functoolsKit.memoize(([exchangeName]) => CREATE_KEY_FN$
|
|
14169
|
-
this.loggerService.log(METHOD_NAME_VALIDATE$
|
|
14178
|
+
this.validate = functoolsKit.memoize(([exchangeName]) => CREATE_KEY_FN$s(exchangeName), async (exchangeName) => {
|
|
14179
|
+
this.loggerService.log(METHOD_NAME_VALIDATE$3, {
|
|
14170
14180
|
exchangeName,
|
|
14171
14181
|
});
|
|
14172
|
-
this.exchangeValidationService.validate(exchangeName, METHOD_NAME_VALIDATE$
|
|
14182
|
+
this.exchangeValidationService.validate(exchangeName, METHOD_NAME_VALIDATE$3);
|
|
14173
14183
|
});
|
|
14174
14184
|
/**
|
|
14175
14185
|
* Fetches historical candles with execution context.
|
|
@@ -14410,14 +14420,14 @@ class ExchangeCoreService {
|
|
|
14410
14420
|
}
|
|
14411
14421
|
}
|
|
14412
14422
|
|
|
14413
|
-
const METHOD_NAME_VALIDATE$
|
|
14423
|
+
const METHOD_NAME_VALIDATE$2 = "strategyCoreService validate";
|
|
14414
14424
|
/**
|
|
14415
14425
|
* Creates a unique key for memoizing validate calls.
|
|
14416
14426
|
* Key format: "strategyName:exchangeName:frameName"
|
|
14417
14427
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
14418
14428
|
* @returns Unique string key for memoization
|
|
14419
14429
|
*/
|
|
14420
|
-
const CREATE_KEY_FN$
|
|
14430
|
+
const CREATE_KEY_FN$r = (context) => {
|
|
14421
14431
|
const parts = [context.strategyName, context.exchangeName];
|
|
14422
14432
|
if (context.frameName)
|
|
14423
14433
|
parts.push(context.frameName);
|
|
@@ -14449,16 +14459,16 @@ class StrategyCoreService {
|
|
|
14449
14459
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
14450
14460
|
* @returns Promise that resolves when validation is complete
|
|
14451
14461
|
*/
|
|
14452
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
14453
|
-
this.loggerService.log(METHOD_NAME_VALIDATE$
|
|
14462
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$r(context), async (context) => {
|
|
14463
|
+
this.loggerService.log(METHOD_NAME_VALIDATE$2, {
|
|
14454
14464
|
context,
|
|
14455
14465
|
});
|
|
14456
14466
|
const { riskName, riskList } = this.strategySchemaService.get(context.strategyName);
|
|
14457
|
-
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$
|
|
14458
|
-
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$
|
|
14459
|
-
context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$
|
|
14460
|
-
riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$
|
|
14461
|
-
riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$
|
|
14467
|
+
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$2);
|
|
14468
|
+
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$2);
|
|
14469
|
+
context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$2);
|
|
14470
|
+
riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$2);
|
|
14471
|
+
riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$2));
|
|
14462
14472
|
});
|
|
14463
14473
|
/**
|
|
14464
14474
|
* Retrieves the currently active pending signal for the symbol.
|
|
@@ -15787,7 +15797,7 @@ class SizingGlobalService {
|
|
|
15787
15797
|
* @param context - Context with riskName, exchangeName, frameName
|
|
15788
15798
|
* @returns Unique string key for memoization
|
|
15789
15799
|
*/
|
|
15790
|
-
const CREATE_KEY_FN$
|
|
15800
|
+
const CREATE_KEY_FN$q = (context) => {
|
|
15791
15801
|
const parts = [context.riskName, context.exchangeName];
|
|
15792
15802
|
if (context.frameName)
|
|
15793
15803
|
parts.push(context.frameName);
|
|
@@ -15813,7 +15823,7 @@ class RiskGlobalService {
|
|
|
15813
15823
|
* @param payload - Payload with riskName, exchangeName and frameName
|
|
15814
15824
|
* @returns Promise that resolves when validation is complete
|
|
15815
15825
|
*/
|
|
15816
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
15826
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$q(context), async (context) => {
|
|
15817
15827
|
this.loggerService.log("riskGlobalService validate", {
|
|
15818
15828
|
context,
|
|
15819
15829
|
});
|
|
@@ -15884,14 +15894,14 @@ class RiskGlobalService {
|
|
|
15884
15894
|
}
|
|
15885
15895
|
}
|
|
15886
15896
|
|
|
15887
|
-
const METHOD_NAME_VALIDATE = "actionCoreService validate";
|
|
15897
|
+
const METHOD_NAME_VALIDATE$1 = "actionCoreService validate";
|
|
15888
15898
|
/**
|
|
15889
15899
|
* Creates a unique key for memoizing validate calls.
|
|
15890
15900
|
* Key format: "strategyName:exchangeName:frameName"
|
|
15891
15901
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
15892
15902
|
* @returns Unique string key for memoization
|
|
15893
15903
|
*/
|
|
15894
|
-
const CREATE_KEY_FN$
|
|
15904
|
+
const CREATE_KEY_FN$p = (context) => {
|
|
15895
15905
|
const parts = [context.strategyName, context.exchangeName];
|
|
15896
15906
|
if (context.frameName)
|
|
15897
15907
|
parts.push(context.frameName);
|
|
@@ -15935,17 +15945,17 @@ class ActionCoreService {
|
|
|
15935
15945
|
* @param context - Strategy execution context with strategyName, exchangeName and frameName
|
|
15936
15946
|
* @returns Promise that resolves when all validations complete
|
|
15937
15947
|
*/
|
|
15938
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
15939
|
-
this.loggerService.log(METHOD_NAME_VALIDATE, {
|
|
15948
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$p(context), async (context) => {
|
|
15949
|
+
this.loggerService.log(METHOD_NAME_VALIDATE$1, {
|
|
15940
15950
|
context,
|
|
15941
15951
|
});
|
|
15942
15952
|
const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
|
|
15943
|
-
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE);
|
|
15944
|
-
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE);
|
|
15945
|
-
context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE);
|
|
15946
|
-
riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE);
|
|
15947
|
-
riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE));
|
|
15948
|
-
actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE));
|
|
15953
|
+
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE$1);
|
|
15954
|
+
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE$1);
|
|
15955
|
+
context.frameName && this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE$1);
|
|
15956
|
+
riskName && this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1);
|
|
15957
|
+
riskList && riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE$1));
|
|
15958
|
+
actions && actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE$1));
|
|
15949
15959
|
});
|
|
15950
15960
|
/**
|
|
15951
15961
|
* Initializes all ClientAction instances for the strategy.
|
|
@@ -20978,7 +20988,7 @@ const ReportWriter = new ReportWriterAdapter();
|
|
|
20978
20988
|
* @param backtest - Whether running in backtest mode
|
|
20979
20989
|
* @returns Unique string key for memoization
|
|
20980
20990
|
*/
|
|
20981
|
-
const CREATE_KEY_FN$
|
|
20991
|
+
const CREATE_KEY_FN$o = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
20982
20992
|
const parts = [symbol, strategyName, exchangeName];
|
|
20983
20993
|
if (frameName)
|
|
20984
20994
|
parts.push(frameName);
|
|
@@ -21224,7 +21234,7 @@ class BacktestMarkdownService {
|
|
|
21224
21234
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
21225
21235
|
* Each combination gets its own isolated storage instance.
|
|
21226
21236
|
*/
|
|
21227
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
21237
|
+
this.getStorage = functoolsKit.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));
|
|
21228
21238
|
/**
|
|
21229
21239
|
* Processes tick events and accumulates closed signals.
|
|
21230
21240
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -21381,7 +21391,7 @@ class BacktestMarkdownService {
|
|
|
21381
21391
|
payload,
|
|
21382
21392
|
});
|
|
21383
21393
|
if (payload) {
|
|
21384
|
-
const key = CREATE_KEY_FN$
|
|
21394
|
+
const key = CREATE_KEY_FN$o(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
21385
21395
|
this.getStorage.clear(key);
|
|
21386
21396
|
}
|
|
21387
21397
|
else {
|
|
@@ -21443,7 +21453,7 @@ class BacktestMarkdownService {
|
|
|
21443
21453
|
* @param backtest - Whether running in backtest mode
|
|
21444
21454
|
* @returns Unique string key for memoization
|
|
21445
21455
|
*/
|
|
21446
|
-
const CREATE_KEY_FN$
|
|
21456
|
+
const CREATE_KEY_FN$n = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
21447
21457
|
const parts = [symbol, strategyName, exchangeName];
|
|
21448
21458
|
if (frameName)
|
|
21449
21459
|
parts.push(frameName);
|
|
@@ -21938,7 +21948,7 @@ class LiveMarkdownService {
|
|
|
21938
21948
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
21939
21949
|
* Each combination gets its own isolated storage instance.
|
|
21940
21950
|
*/
|
|
21941
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
21951
|
+
this.getStorage = functoolsKit.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));
|
|
21942
21952
|
/**
|
|
21943
21953
|
* Subscribes to live signal emitter to receive tick events.
|
|
21944
21954
|
* Protected against multiple subscriptions.
|
|
@@ -22156,7 +22166,7 @@ class LiveMarkdownService {
|
|
|
22156
22166
|
payload,
|
|
22157
22167
|
});
|
|
22158
22168
|
if (payload) {
|
|
22159
|
-
const key = CREATE_KEY_FN$
|
|
22169
|
+
const key = CREATE_KEY_FN$n(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
22160
22170
|
this.getStorage.clear(key);
|
|
22161
22171
|
}
|
|
22162
22172
|
else {
|
|
@@ -22176,7 +22186,7 @@ class LiveMarkdownService {
|
|
|
22176
22186
|
* @param backtest - Whether running in backtest mode
|
|
22177
22187
|
* @returns Unique string key for memoization
|
|
22178
22188
|
*/
|
|
22179
|
-
const CREATE_KEY_FN$
|
|
22189
|
+
const CREATE_KEY_FN$m = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
22180
22190
|
const parts = [symbol, strategyName, exchangeName];
|
|
22181
22191
|
if (frameName)
|
|
22182
22192
|
parts.push(frameName);
|
|
@@ -22465,7 +22475,7 @@ class ScheduleMarkdownService {
|
|
|
22465
22475
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
22466
22476
|
* Each combination gets its own isolated storage instance.
|
|
22467
22477
|
*/
|
|
22468
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
22478
|
+
this.getStorage = functoolsKit.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));
|
|
22469
22479
|
/**
|
|
22470
22480
|
* Subscribes to signal emitter to receive scheduled signal events.
|
|
22471
22481
|
* Protected against multiple subscriptions.
|
|
@@ -22668,7 +22678,7 @@ class ScheduleMarkdownService {
|
|
|
22668
22678
|
payload,
|
|
22669
22679
|
});
|
|
22670
22680
|
if (payload) {
|
|
22671
|
-
const key = CREATE_KEY_FN$
|
|
22681
|
+
const key = CREATE_KEY_FN$m(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
22672
22682
|
this.getStorage.clear(key);
|
|
22673
22683
|
}
|
|
22674
22684
|
else {
|
|
@@ -22688,7 +22698,7 @@ class ScheduleMarkdownService {
|
|
|
22688
22698
|
* @param backtest - Whether running in backtest mode
|
|
22689
22699
|
* @returns Unique string key for memoization
|
|
22690
22700
|
*/
|
|
22691
|
-
const CREATE_KEY_FN$
|
|
22701
|
+
const CREATE_KEY_FN$l = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
22692
22702
|
const parts = [symbol, strategyName, exchangeName];
|
|
22693
22703
|
if (frameName)
|
|
22694
22704
|
parts.push(frameName);
|
|
@@ -22933,7 +22943,7 @@ class PerformanceMarkdownService {
|
|
|
22933
22943
|
* Memoized function to get or create PerformanceStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
22934
22944
|
* Each combination gets its own isolated storage instance.
|
|
22935
22945
|
*/
|
|
22936
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
22946
|
+
this.getStorage = functoolsKit.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));
|
|
22937
22947
|
/**
|
|
22938
22948
|
* Subscribes to performance emitter to receive performance events.
|
|
22939
22949
|
* Protected against multiple subscriptions.
|
|
@@ -23100,7 +23110,7 @@ class PerformanceMarkdownService {
|
|
|
23100
23110
|
payload,
|
|
23101
23111
|
});
|
|
23102
23112
|
if (payload) {
|
|
23103
|
-
const key = CREATE_KEY_FN$
|
|
23113
|
+
const key = CREATE_KEY_FN$l(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
23104
23114
|
this.getStorage.clear(key);
|
|
23105
23115
|
}
|
|
23106
23116
|
else {
|
|
@@ -23579,7 +23589,7 @@ class WalkerMarkdownService {
|
|
|
23579
23589
|
* @param backtest - Whether running in backtest mode
|
|
23580
23590
|
* @returns Unique string key for memoization
|
|
23581
23591
|
*/
|
|
23582
|
-
const CREATE_KEY_FN$
|
|
23592
|
+
const CREATE_KEY_FN$k = (exchangeName, frameName, backtest) => {
|
|
23583
23593
|
const parts = [exchangeName];
|
|
23584
23594
|
if (frameName)
|
|
23585
23595
|
parts.push(frameName);
|
|
@@ -24026,7 +24036,7 @@ class HeatMarkdownService {
|
|
|
24026
24036
|
* Memoized function to get or create HeatmapStorage for exchange, frame and backtest mode.
|
|
24027
24037
|
* Each exchangeName + frameName + backtest mode combination gets its own isolated heatmap storage instance.
|
|
24028
24038
|
*/
|
|
24029
|
-
this.getStorage = functoolsKit.memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
24039
|
+
this.getStorage = functoolsKit.memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$k(exchangeName, frameName, backtest), (exchangeName, frameName, backtest) => new HeatmapStorage(exchangeName, frameName, backtest));
|
|
24030
24040
|
/**
|
|
24031
24041
|
* Subscribes to signal emitter to receive tick events.
|
|
24032
24042
|
* Protected against multiple subscriptions.
|
|
@@ -24244,7 +24254,7 @@ class HeatMarkdownService {
|
|
|
24244
24254
|
payload,
|
|
24245
24255
|
});
|
|
24246
24256
|
if (payload) {
|
|
24247
|
-
const key = CREATE_KEY_FN$
|
|
24257
|
+
const key = CREATE_KEY_FN$k(payload.exchangeName, payload.frameName, payload.backtest);
|
|
24248
24258
|
this.getStorage.clear(key);
|
|
24249
24259
|
}
|
|
24250
24260
|
else {
|
|
@@ -25275,7 +25285,7 @@ class ClientPartial {
|
|
|
25275
25285
|
* @param backtest - Whether running in backtest mode
|
|
25276
25286
|
* @returns Unique string key for memoization
|
|
25277
25287
|
*/
|
|
25278
|
-
const CREATE_KEY_FN$
|
|
25288
|
+
const CREATE_KEY_FN$j = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
|
|
25279
25289
|
/**
|
|
25280
25290
|
* Creates a callback function for emitting profit events to partialProfitSubject.
|
|
25281
25291
|
*
|
|
@@ -25397,7 +25407,7 @@ class PartialConnectionService {
|
|
|
25397
25407
|
* Key format: "signalId:backtest" or "signalId:live"
|
|
25398
25408
|
* Value: ClientPartial instance with logger and event emitters
|
|
25399
25409
|
*/
|
|
25400
|
-
this.getPartial = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$
|
|
25410
|
+
this.getPartial = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$j(signalId, backtest), (signalId, backtest) => {
|
|
25401
25411
|
return new ClientPartial({
|
|
25402
25412
|
signalId,
|
|
25403
25413
|
logger: this.loggerService,
|
|
@@ -25487,7 +25497,7 @@ class PartialConnectionService {
|
|
|
25487
25497
|
const partial = this.getPartial(data.id, backtest);
|
|
25488
25498
|
await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
|
|
25489
25499
|
await partial.clear(symbol, data, priceClose, backtest);
|
|
25490
|
-
const key = CREATE_KEY_FN$
|
|
25500
|
+
const key = CREATE_KEY_FN$j(data.id, backtest);
|
|
25491
25501
|
this.getPartial.clear(key);
|
|
25492
25502
|
};
|
|
25493
25503
|
}
|
|
@@ -25503,7 +25513,7 @@ class PartialConnectionService {
|
|
|
25503
25513
|
* @param backtest - Whether running in backtest mode
|
|
25504
25514
|
* @returns Unique string key for memoization
|
|
25505
25515
|
*/
|
|
25506
|
-
const CREATE_KEY_FN$
|
|
25516
|
+
const CREATE_KEY_FN$i = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
25507
25517
|
const parts = [symbol, strategyName, exchangeName];
|
|
25508
25518
|
if (frameName)
|
|
25509
25519
|
parts.push(frameName);
|
|
@@ -25726,7 +25736,7 @@ class PartialMarkdownService {
|
|
|
25726
25736
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
25727
25737
|
* Each combination gets its own isolated storage instance.
|
|
25728
25738
|
*/
|
|
25729
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
25739
|
+
this.getStorage = functoolsKit.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));
|
|
25730
25740
|
/**
|
|
25731
25741
|
* Subscribes to partial profit/loss signal emitters to receive events.
|
|
25732
25742
|
* Protected against multiple subscriptions.
|
|
@@ -25936,7 +25946,7 @@ class PartialMarkdownService {
|
|
|
25936
25946
|
payload,
|
|
25937
25947
|
});
|
|
25938
25948
|
if (payload) {
|
|
25939
|
-
const key = CREATE_KEY_FN$
|
|
25949
|
+
const key = CREATE_KEY_FN$i(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
25940
25950
|
this.getStorage.clear(key);
|
|
25941
25951
|
}
|
|
25942
25952
|
else {
|
|
@@ -25952,7 +25962,7 @@ class PartialMarkdownService {
|
|
|
25952
25962
|
* @param context - Context with strategyName, exchangeName, frameName
|
|
25953
25963
|
* @returns Unique string key for memoization
|
|
25954
25964
|
*/
|
|
25955
|
-
const CREATE_KEY_FN$
|
|
25965
|
+
const CREATE_KEY_FN$h = (context) => {
|
|
25956
25966
|
const parts = [context.strategyName, context.exchangeName];
|
|
25957
25967
|
if (context.frameName)
|
|
25958
25968
|
parts.push(context.frameName);
|
|
@@ -26026,7 +26036,7 @@ class PartialGlobalService {
|
|
|
26026
26036
|
* @param context - Context with strategyName, exchangeName and frameName
|
|
26027
26037
|
* @param methodName - Name of the calling method for error tracking
|
|
26028
26038
|
*/
|
|
26029
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
26039
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$h(context), (context, methodName) => {
|
|
26030
26040
|
this.loggerService.log("partialGlobalService validate", {
|
|
26031
26041
|
context,
|
|
26032
26042
|
methodName,
|
|
@@ -26481,7 +26491,7 @@ class ClientBreakeven {
|
|
|
26481
26491
|
* @param backtest - Whether running in backtest mode
|
|
26482
26492
|
* @returns Unique string key for memoization
|
|
26483
26493
|
*/
|
|
26484
|
-
const CREATE_KEY_FN$
|
|
26494
|
+
const CREATE_KEY_FN$g = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
|
|
26485
26495
|
/**
|
|
26486
26496
|
* Creates a callback function for emitting breakeven events to breakevenSubject.
|
|
26487
26497
|
*
|
|
@@ -26567,7 +26577,7 @@ class BreakevenConnectionService {
|
|
|
26567
26577
|
* Key format: "signalId:backtest" or "signalId:live"
|
|
26568
26578
|
* Value: ClientBreakeven instance with logger and event emitter
|
|
26569
26579
|
*/
|
|
26570
|
-
this.getBreakeven = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$
|
|
26580
|
+
this.getBreakeven = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$g(signalId, backtest), (signalId, backtest) => {
|
|
26571
26581
|
return new ClientBreakeven({
|
|
26572
26582
|
signalId,
|
|
26573
26583
|
logger: this.loggerService,
|
|
@@ -26628,7 +26638,7 @@ class BreakevenConnectionService {
|
|
|
26628
26638
|
const breakeven = this.getBreakeven(data.id, backtest);
|
|
26629
26639
|
await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
|
|
26630
26640
|
await breakeven.clear(symbol, data, priceClose, backtest);
|
|
26631
|
-
const key = CREATE_KEY_FN$
|
|
26641
|
+
const key = CREATE_KEY_FN$g(data.id, backtest);
|
|
26632
26642
|
this.getBreakeven.clear(key);
|
|
26633
26643
|
};
|
|
26634
26644
|
}
|
|
@@ -26644,7 +26654,7 @@ class BreakevenConnectionService {
|
|
|
26644
26654
|
* @param backtest - Whether running in backtest mode
|
|
26645
26655
|
* @returns Unique string key for memoization
|
|
26646
26656
|
*/
|
|
26647
|
-
const CREATE_KEY_FN$
|
|
26657
|
+
const CREATE_KEY_FN$f = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
26648
26658
|
const parts = [symbol, strategyName, exchangeName];
|
|
26649
26659
|
if (frameName)
|
|
26650
26660
|
parts.push(frameName);
|
|
@@ -26819,7 +26829,7 @@ class BreakevenMarkdownService {
|
|
|
26819
26829
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
26820
26830
|
* Each combination gets its own isolated storage instance.
|
|
26821
26831
|
*/
|
|
26822
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
26832
|
+
this.getStorage = functoolsKit.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));
|
|
26823
26833
|
/**
|
|
26824
26834
|
* Subscribes to breakeven signal emitter to receive events.
|
|
26825
26835
|
* Protected against multiple subscriptions.
|
|
@@ -27008,7 +27018,7 @@ class BreakevenMarkdownService {
|
|
|
27008
27018
|
payload,
|
|
27009
27019
|
});
|
|
27010
27020
|
if (payload) {
|
|
27011
|
-
const key = CREATE_KEY_FN$
|
|
27021
|
+
const key = CREATE_KEY_FN$f(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
27012
27022
|
this.getStorage.clear(key);
|
|
27013
27023
|
}
|
|
27014
27024
|
else {
|
|
@@ -27024,7 +27034,7 @@ class BreakevenMarkdownService {
|
|
|
27024
27034
|
* @param context - Context with strategyName, exchangeName, frameName
|
|
27025
27035
|
* @returns Unique string key for memoization
|
|
27026
27036
|
*/
|
|
27027
|
-
const CREATE_KEY_FN$
|
|
27037
|
+
const CREATE_KEY_FN$e = (context) => {
|
|
27028
27038
|
const parts = [context.strategyName, context.exchangeName];
|
|
27029
27039
|
if (context.frameName)
|
|
27030
27040
|
parts.push(context.frameName);
|
|
@@ -27098,7 +27108,7 @@ class BreakevenGlobalService {
|
|
|
27098
27108
|
* @param context - Context with strategyName, exchangeName and frameName
|
|
27099
27109
|
* @param methodName - Name of the calling method for error tracking
|
|
27100
27110
|
*/
|
|
27101
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
27111
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$e(context), (context, methodName) => {
|
|
27102
27112
|
this.loggerService.log("breakevenGlobalService validate", {
|
|
27103
27113
|
context,
|
|
27104
27114
|
methodName,
|
|
@@ -27319,7 +27329,7 @@ class ConfigValidationService {
|
|
|
27319
27329
|
* @param backtest - Whether running in backtest mode
|
|
27320
27330
|
* @returns Unique string key for memoization
|
|
27321
27331
|
*/
|
|
27322
|
-
const CREATE_KEY_FN$
|
|
27332
|
+
const CREATE_KEY_FN$d = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
27323
27333
|
const parts = [symbol, strategyName, exchangeName];
|
|
27324
27334
|
if (frameName)
|
|
27325
27335
|
parts.push(frameName);
|
|
@@ -27486,7 +27496,7 @@ class RiskMarkdownService {
|
|
|
27486
27496
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
27487
27497
|
* Each combination gets its own isolated storage instance.
|
|
27488
27498
|
*/
|
|
27489
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
27499
|
+
this.getStorage = functoolsKit.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));
|
|
27490
27500
|
/**
|
|
27491
27501
|
* Subscribes to risk rejection emitter to receive rejection events.
|
|
27492
27502
|
* Protected against multiple subscriptions.
|
|
@@ -27675,7 +27685,7 @@ class RiskMarkdownService {
|
|
|
27675
27685
|
payload,
|
|
27676
27686
|
});
|
|
27677
27687
|
if (payload) {
|
|
27678
|
-
const key = CREATE_KEY_FN$
|
|
27688
|
+
const key = CREATE_KEY_FN$d(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
27679
27689
|
this.getStorage.clear(key);
|
|
27680
27690
|
}
|
|
27681
27691
|
else {
|
|
@@ -30057,7 +30067,7 @@ class HighestProfitReportService {
|
|
|
30057
30067
|
* @returns Colon-separated key string for memoization
|
|
30058
30068
|
* @internal
|
|
30059
30069
|
*/
|
|
30060
|
-
const CREATE_KEY_FN$
|
|
30070
|
+
const CREATE_KEY_FN$c = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
30061
30071
|
const parts = [symbol, strategyName, exchangeName];
|
|
30062
30072
|
if (frameName)
|
|
30063
30073
|
parts.push(frameName);
|
|
@@ -30299,7 +30309,7 @@ class StrategyMarkdownService {
|
|
|
30299
30309
|
*
|
|
30300
30310
|
* @internal
|
|
30301
30311
|
*/
|
|
30302
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
30312
|
+
this.getStorage = functoolsKit.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));
|
|
30303
30313
|
/**
|
|
30304
30314
|
* Records a cancel-scheduled event when a scheduled signal is cancelled.
|
|
30305
30315
|
*
|
|
@@ -30873,7 +30883,7 @@ class StrategyMarkdownService {
|
|
|
30873
30883
|
this.clear = async (payload) => {
|
|
30874
30884
|
this.loggerService.log("strategyMarkdownService clear", { payload });
|
|
30875
30885
|
if (payload) {
|
|
30876
|
-
const key = CREATE_KEY_FN$
|
|
30886
|
+
const key = CREATE_KEY_FN$c(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
30877
30887
|
this.getStorage.clear(key);
|
|
30878
30888
|
}
|
|
30879
30889
|
else {
|
|
@@ -30981,7 +30991,7 @@ class StrategyMarkdownService {
|
|
|
30981
30991
|
* Creates a unique key for memoizing ReportStorage instances.
|
|
30982
30992
|
* Key format: "symbol:strategyName:exchangeName[:frameName]:backtest|live"
|
|
30983
30993
|
*/
|
|
30984
|
-
const CREATE_KEY_FN$
|
|
30994
|
+
const CREATE_KEY_FN$b = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
30985
30995
|
const parts = [symbol, strategyName, exchangeName];
|
|
30986
30996
|
if (frameName)
|
|
30987
30997
|
parts.push(frameName);
|
|
@@ -31174,7 +31184,7 @@ let ReportStorage$2 = class ReportStorage {
|
|
|
31174
31184
|
class SyncMarkdownService {
|
|
31175
31185
|
constructor() {
|
|
31176
31186
|
this.loggerService = inject(TYPES.loggerService);
|
|
31177
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
31187
|
+
this.getStorage = functoolsKit.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));
|
|
31178
31188
|
/**
|
|
31179
31189
|
* Subscribes to `syncSubject` to start receiving `SignalSyncContract` events.
|
|
31180
31190
|
* Protected against multiple subscriptions via `singleshot` — subsequent calls
|
|
@@ -31370,7 +31380,7 @@ class SyncMarkdownService {
|
|
|
31370
31380
|
this.clear = async (payload) => {
|
|
31371
31381
|
this.loggerService.log("syncMarkdownService clear", { payload });
|
|
31372
31382
|
if (payload) {
|
|
31373
|
-
const key = CREATE_KEY_FN$
|
|
31383
|
+
const key = CREATE_KEY_FN$b(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
31374
31384
|
this.getStorage.clear(key);
|
|
31375
31385
|
}
|
|
31376
31386
|
else {
|
|
@@ -31383,7 +31393,7 @@ class SyncMarkdownService {
|
|
|
31383
31393
|
/**
|
|
31384
31394
|
* Creates a unique memoization key for a symbol-strategy-exchange-frame-backtest combination.
|
|
31385
31395
|
*/
|
|
31386
|
-
const CREATE_KEY_FN$
|
|
31396
|
+
const CREATE_KEY_FN$a = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
31387
31397
|
const parts = [symbol, strategyName, exchangeName];
|
|
31388
31398
|
if (frameName)
|
|
31389
31399
|
parts.push(frameName);
|
|
@@ -31559,7 +31569,7 @@ let ReportStorage$1 = class ReportStorage {
|
|
|
31559
31569
|
class HighestProfitMarkdownService {
|
|
31560
31570
|
constructor() {
|
|
31561
31571
|
this.loggerService = inject(TYPES.loggerService);
|
|
31562
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
31572
|
+
this.getStorage = functoolsKit.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));
|
|
31563
31573
|
/**
|
|
31564
31574
|
* Subscribes to `highestProfitSubject` to start receiving `HighestProfitContract`
|
|
31565
31575
|
* events. Protected against multiple subscriptions via `singleshot` — subsequent
|
|
@@ -31725,7 +31735,7 @@ class HighestProfitMarkdownService {
|
|
|
31725
31735
|
this.clear = async (payload) => {
|
|
31726
31736
|
this.loggerService.log("highestProfitMarkdownService clear", { payload });
|
|
31727
31737
|
if (payload) {
|
|
31728
|
-
const key = CREATE_KEY_FN$
|
|
31738
|
+
const key = CREATE_KEY_FN$a(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
31729
31739
|
this.getStorage.clear(key);
|
|
31730
31740
|
}
|
|
31731
31741
|
else {
|
|
@@ -31747,7 +31757,7 @@ const LISTEN_TIMEOUT$1 = 120000;
|
|
|
31747
31757
|
* @param backtest - Whether running in backtest mode
|
|
31748
31758
|
* @returns Unique string key for memoization
|
|
31749
31759
|
*/
|
|
31750
|
-
const CREATE_KEY_FN$
|
|
31760
|
+
const CREATE_KEY_FN$9 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
31751
31761
|
const parts = [symbol, strategyName, exchangeName];
|
|
31752
31762
|
if (frameName)
|
|
31753
31763
|
parts.push(frameName);
|
|
@@ -31790,7 +31800,7 @@ class PriceMetaService {
|
|
|
31790
31800
|
* Each subject holds the latest currentPrice emitted by the strategy iterator for that key.
|
|
31791
31801
|
* Instances are cached until clear() is called.
|
|
31792
31802
|
*/
|
|
31793
|
-
this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
31803
|
+
this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$9(symbol, strategyName, exchangeName, frameName, backtest), () => new functoolsKit.BehaviorSubject());
|
|
31794
31804
|
/**
|
|
31795
31805
|
* Returns the current market price for the given symbol and context.
|
|
31796
31806
|
*
|
|
@@ -31819,10 +31829,10 @@ class PriceMetaService {
|
|
|
31819
31829
|
if (source.data) {
|
|
31820
31830
|
return source.data;
|
|
31821
31831
|
}
|
|
31822
|
-
console.warn(`PriceMetaService: No currentPrice available for ${CREATE_KEY_FN$
|
|
31832
|
+
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...`);
|
|
31823
31833
|
const currentPrice = await functoolsKit.waitForNext(source, (data) => !!data, LISTEN_TIMEOUT$1);
|
|
31824
31834
|
if (typeof currentPrice === "symbol") {
|
|
31825
|
-
throw new Error(`PriceMetaService: Timeout while waiting for currentPrice for ${CREATE_KEY_FN$
|
|
31835
|
+
throw new Error(`PriceMetaService: Timeout while waiting for currentPrice for ${CREATE_KEY_FN$9(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
|
|
31826
31836
|
}
|
|
31827
31837
|
return currentPrice;
|
|
31828
31838
|
};
|
|
@@ -31864,7 +31874,7 @@ class PriceMetaService {
|
|
|
31864
31874
|
this.getSource.clear();
|
|
31865
31875
|
return;
|
|
31866
31876
|
}
|
|
31867
|
-
const key = CREATE_KEY_FN$
|
|
31877
|
+
const key = CREATE_KEY_FN$9(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
31868
31878
|
this.getSource.clear(key);
|
|
31869
31879
|
};
|
|
31870
31880
|
}
|
|
@@ -31882,7 +31892,7 @@ const LISTEN_TIMEOUT = 120000;
|
|
|
31882
31892
|
* @param backtest - Whether running in backtest mode
|
|
31883
31893
|
* @returns Unique string key for memoization
|
|
31884
31894
|
*/
|
|
31885
|
-
const CREATE_KEY_FN$
|
|
31895
|
+
const CREATE_KEY_FN$8 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
31886
31896
|
const parts = [symbol, strategyName, exchangeName];
|
|
31887
31897
|
if (frameName)
|
|
31888
31898
|
parts.push(frameName);
|
|
@@ -31925,7 +31935,7 @@ class TimeMetaService {
|
|
|
31925
31935
|
* Each subject holds the latest createdAt timestamp emitted by the strategy iterator for that key.
|
|
31926
31936
|
* Instances are cached until clear() is called.
|
|
31927
31937
|
*/
|
|
31928
|
-
this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
31938
|
+
this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$8(symbol, strategyName, exchangeName, frameName, backtest), () => new functoolsKit.BehaviorSubject());
|
|
31929
31939
|
/**
|
|
31930
31940
|
* Returns the current candle timestamp (in milliseconds) for the given symbol and context.
|
|
31931
31941
|
*
|
|
@@ -31953,10 +31963,10 @@ class TimeMetaService {
|
|
|
31953
31963
|
if (source.data) {
|
|
31954
31964
|
return source.data;
|
|
31955
31965
|
}
|
|
31956
|
-
console.warn(`TimeMetaService: No timestamp available for ${CREATE_KEY_FN$
|
|
31966
|
+
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...`);
|
|
31957
31967
|
const timestamp = await functoolsKit.waitForNext(source, (data) => !!data, LISTEN_TIMEOUT);
|
|
31958
31968
|
if (typeof timestamp === "symbol") {
|
|
31959
|
-
throw new Error(`TimeMetaService: Timeout while waiting for timestamp for ${CREATE_KEY_FN$
|
|
31969
|
+
throw new Error(`TimeMetaService: Timeout while waiting for timestamp for ${CREATE_KEY_FN$8(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
|
|
31960
31970
|
}
|
|
31961
31971
|
return timestamp;
|
|
31962
31972
|
};
|
|
@@ -31998,7 +32008,7 @@ class TimeMetaService {
|
|
|
31998
32008
|
this.getSource.clear();
|
|
31999
32009
|
return;
|
|
32000
32010
|
}
|
|
32001
|
-
const key = CREATE_KEY_FN$
|
|
32011
|
+
const key = CREATE_KEY_FN$8(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
32002
32012
|
this.getSource.clear(key);
|
|
32003
32013
|
};
|
|
32004
32014
|
}
|
|
@@ -32094,7 +32104,7 @@ class MaxDrawdownReportService {
|
|
|
32094
32104
|
/**
|
|
32095
32105
|
* Creates a unique memoization key for a symbol-strategy-exchange-frame-backtest combination.
|
|
32096
32106
|
*/
|
|
32097
|
-
const CREATE_KEY_FN$
|
|
32107
|
+
const CREATE_KEY_FN$7 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
32098
32108
|
const parts = [symbol, strategyName, exchangeName];
|
|
32099
32109
|
if (frameName)
|
|
32100
32110
|
parts.push(frameName);
|
|
@@ -32218,7 +32228,7 @@ class ReportStorage {
|
|
|
32218
32228
|
class MaxDrawdownMarkdownService {
|
|
32219
32229
|
constructor() {
|
|
32220
32230
|
this.loggerService = inject(TYPES.loggerService);
|
|
32221
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
32231
|
+
this.getStorage = functoolsKit.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));
|
|
32222
32232
|
/**
|
|
32223
32233
|
* Subscribes to `maxDrawdownSubject` to start receiving `MaxDrawdownContract`
|
|
32224
32234
|
* events. Protected against multiple subscriptions via `singleshot`.
|
|
@@ -32297,7 +32307,7 @@ class MaxDrawdownMarkdownService {
|
|
|
32297
32307
|
this.clear = async (payload) => {
|
|
32298
32308
|
this.loggerService.log("maxDrawdownMarkdownService clear", { payload });
|
|
32299
32309
|
if (payload) {
|
|
32300
|
-
const key = CREATE_KEY_FN$
|
|
32310
|
+
const key = CREATE_KEY_FN$7(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
32301
32311
|
this.getStorage.clear(key);
|
|
32302
32312
|
}
|
|
32303
32313
|
else {
|
|
@@ -32307,6 +32317,125 @@ class MaxDrawdownMarkdownService {
|
|
|
32307
32317
|
}
|
|
32308
32318
|
}
|
|
32309
32319
|
|
|
32320
|
+
const METHOD_NAME_COMMIT_SIGNAL_NOTIFY = "notificationHelperService.commitSignalNotify";
|
|
32321
|
+
const METHOD_NAME_VALIDATE = "notificationHelperService.validate";
|
|
32322
|
+
/**
|
|
32323
|
+
* Creates a unique key for memoizing validate calls.
|
|
32324
|
+
* Key format: "strategyName:exchangeName:frameName"
|
|
32325
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
32326
|
+
* @returns Unique string key for memoization
|
|
32327
|
+
*/
|
|
32328
|
+
const CREATE_KEY_FN$6 = (context) => {
|
|
32329
|
+
const parts = [context.strategyName, context.exchangeName];
|
|
32330
|
+
if (context.frameName)
|
|
32331
|
+
parts.push(context.frameName);
|
|
32332
|
+
return parts.join(":");
|
|
32333
|
+
};
|
|
32334
|
+
/**
|
|
32335
|
+
* Helper service for emitting signal info notifications.
|
|
32336
|
+
*
|
|
32337
|
+
* Handles validation (memoized per context) and emission of `signal.info` events
|
|
32338
|
+
* via `signalNotifySubject`. Used internally by the framework action pipeline —
|
|
32339
|
+
* end users interact with this via `commitSignalNotify()` in `onActivePing` callbacks.
|
|
32340
|
+
*/
|
|
32341
|
+
class NotificationHelperService {
|
|
32342
|
+
constructor() {
|
|
32343
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
32344
|
+
this.strategySchemaService = inject(TYPES.strategySchemaService);
|
|
32345
|
+
this.riskValidationService = inject(TYPES.riskValidationService);
|
|
32346
|
+
this.strategyValidationService = inject(TYPES.strategyValidationService);
|
|
32347
|
+
this.exchangeValidationService = inject(TYPES.exchangeValidationService);
|
|
32348
|
+
this.frameValidationService = inject(TYPES.frameValidationService);
|
|
32349
|
+
this.actionValidationService = inject(TYPES.actionValidationService);
|
|
32350
|
+
this.strategyCoreService = inject(TYPES.strategyCoreService);
|
|
32351
|
+
this.timeMetaService = inject(TYPES.timeMetaService);
|
|
32352
|
+
/**
|
|
32353
|
+
* Validates strategy, exchange, frame, risk, and action schemas for the given context.
|
|
32354
|
+
*
|
|
32355
|
+
* Memoized per unique `"strategyName:exchangeName[:frameName]"` key — subsequent calls
|
|
32356
|
+
* with the same context are no-ops, so validation runs at most once per context.
|
|
32357
|
+
*
|
|
32358
|
+
* @param context - Routing context: strategyName, exchangeName, frameName
|
|
32359
|
+
* @throws {Error} If any registered schema fails validation
|
|
32360
|
+
*/
|
|
32361
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$6(context), async (context) => {
|
|
32362
|
+
this.loggerService.log(METHOD_NAME_VALIDATE, {
|
|
32363
|
+
context,
|
|
32364
|
+
});
|
|
32365
|
+
this.strategyValidationService.validate(context.strategyName, METHOD_NAME_VALIDATE);
|
|
32366
|
+
this.exchangeValidationService.validate(context.exchangeName, METHOD_NAME_VALIDATE);
|
|
32367
|
+
const { riskName, riskList, actions } = this.strategySchemaService.get(context.strategyName);
|
|
32368
|
+
context.frameName &&
|
|
32369
|
+
this.frameValidationService.validate(context.frameName, METHOD_NAME_VALIDATE);
|
|
32370
|
+
riskName &&
|
|
32371
|
+
this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE);
|
|
32372
|
+
riskList &&
|
|
32373
|
+
riskList.forEach((riskName) => this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE));
|
|
32374
|
+
actions &&
|
|
32375
|
+
actions.forEach((actionName) => this.actionValidationService.validate(actionName, METHOD_NAME_VALIDATE));
|
|
32376
|
+
});
|
|
32377
|
+
/**
|
|
32378
|
+
* Emits a `signal.info` notification for the currently active pending signal.
|
|
32379
|
+
*
|
|
32380
|
+
* Validates all schemas (via memoized `validate`), resolves the pending signal
|
|
32381
|
+
* for the given symbol, then emits a `SignalInfoContract` via `signalNotifySubject`,
|
|
32382
|
+
* which is routed to all registered `listenSignalNotify` callbacks and persisted
|
|
32383
|
+
* by `NotificationAdapter`.
|
|
32384
|
+
*
|
|
32385
|
+
* @param payload - Optional notification fields (notificationId, notificationNote)
|
|
32386
|
+
* @param symbol - Trading pair symbol (e.g. "BTCUSDT")
|
|
32387
|
+
* @param currentPrice - Market price at the time of the call
|
|
32388
|
+
* @param context - Routing context: strategyName, exchangeName, frameName
|
|
32389
|
+
* @param backtest - true when called during a backtest run
|
|
32390
|
+
*
|
|
32391
|
+
* @throws {Error} If no active pending signal is found for the given symbol
|
|
32392
|
+
*
|
|
32393
|
+
* @example
|
|
32394
|
+
* ```typescript
|
|
32395
|
+
* // Inside onActivePing callback:
|
|
32396
|
+
* await commitSignalNotify("BTCUSDT", {
|
|
32397
|
+
* notificationNote: "RSI crossed 70, consider closing",
|
|
32398
|
+
* notificationId: "msg-123",
|
|
32399
|
+
* });
|
|
32400
|
+
* ```
|
|
32401
|
+
*/
|
|
32402
|
+
this.commitSignalNotify = async (payload, symbol, currentPrice, context, backtest) => {
|
|
32403
|
+
this.loggerService.info(METHOD_NAME_COMMIT_SIGNAL_NOTIFY, {
|
|
32404
|
+
symbol,
|
|
32405
|
+
context,
|
|
32406
|
+
backtest,
|
|
32407
|
+
currentPrice,
|
|
32408
|
+
});
|
|
32409
|
+
this.validate(context);
|
|
32410
|
+
const pendingSignal = await this.strategyCoreService.getPendingSignal(backtest, symbol, currentPrice, {
|
|
32411
|
+
strategyName: context.strategyName,
|
|
32412
|
+
exchangeName: context.exchangeName,
|
|
32413
|
+
frameName: "",
|
|
32414
|
+
});
|
|
32415
|
+
if (!pendingSignal) {
|
|
32416
|
+
throw new Error(`SignalUtils notify No pending signal found symbol=${symbol} `);
|
|
32417
|
+
}
|
|
32418
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, {
|
|
32419
|
+
strategyName: context.strategyName,
|
|
32420
|
+
exchangeName: context.exchangeName,
|
|
32421
|
+
frameName: context.frameName,
|
|
32422
|
+
}, backtest);
|
|
32423
|
+
await signalNotifySubject.next({
|
|
32424
|
+
backtest,
|
|
32425
|
+
symbol,
|
|
32426
|
+
currentPrice,
|
|
32427
|
+
data: pendingSignal,
|
|
32428
|
+
exchangeName: context.exchangeName,
|
|
32429
|
+
strategyName: context.strategyName,
|
|
32430
|
+
frameName: context.frameName,
|
|
32431
|
+
note: payload.notificationNote || pendingSignal.note,
|
|
32432
|
+
notificationId: payload.notificationId,
|
|
32433
|
+
timestamp,
|
|
32434
|
+
});
|
|
32435
|
+
};
|
|
32436
|
+
}
|
|
32437
|
+
}
|
|
32438
|
+
|
|
32310
32439
|
{
|
|
32311
32440
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
32312
32441
|
}
|
|
@@ -32395,6 +32524,9 @@ class MaxDrawdownMarkdownService {
|
|
|
32395
32524
|
provide(TYPES.highestProfitReportService, () => new HighestProfitReportService());
|
|
32396
32525
|
provide(TYPES.maxDrawdownReportService, () => new MaxDrawdownReportService());
|
|
32397
32526
|
}
|
|
32527
|
+
{
|
|
32528
|
+
provide(TYPES.notificationHelperService, () => new NotificationHelperService());
|
|
32529
|
+
}
|
|
32398
32530
|
{
|
|
32399
32531
|
provide(TYPES.exchangeValidationService, () => new ExchangeValidationService());
|
|
32400
32532
|
provide(TYPES.strategyValidationService, () => new StrategyValidationService());
|
|
@@ -32495,6 +32627,9 @@ const reportServices = {
|
|
|
32495
32627
|
highestProfitReportService: inject(TYPES.highestProfitReportService),
|
|
32496
32628
|
maxDrawdownReportService: inject(TYPES.maxDrawdownReportService),
|
|
32497
32629
|
};
|
|
32630
|
+
const helperServices = {
|
|
32631
|
+
notificationHelperService: inject(TYPES.notificationHelperService),
|
|
32632
|
+
};
|
|
32498
32633
|
const validationServices = {
|
|
32499
32634
|
exchangeValidationService: inject(TYPES.exchangeValidationService),
|
|
32500
32635
|
strategyValidationService: inject(TYPES.strategyValidationService),
|
|
@@ -32520,6 +32655,7 @@ const backtest = {
|
|
|
32520
32655
|
...markdownServices,
|
|
32521
32656
|
...reportServices,
|
|
32522
32657
|
...validationServices,
|
|
32658
|
+
...helperServices,
|
|
32523
32659
|
};
|
|
32524
32660
|
init();
|
|
32525
32661
|
|
|
@@ -35436,6 +35572,7 @@ const GET_POSITION_ENTRY_OVERLAP_METHOD_NAME = "strategy.getPositionEntryOverlap
|
|
|
35436
35572
|
const GET_POSITION_PARTIAL_OVERLAP_METHOD_NAME = "strategy.getPositionPartialOverlap";
|
|
35437
35573
|
const HAS_NO_PENDING_SIGNAL_METHOD_NAME = "strategy.hasNoPendingSignal";
|
|
35438
35574
|
const HAS_NO_SCHEDULED_SIGNAL_METHOD_NAME = "strategy.hasNoScheduledSignal";
|
|
35575
|
+
const COMMIT_SIGNAL_NOTIFY_METHOD_NAME = "strategy.commitSignalNotify";
|
|
35439
35576
|
/**
|
|
35440
35577
|
* Cancels the scheduled signal without stopping the strategy.
|
|
35441
35578
|
*
|
|
@@ -37400,6 +37537,50 @@ async function hasNoScheduledSignal(symbol) {
|
|
|
37400
37537
|
const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
|
|
37401
37538
|
return await functoolsKit.not(backtest.strategyCoreService.hasScheduledSignal(isBacktest, symbol, { exchangeName, frameName, strategyName }));
|
|
37402
37539
|
}
|
|
37540
|
+
/**
|
|
37541
|
+
* Emits a `signal.info` notification for the currently active pending signal.
|
|
37542
|
+
*
|
|
37543
|
+
* Broadcasts a user-defined informational note without affecting position state.
|
|
37544
|
+
* Useful for annotating strategy decisions, triggering external alerts, or logging
|
|
37545
|
+
* mid-position events (e.g. RSI crossing a threshold, volume spike detected).
|
|
37546
|
+
*
|
|
37547
|
+
* Automatically reads backtest/live mode from execution context.
|
|
37548
|
+
* Automatically reads strategyName, exchangeName, frameName from method context.
|
|
37549
|
+
* Automatically fetches current price via getAveragePrice.
|
|
37550
|
+
*
|
|
37551
|
+
* @param symbol - Trading pair symbol (e.g. "BTCUSDT")
|
|
37552
|
+
* @param payload - Optional notification fields
|
|
37553
|
+
* @param payload.notificationNote - Human-readable note. Falls back to signal.note if omitted.
|
|
37554
|
+
* @param payload.notificationId - Optional correlation ID for external systems (e.g. Telegram message ID).
|
|
37555
|
+
*
|
|
37556
|
+
* @throws {Error} If called outside an execution context
|
|
37557
|
+
* @throws {Error} If called outside a method context
|
|
37558
|
+
* @throws {Error} If no active pending signal exists for the given symbol
|
|
37559
|
+
*
|
|
37560
|
+
* @example
|
|
37561
|
+
* ```typescript
|
|
37562
|
+
* import { commitSignalNotify } from "backtest-kit";
|
|
37563
|
+
*
|
|
37564
|
+
* // Inside onActivePing callback:
|
|
37565
|
+
* await commitSignalNotify("BTCUSDT", {
|
|
37566
|
+
* notificationNote: "RSI crossed 70, consider closing",
|
|
37567
|
+
* notificationId: "msg-123",
|
|
37568
|
+
* });
|
|
37569
|
+
* ```
|
|
37570
|
+
*/
|
|
37571
|
+
async function commitSignalNotify(symbol, payload = {}) {
|
|
37572
|
+
backtest.loggerService.info(COMMIT_SIGNAL_NOTIFY_METHOD_NAME, { symbol, payload });
|
|
37573
|
+
if (!ExecutionContextService.hasContext()) {
|
|
37574
|
+
throw new Error("commitSignalNotify requires an execution context");
|
|
37575
|
+
}
|
|
37576
|
+
if (!MethodContextService.hasContext()) {
|
|
37577
|
+
throw new Error("commitSignalNotify requires a method context");
|
|
37578
|
+
}
|
|
37579
|
+
const currentPrice = await getAveragePrice(symbol);
|
|
37580
|
+
const { backtest: isBacktest } = backtest.executionContextService.context;
|
|
37581
|
+
const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
|
|
37582
|
+
await backtest.notificationHelperService.commitSignalNotify(payload, symbol, currentPrice, { strategyName, exchangeName, frameName }, isBacktest);
|
|
37583
|
+
}
|
|
37403
37584
|
|
|
37404
37585
|
const STOP_STRATEGY_METHOD_NAME = "control.stopStrategy";
|
|
37405
37586
|
/**
|
|
@@ -37483,6 +37664,8 @@ const LISTEN_HIGHEST_PROFIT_METHOD_NAME = "event.listenHighestProfit";
|
|
|
37483
37664
|
const LISTEN_HIGHEST_PROFIT_ONCE_METHOD_NAME = "event.listenHighestProfitOnce";
|
|
37484
37665
|
const LISTEN_MAX_DRAWDOWN_METHOD_NAME = "event.listenMaxDrawdown";
|
|
37485
37666
|
const LISTEN_MAX_DRAWDOWN_ONCE_METHOD_NAME = "event.listenMaxDrawdownOnce";
|
|
37667
|
+
const LISTEN_SIGNAL_NOTIFY_METHOD_NAME = "event.listenSignalNotify";
|
|
37668
|
+
const LISTEN_SIGNAL_NOTIFY_ONCE_METHOD_NAME = "event.listenSignalNotifyOnce";
|
|
37486
37669
|
/**
|
|
37487
37670
|
* Subscribes to all signal events with queued async processing.
|
|
37488
37671
|
*
|
|
@@ -38874,6 +39057,46 @@ function listenMaxDrawdownOnce(filterFn, fn) {
|
|
|
38874
39057
|
};
|
|
38875
39058
|
return disposeFn = listenMaxDrawdown(wrappedFn);
|
|
38876
39059
|
}
|
|
39060
|
+
/**
|
|
39061
|
+
* Subscribes to signal info events with queued async processing.
|
|
39062
|
+
* Emits when a strategy calls commitSignalInfo() to broadcast a user-defined note for an open position.
|
|
39063
|
+
* Events are processed sequentially in order received, even if callback is async.
|
|
39064
|
+
* Uses queued wrapper to prevent concurrent execution of the callback.
|
|
39065
|
+
* @param fn - Callback function to handle signal info events
|
|
39066
|
+
* @return Unsubscribe function to stop listening to events
|
|
39067
|
+
*/
|
|
39068
|
+
function listenSignalNotify(fn) {
|
|
39069
|
+
backtest.loggerService.log(LISTEN_SIGNAL_NOTIFY_METHOD_NAME);
|
|
39070
|
+
const wrappedFn = async (event) => {
|
|
39071
|
+
if (await backtest.strategyCoreService.hasPendingSignal(event.backtest, event.symbol, {
|
|
39072
|
+
strategyName: event.strategyName,
|
|
39073
|
+
exchangeName: event.exchangeName,
|
|
39074
|
+
frameName: event.frameName,
|
|
39075
|
+
})) {
|
|
39076
|
+
await fn(event);
|
|
39077
|
+
}
|
|
39078
|
+
};
|
|
39079
|
+
return signalNotifySubject.subscribe(functoolsKit.queued(wrappedFn));
|
|
39080
|
+
}
|
|
39081
|
+
/**
|
|
39082
|
+
* Subscribes to filtered signal info events with one-time execution.
|
|
39083
|
+
* Listens for events matching the filter predicate, then executes callback once
|
|
39084
|
+
* and automatically unsubscribes.
|
|
39085
|
+
* @param filterFn - Predicate to filter which events trigger the callback
|
|
39086
|
+
* @param fn - Callback function to handle the filtered event (called only once)
|
|
39087
|
+
* @return Unsubscribe function to cancel the listener before it fires
|
|
39088
|
+
*/
|
|
39089
|
+
function listenSignalNotifyOnce(filterFn, fn) {
|
|
39090
|
+
backtest.loggerService.log(LISTEN_SIGNAL_NOTIFY_ONCE_METHOD_NAME);
|
|
39091
|
+
let disposeFn;
|
|
39092
|
+
const wrappedFn = async (event) => {
|
|
39093
|
+
if (filterFn(event)) {
|
|
39094
|
+
await fn(event);
|
|
39095
|
+
disposeFn && disposeFn();
|
|
39096
|
+
}
|
|
39097
|
+
};
|
|
39098
|
+
return disposeFn = listenSignalNotify(wrappedFn);
|
|
39099
|
+
}
|
|
38877
39100
|
|
|
38878
39101
|
const BACKTEST_METHOD_NAME_RUN = "BacktestUtils.run";
|
|
38879
39102
|
const BACKTEST_METHOD_NAME_BACKGROUND = "BacktestUtils.background";
|
|
@@ -38930,6 +39153,7 @@ const BACKTEST_METHOD_NAME_TRAILING_STOP_COST = "BacktestUtils.commitTrailingSto
|
|
|
38930
39153
|
const BACKTEST_METHOD_NAME_TRAILING_PROFIT_COST = "BacktestUtils.commitTrailingTakeCost";
|
|
38931
39154
|
const BACKTEST_METHOD_NAME_ACTIVATE_SCHEDULED = "Backtest.commitActivateScheduled";
|
|
38932
39155
|
const BACKTEST_METHOD_NAME_AVERAGE_BUY = "Backtest.commitAverageBuy";
|
|
39156
|
+
const BACKTEST_METHOD_NAME_SIGNAL_NOTIFY = "Backtest.commitSignalNotify";
|
|
38933
39157
|
const BACKTEST_METHOD_NAME_GET_DATA = "BacktestUtils.getData";
|
|
38934
39158
|
const BACKTEST_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "BacktestUtils.hasNoPendingSignal";
|
|
38935
39159
|
const BACKTEST_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "BacktestUtils.hasNoScheduledSignal";
|
|
@@ -41285,6 +41509,33 @@ class BacktestUtils {
|
|
|
41285
41509
|
});
|
|
41286
41510
|
return await backtest.strategyCoreService.averageBuy(true, symbol, currentPrice, context, cost);
|
|
41287
41511
|
};
|
|
41512
|
+
/**
|
|
41513
|
+
* Emits a `signal.info` notification for the currently active pending signal.
|
|
41514
|
+
*
|
|
41515
|
+
* @param symbol - Trading pair symbol
|
|
41516
|
+
* @param currentPrice - Market price at the time of the call
|
|
41517
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
41518
|
+
* @param payload - Optional notification fields (notificationNote, notificationId)
|
|
41519
|
+
*
|
|
41520
|
+
* @throws {Error} If no active pending signal exists for the given symbol
|
|
41521
|
+
*
|
|
41522
|
+
* @example
|
|
41523
|
+
* ```typescript
|
|
41524
|
+
* await Backtest.commitSignalNotify("BTCUSDT", 42000, {
|
|
41525
|
+
* strategyName: "my-strategy",
|
|
41526
|
+
* exchangeName: "binance",
|
|
41527
|
+
* frameName: "1h"
|
|
41528
|
+
* }, { notificationNote: "RSI crossed 70" });
|
|
41529
|
+
* ```
|
|
41530
|
+
*/
|
|
41531
|
+
this.commitSignalNotify = async (symbol, currentPrice, context, payload = {}) => {
|
|
41532
|
+
backtest.loggerService.info(BACKTEST_METHOD_NAME_SIGNAL_NOTIFY, {
|
|
41533
|
+
symbol,
|
|
41534
|
+
currentPrice,
|
|
41535
|
+
context,
|
|
41536
|
+
});
|
|
41537
|
+
await backtest.notificationHelperService.commitSignalNotify(payload, symbol, currentPrice, context, true);
|
|
41538
|
+
};
|
|
41288
41539
|
/**
|
|
41289
41540
|
* Gets statistical data from all closed signals for a symbol-strategy pair.
|
|
41290
41541
|
*
|
|
@@ -41498,6 +41749,7 @@ const LIVE_METHOD_NAME_TRAILING_STOP_COST = "LiveUtils.commitTrailingStopCost";
|
|
|
41498
41749
|
const LIVE_METHOD_NAME_TRAILING_PROFIT_COST = "LiveUtils.commitTrailingTakeCost";
|
|
41499
41750
|
const LIVE_METHOD_NAME_ACTIVATE_SCHEDULED = "Live.commitActivateScheduled";
|
|
41500
41751
|
const LIVE_METHOD_NAME_AVERAGE_BUY = "Live.commitAverageBuy";
|
|
41752
|
+
const LIVE_METHOD_NAME_SIGNAL_NOTIFY = "Live.commitSignalNotify";
|
|
41501
41753
|
const LIVE_METHOD_NAME_HAS_NO_PENDING_SIGNAL = "LiveUtils.hasNoPendingSignal";
|
|
41502
41754
|
const LIVE_METHOD_NAME_HAS_NO_SCHEDULED_SIGNAL = "LiveUtils.hasNoScheduledSignal";
|
|
41503
41755
|
/**
|
|
@@ -44194,6 +44446,36 @@ class LiveUtils {
|
|
|
44194
44446
|
frameName: "",
|
|
44195
44447
|
}, cost);
|
|
44196
44448
|
};
|
|
44449
|
+
/**
|
|
44450
|
+
* Emits a `signal.info` notification for the currently active pending signal.
|
|
44451
|
+
*
|
|
44452
|
+
* @param symbol - Trading pair symbol
|
|
44453
|
+
* @param currentPrice - Market price at the time of the call
|
|
44454
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
44455
|
+
* @param payload - Optional notification fields (notificationNote, notificationId)
|
|
44456
|
+
*
|
|
44457
|
+
* @throws {Error} If no active pending signal exists for the given symbol
|
|
44458
|
+
*
|
|
44459
|
+
* @example
|
|
44460
|
+
* ```typescript
|
|
44461
|
+
* await Live.commitSignalNotify("BTCUSDT", 42000, {
|
|
44462
|
+
* strategyName: "my-strategy",
|
|
44463
|
+
* exchangeName: "binance",
|
|
44464
|
+
* }, { notificationNote: "RSI crossed 70" });
|
|
44465
|
+
* ```
|
|
44466
|
+
*/
|
|
44467
|
+
this.commitSignalNotify = async (symbol, currentPrice, context, payload = {}) => {
|
|
44468
|
+
backtest.loggerService.info(LIVE_METHOD_NAME_SIGNAL_NOTIFY, {
|
|
44469
|
+
symbol,
|
|
44470
|
+
currentPrice,
|
|
44471
|
+
context,
|
|
44472
|
+
});
|
|
44473
|
+
await backtest.notificationHelperService.commitSignalNotify(payload, symbol, currentPrice, {
|
|
44474
|
+
strategyName: context.strategyName,
|
|
44475
|
+
exchangeName: context.exchangeName,
|
|
44476
|
+
frameName: "",
|
|
44477
|
+
}, false);
|
|
44478
|
+
};
|
|
44197
44479
|
/**
|
|
44198
44480
|
* Gets statistical data from all live trading events for a symbol-strategy pair.
|
|
44199
44481
|
*
|
|
@@ -48388,6 +48670,87 @@ class MarkdownUtils {
|
|
|
48388
48670
|
backtest.maxDrawdownMarkdownService.unsubscribe();
|
|
48389
48671
|
}
|
|
48390
48672
|
};
|
|
48673
|
+
/**
|
|
48674
|
+
* Clears markdown report data selectively.
|
|
48675
|
+
*
|
|
48676
|
+
* Clears accumulated data for specified markdown services without unsubscribing.
|
|
48677
|
+
* Use this method to reset report data for specific services while keeping them active.
|
|
48678
|
+
*
|
|
48679
|
+
* Each cleared service will:
|
|
48680
|
+
* - Clear accumulated data for all reports
|
|
48681
|
+
* - Start fresh with new data for future events
|
|
48682
|
+
* - Not affect event subscriptions or report generation status
|
|
48683
|
+
*
|
|
48684
|
+
* @param config - Service configuration object specifying which services to clear. Defaults to clearing all services.
|
|
48685
|
+
* @param config.backtest - Clear backtest result report data
|
|
48686
|
+
* @param config.breakeven - Clear breakeven event tracking data
|
|
48687
|
+
* @param config.partial - Clear partial profit/loss event tracking data
|
|
48688
|
+
* @param config.heat - Clear portfolio heatmap analysis data
|
|
48689
|
+
* @param config.walker - Clear walker strategy comparison report data
|
|
48690
|
+
* @param config.performance - Clear performance bottleneck analysis data
|
|
48691
|
+
* @param config.risk - Clear risk rejection tracking data
|
|
48692
|
+
* @param config.schedule - Clear scheduled signal tracking data
|
|
48693
|
+
* @param config.live - Clear live trading event report data
|
|
48694
|
+
* @param config.strategy - Clear strategy report data
|
|
48695
|
+
* @param config.sync - Clear sync report data
|
|
48696
|
+
* @param config.highest_profit - Clear highest profit report data
|
|
48697
|
+
* @param config.max_drawdown - Clear max drawdown report data
|
|
48698
|
+
*/
|
|
48699
|
+
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) => {
|
|
48700
|
+
LOGGER_SERVICE$1.debug(MARKDOWN_METHOD_NAME_CLEAR, {
|
|
48701
|
+
backtest: bt,
|
|
48702
|
+
breakeven,
|
|
48703
|
+
heat,
|
|
48704
|
+
live,
|
|
48705
|
+
partial,
|
|
48706
|
+
performance,
|
|
48707
|
+
risk,
|
|
48708
|
+
strategy,
|
|
48709
|
+
schedule,
|
|
48710
|
+
walker,
|
|
48711
|
+
sync,
|
|
48712
|
+
highest_profit,
|
|
48713
|
+
});
|
|
48714
|
+
if (bt) {
|
|
48715
|
+
backtest.backtestMarkdownService.clear();
|
|
48716
|
+
}
|
|
48717
|
+
if (breakeven) {
|
|
48718
|
+
backtest.breakevenMarkdownService.clear();
|
|
48719
|
+
}
|
|
48720
|
+
if (heat) {
|
|
48721
|
+
backtest.heatMarkdownService.clear();
|
|
48722
|
+
}
|
|
48723
|
+
if (live) {
|
|
48724
|
+
backtest.liveMarkdownService.clear();
|
|
48725
|
+
}
|
|
48726
|
+
if (partial) {
|
|
48727
|
+
backtest.partialMarkdownService.clear();
|
|
48728
|
+
}
|
|
48729
|
+
if (performance) {
|
|
48730
|
+
backtest.performanceMarkdownService.clear();
|
|
48731
|
+
}
|
|
48732
|
+
if (risk) {
|
|
48733
|
+
backtest.riskMarkdownService.clear();
|
|
48734
|
+
}
|
|
48735
|
+
if (strategy) {
|
|
48736
|
+
backtest.strategyMarkdownService.clear();
|
|
48737
|
+
}
|
|
48738
|
+
if (schedule) {
|
|
48739
|
+
backtest.scheduleMarkdownService.clear();
|
|
48740
|
+
}
|
|
48741
|
+
if (walker) {
|
|
48742
|
+
backtest.walkerMarkdownService.clear();
|
|
48743
|
+
}
|
|
48744
|
+
if (sync) {
|
|
48745
|
+
backtest.syncMarkdownService.clear();
|
|
48746
|
+
}
|
|
48747
|
+
if (highest_profit) {
|
|
48748
|
+
backtest.highestProfitMarkdownService.clear();
|
|
48749
|
+
}
|
|
48750
|
+
if (max_drawdown) {
|
|
48751
|
+
backtest.maxDrawdownMarkdownService.clear();
|
|
48752
|
+
}
|
|
48753
|
+
};
|
|
48391
48754
|
}
|
|
48392
48755
|
}
|
|
48393
48756
|
/**
|
|
@@ -48430,15 +48793,6 @@ class MarkdownAdapter extends MarkdownUtils {
|
|
|
48430
48793
|
LOGGER_SERVICE$1.debug(MARKDOWN_METHOD_NAME_USE_JSONL);
|
|
48431
48794
|
MarkdownWriter.useJsonl();
|
|
48432
48795
|
}
|
|
48433
|
-
/**
|
|
48434
|
-
* Clears the memoized storage cache.
|
|
48435
|
-
* Call this when process.cwd() changes between strategy iterations
|
|
48436
|
-
* so new storage instances are created with the updated base path.
|
|
48437
|
-
*/
|
|
48438
|
-
clear() {
|
|
48439
|
-
LOGGER_SERVICE$1.log(MARKDOWN_METHOD_NAME_CLEAR);
|
|
48440
|
-
MarkdownWriter.clear();
|
|
48441
|
-
}
|
|
48442
48796
|
/**
|
|
48443
48797
|
* Switches to a dummy markdown adapter that discards all writes.
|
|
48444
48798
|
* All future markdown writes will be no-ops.
|
|
@@ -49135,6 +49489,7 @@ const SUBJECT_ISOLATION_LIST = [
|
|
|
49135
49489
|
strategyCommitSubject,
|
|
49136
49490
|
syncSubject,
|
|
49137
49491
|
validationSubject,
|
|
49492
|
+
signalNotifySubject,
|
|
49138
49493
|
];
|
|
49139
49494
|
/**
|
|
49140
49495
|
* Creates a snapshot function for a given subject by clearing its internal
|
|
@@ -53980,7 +54335,44 @@ const CREATE_VALIDATION_ERROR_NOTIFICATION_FN = (error) => ({
|
|
|
53980
54335
|
message: functoolsKit.getErrorMessage(error),
|
|
53981
54336
|
backtest: false,
|
|
53982
54337
|
});
|
|
54338
|
+
/**
|
|
54339
|
+
* Creates a notification model for signal info events.
|
|
54340
|
+
* @param data - The signal info contract data
|
|
54341
|
+
* @returns NotificationModel for signal info event
|
|
54342
|
+
*/
|
|
54343
|
+
const CREATE_SIGNAL_INFO_NOTIFICATION_FN = (data) => ({
|
|
54344
|
+
type: "signal.info",
|
|
54345
|
+
id: CREATE_KEY_FN$2(),
|
|
54346
|
+
timestamp: data.timestamp,
|
|
54347
|
+
backtest: data.backtest,
|
|
54348
|
+
symbol: data.symbol,
|
|
54349
|
+
strategyName: data.strategyName,
|
|
54350
|
+
exchangeName: data.exchangeName,
|
|
54351
|
+
signalId: data.data.id,
|
|
54352
|
+
currentPrice: data.currentPrice,
|
|
54353
|
+
position: data.data.position,
|
|
54354
|
+
priceOpen: data.data.priceOpen,
|
|
54355
|
+
priceTakeProfit: data.data.priceTakeProfit,
|
|
54356
|
+
priceStopLoss: data.data.priceStopLoss,
|
|
54357
|
+
originalPriceTakeProfit: data.data.originalPriceTakeProfit,
|
|
54358
|
+
originalPriceStopLoss: data.data.originalPriceStopLoss,
|
|
54359
|
+
originalPriceOpen: data.data.originalPriceOpen,
|
|
54360
|
+
totalEntries: data.data.totalEntries,
|
|
54361
|
+
totalPartials: data.data.totalPartials,
|
|
54362
|
+
pnl: data.data.pnl,
|
|
54363
|
+
pnlPercentage: data.data.pnl.pnlPercentage,
|
|
54364
|
+
pnlPriceOpen: data.data.pnl.priceOpen,
|
|
54365
|
+
pnlPriceClose: data.data.pnl.priceClose,
|
|
54366
|
+
pnlCost: data.data.pnl.pnlCost,
|
|
54367
|
+
pnlEntries: data.data.pnl.pnlEntries,
|
|
54368
|
+
note: data.note,
|
|
54369
|
+
notificationId: data.notificationId,
|
|
54370
|
+
scheduledAt: data.data.scheduledAt,
|
|
54371
|
+
pendingAt: data.data.pendingAt,
|
|
54372
|
+
createdAt: data.timestamp,
|
|
54373
|
+
});
|
|
53983
54374
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL = "NotificationMemoryBacktestUtils.handleSignal";
|
|
54375
|
+
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationMemoryBacktestUtils.handleSignalNotify";
|
|
53984
54376
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationMemoryBacktestUtils.handlePartialProfit";
|
|
53985
54377
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationMemoryBacktestUtils.handlePartialLoss";
|
|
53986
54378
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationMemoryBacktestUtils.handleBreakeven";
|
|
@@ -53993,6 +54385,7 @@ const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_VALIDATION_ERROR = "Notifi
|
|
|
53993
54385
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_GET_DATA = "NotificationMemoryBacktestUtils.getData";
|
|
53994
54386
|
const NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_DISPOSE = "NotificationMemoryBacktestUtils.dispose";
|
|
53995
54387
|
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL = "NotificationMemoryLiveUtils.handleSignal";
|
|
54388
|
+
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationMemoryLiveUtils.handleSignalNotify";
|
|
53996
54389
|
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationMemoryLiveUtils.handlePartialProfit";
|
|
53997
54390
|
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationMemoryLiveUtils.handlePartialLoss";
|
|
53998
54391
|
const NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationMemoryLiveUtils.handleBreakeven";
|
|
@@ -54021,6 +54414,7 @@ const NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_CLEAR = "NotificationLiveAdapter.cle
|
|
|
54021
54414
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "NotificationPersistBacktestUtils.waitForInit";
|
|
54022
54415
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_UPDATE_NOTIFICATIONS = "NotificationPersistBacktestUtils._updateNotifications";
|
|
54023
54416
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL = "NotificationPersistBacktestUtils.handleSignal";
|
|
54417
|
+
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationPersistBacktestUtils.handleSignalNotify";
|
|
54024
54418
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationPersistBacktestUtils.handlePartialProfit";
|
|
54025
54419
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationPersistBacktestUtils.handlePartialLoss";
|
|
54026
54420
|
const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationPersistBacktestUtils.handleBreakeven";
|
|
@@ -54035,6 +54429,7 @@ const NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_DISPOSE = "NotificationPersistBa
|
|
|
54035
54429
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_WAIT_FOR_INIT = "NotificationPersistLiveUtils.waitForInit";
|
|
54036
54430
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_UPDATE_NOTIFICATIONS = "NotificationPersistLiveUtils._updateNotifications";
|
|
54037
54431
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL = "NotificationPersistLiveUtils.handleSignal";
|
|
54432
|
+
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY = "NotificationPersistLiveUtils.handleSignalNotify";
|
|
54038
54433
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_PARTIAL_PROFIT = "NotificationPersistLiveUtils.handlePartialProfit";
|
|
54039
54434
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_PARTIAL_LOSS = "NotificationPersistLiveUtils.handlePartialLoss";
|
|
54040
54435
|
const NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_BREAKEVEN = "NotificationPersistLiveUtils.handleBreakeven";
|
|
@@ -54077,6 +54472,12 @@ class NotificationMemoryBacktestUtils {
|
|
|
54077
54472
|
this._addNotification(notification);
|
|
54078
54473
|
}
|
|
54079
54474
|
};
|
|
54475
|
+
this.handleSignalNotify = async (data) => {
|
|
54476
|
+
backtest.loggerService.info(NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
|
|
54477
|
+
signalId: data.data.id,
|
|
54478
|
+
});
|
|
54479
|
+
this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
|
|
54480
|
+
};
|
|
54080
54481
|
/**
|
|
54081
54482
|
* Handles partial profit availability event.
|
|
54082
54483
|
* @param data - The partial profit contract data
|
|
@@ -54221,6 +54622,8 @@ class NotificationDummyBacktestUtils {
|
|
|
54221
54622
|
*/
|
|
54222
54623
|
this.handleSignal = async () => {
|
|
54223
54624
|
};
|
|
54625
|
+
this.handleSignalNotify = async () => {
|
|
54626
|
+
};
|
|
54224
54627
|
/**
|
|
54225
54628
|
* No-op handler for partial profit event.
|
|
54226
54629
|
*/
|
|
@@ -54328,6 +54731,14 @@ class NotificationPersistBacktestUtils {
|
|
|
54328
54731
|
await this._updateNotifications();
|
|
54329
54732
|
}
|
|
54330
54733
|
};
|
|
54734
|
+
this.handleSignalNotify = async (data) => {
|
|
54735
|
+
backtest.loggerService.info(NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
|
|
54736
|
+
signalId: data.data.id,
|
|
54737
|
+
});
|
|
54738
|
+
await this.waitForInit();
|
|
54739
|
+
this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
|
|
54740
|
+
await this._updateNotifications();
|
|
54741
|
+
};
|
|
54331
54742
|
/**
|
|
54332
54743
|
* Handles partial profit availability event.
|
|
54333
54744
|
* @param data - The partial profit contract data
|
|
@@ -54529,6 +54940,12 @@ class NotificationMemoryLiveUtils {
|
|
|
54529
54940
|
this._addNotification(notification);
|
|
54530
54941
|
}
|
|
54531
54942
|
};
|
|
54943
|
+
this.handleSignalNotify = async (data) => {
|
|
54944
|
+
backtest.loggerService.info(NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
|
|
54945
|
+
signalId: data.data.id,
|
|
54946
|
+
});
|
|
54947
|
+
this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
|
|
54948
|
+
};
|
|
54532
54949
|
/**
|
|
54533
54950
|
* Handles partial profit availability event.
|
|
54534
54951
|
* @param data - The partial profit contract data
|
|
@@ -54673,6 +55090,8 @@ class NotificationDummyLiveUtils {
|
|
|
54673
55090
|
*/
|
|
54674
55091
|
this.handleSignal = async () => {
|
|
54675
55092
|
};
|
|
55093
|
+
this.handleSignalNotify = async () => {
|
|
55094
|
+
};
|
|
54676
55095
|
/**
|
|
54677
55096
|
* No-op handler for partial profit event.
|
|
54678
55097
|
*/
|
|
@@ -54781,6 +55200,14 @@ class NotificationPersistLiveUtils {
|
|
|
54781
55200
|
await this._updateNotifications();
|
|
54782
55201
|
}
|
|
54783
55202
|
};
|
|
55203
|
+
this.handleSignalNotify = async (data) => {
|
|
55204
|
+
backtest.loggerService.info(NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL_NOTIFY, {
|
|
55205
|
+
signalId: data.data.id,
|
|
55206
|
+
});
|
|
55207
|
+
await this.waitForInit();
|
|
55208
|
+
this._addNotification(CREATE_SIGNAL_INFO_NOTIFICATION_FN(data));
|
|
55209
|
+
await this._updateNotifications();
|
|
55210
|
+
};
|
|
54784
55211
|
/**
|
|
54785
55212
|
* Handles partial profit availability event.
|
|
54786
55213
|
* @param data - The partial profit contract data
|
|
@@ -54974,6 +55401,9 @@ class NotificationBacktestAdapter {
|
|
|
54974
55401
|
this.handleSignal = async (data) => {
|
|
54975
55402
|
return await this._notificationBacktestUtils.handleSignal(data);
|
|
54976
55403
|
};
|
|
55404
|
+
this.handleSignalNotify = async (data) => {
|
|
55405
|
+
return await this._notificationBacktestUtils.handleSignalNotify(data);
|
|
55406
|
+
};
|
|
54977
55407
|
/**
|
|
54978
55408
|
* Handles partial profit availability event.
|
|
54979
55409
|
* Proxies call to the underlying notification adapter.
|
|
@@ -55129,6 +55559,9 @@ class NotificationLiveAdapter {
|
|
|
55129
55559
|
this.handleSignal = async (data) => {
|
|
55130
55560
|
return await this._notificationLiveUtils.handleSignal(data);
|
|
55131
55561
|
};
|
|
55562
|
+
this.handleSignalNotify = async (data) => {
|
|
55563
|
+
return await this._notificationLiveUtils.handleSignalNotify(data);
|
|
55564
|
+
};
|
|
55132
55565
|
/**
|
|
55133
55566
|
* Handles partial profit availability event.
|
|
55134
55567
|
* Proxies call to the underlying notification adapter.
|
|
@@ -55307,7 +55740,10 @@ class NotificationAdapter {
|
|
|
55307
55740
|
const unBacktestError = errorEmitter.subscribe((error) => NotificationBacktest.handleError(error));
|
|
55308
55741
|
const unBacktestExit = exitEmitter.subscribe((error) => NotificationBacktest.handleCriticalError(error));
|
|
55309
55742
|
const unBacktestValidation = validationSubject.subscribe((error) => NotificationBacktest.handleValidationError(error));
|
|
55310
|
-
|
|
55743
|
+
const unBacktestSignalNotify = signalNotifySubject
|
|
55744
|
+
.filter(({ backtest }) => backtest)
|
|
55745
|
+
.connect((data) => NotificationBacktest.handleSignalNotify(data));
|
|
55746
|
+
unBacktest = functoolsKit.compose(() => unBacktestSignal(), () => unBacktestPartialProfit(), () => unBacktestPartialLoss(), () => unBacktestBreakeven(), () => unBacktestStrategyCommit(), () => unBacktestSync(), () => unBacktestRisk(), () => unBacktestError(), () => unBacktestExit(), () => unBacktestValidation(), () => unBacktestSignalNotify());
|
|
55311
55747
|
}
|
|
55312
55748
|
{
|
|
55313
55749
|
const unLiveSignal = signalLiveEmitter.subscribe((data) => NotificationLive.handleSignal(data));
|
|
@@ -55332,7 +55768,10 @@ class NotificationAdapter {
|
|
|
55332
55768
|
const unLiveError = errorEmitter.subscribe((error) => NotificationLive.handleError(error));
|
|
55333
55769
|
const unLiveExit = exitEmitter.subscribe((error) => NotificationLive.handleCriticalError(error));
|
|
55334
55770
|
const unLiveValidation = validationSubject.subscribe((error) => NotificationLive.handleValidationError(error));
|
|
55335
|
-
|
|
55771
|
+
const unLiveSignalNotify = signalNotifySubject
|
|
55772
|
+
.filter(({ backtest }) => !backtest)
|
|
55773
|
+
.connect((data) => NotificationLive.handleSignalNotify(data));
|
|
55774
|
+
unLive = functoolsKit.compose(() => unLiveSignal(), () => unLivePartialProfit(), () => unLivePartialLoss(), () => unLiveBreakeven(), () => unLiveStrategyCommit(), () => unLiveSync(), () => unLiveRisk(), () => unLiveError(), () => unLiveExit(), () => unLiveValidation(), () => unLiveSignalNotify());
|
|
55336
55775
|
}
|
|
55337
55776
|
return () => {
|
|
55338
55777
|
unLive();
|
|
@@ -55570,11 +56009,17 @@ class CacheFnInstance {
|
|
|
55570
56009
|
return cached;
|
|
55571
56010
|
}
|
|
55572
56011
|
}
|
|
56012
|
+
const value = this.fn(...args);
|
|
55573
56013
|
const newCache = {
|
|
55574
56014
|
when: currentWhen,
|
|
55575
|
-
value
|
|
56015
|
+
value,
|
|
55576
56016
|
};
|
|
55577
56017
|
this._cacheMap.set(key, newCache);
|
|
56018
|
+
if (value && value instanceof Promise) {
|
|
56019
|
+
value.catch(() => {
|
|
56020
|
+
this._cacheMap.delete(key);
|
|
56021
|
+
});
|
|
56022
|
+
}
|
|
55578
56023
|
return newCache;
|
|
55579
56024
|
};
|
|
55580
56025
|
/**
|
|
@@ -56155,7 +56600,7 @@ class IntervalFnInstance {
|
|
|
56155
56600
|
* within the same interval or when `fn` itself returned `null`
|
|
56156
56601
|
* @throws Error if method context, execution context, or interval is missing
|
|
56157
56602
|
*/
|
|
56158
|
-
this.run =
|
|
56603
|
+
this.run = (...args) => {
|
|
56159
56604
|
backtest.loggerService.debug(INTERVAL_METHOD_NAME_RUN, { args });
|
|
56160
56605
|
const step = INTERVAL_MINUTES[this.interval];
|
|
56161
56606
|
{
|
|
@@ -56177,10 +56622,15 @@ class IntervalFnInstance {
|
|
|
56177
56622
|
if (this._stateMap.get(stateKey) === currentAligned) {
|
|
56178
56623
|
return null;
|
|
56179
56624
|
}
|
|
56180
|
-
const result =
|
|
56625
|
+
const result = this.fn.apply(null, args);
|
|
56181
56626
|
if (result !== null) {
|
|
56182
56627
|
this._stateMap.set(stateKey, currentAligned);
|
|
56183
56628
|
}
|
|
56629
|
+
if (result && result instanceof Promise) {
|
|
56630
|
+
result.catch(() => {
|
|
56631
|
+
this._stateMap.delete(stateKey);
|
|
56632
|
+
});
|
|
56633
|
+
}
|
|
56184
56634
|
return result;
|
|
56185
56635
|
};
|
|
56186
56636
|
/**
|
|
@@ -57788,6 +58238,7 @@ exports.commitPartialLoss = commitPartialLoss;
|
|
|
57788
58238
|
exports.commitPartialLossCost = commitPartialLossCost;
|
|
57789
58239
|
exports.commitPartialProfit = commitPartialProfit;
|
|
57790
58240
|
exports.commitPartialProfitCost = commitPartialProfitCost;
|
|
58241
|
+
exports.commitSignalNotify = commitSignalNotify;
|
|
57791
58242
|
exports.commitTrailingStop = commitTrailingStop;
|
|
57792
58243
|
exports.commitTrailingStopCost = commitTrailingStopCost;
|
|
57793
58244
|
exports.commitTrailingTake = commitTrailingTake;
|
|
@@ -57906,6 +58357,8 @@ exports.listenSignalBacktest = listenSignalBacktest;
|
|
|
57906
58357
|
exports.listenSignalBacktestOnce = listenSignalBacktestOnce;
|
|
57907
58358
|
exports.listenSignalLive = listenSignalLive;
|
|
57908
58359
|
exports.listenSignalLiveOnce = listenSignalLiveOnce;
|
|
58360
|
+
exports.listenSignalNotify = listenSignalNotify;
|
|
58361
|
+
exports.listenSignalNotifyOnce = listenSignalNotifyOnce;
|
|
57909
58362
|
exports.listenSignalOnce = listenSignalOnce;
|
|
57910
58363
|
exports.listenStrategyCommit = listenStrategyCommit;
|
|
57911
58364
|
exports.listenStrategyCommitOnce = listenStrategyCommitOnce;
|