backtest-kit 1.5.27 → 1.5.29
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 +664 -540
- package/build/index.mjs +664 -540
- package/package.json +1 -1
- package/types.d.ts +159 -110
package/build/index.cjs
CHANGED
|
@@ -2043,7 +2043,7 @@ const BASE_WAIT_FOR_INIT_FN_METHOD_NAME = "PersistBase.waitForInitFn";
|
|
|
2043
2043
|
const BASE_UNLINK_RETRY_COUNT = 5;
|
|
2044
2044
|
const BASE_UNLINK_RETRY_DELAY = 1000;
|
|
2045
2045
|
const BASE_WAIT_FOR_INIT_FN = async (self) => {
|
|
2046
|
-
|
|
2046
|
+
bt.loggerService.debug(BASE_WAIT_FOR_INIT_FN_METHOD_NAME, {
|
|
2047
2047
|
entityName: self.entityName,
|
|
2048
2048
|
directory: self._directory,
|
|
2049
2049
|
});
|
|
@@ -2101,7 +2101,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2101
2101
|
this.entityName = entityName;
|
|
2102
2102
|
this.baseDir = baseDir;
|
|
2103
2103
|
this[_a] = functoolsKit.singleshot(async () => await BASE_WAIT_FOR_INIT_FN(this));
|
|
2104
|
-
|
|
2104
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_CTOR, {
|
|
2105
2105
|
entityName: this.entityName,
|
|
2106
2106
|
baseDir,
|
|
2107
2107
|
});
|
|
@@ -2117,7 +2117,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2117
2117
|
return path.join(this.baseDir, this.entityName, `${entityId}.json`);
|
|
2118
2118
|
}
|
|
2119
2119
|
async waitForInit(initial) {
|
|
2120
|
-
|
|
2120
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_WAIT_FOR_INIT, {
|
|
2121
2121
|
entityName: this.entityName,
|
|
2122
2122
|
initial,
|
|
2123
2123
|
});
|
|
@@ -2134,7 +2134,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2134
2134
|
return length;
|
|
2135
2135
|
}
|
|
2136
2136
|
async readValue(entityId) {
|
|
2137
|
-
|
|
2137
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_READ_VALUE, {
|
|
2138
2138
|
entityName: this.entityName,
|
|
2139
2139
|
entityId,
|
|
2140
2140
|
});
|
|
@@ -2151,7 +2151,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2151
2151
|
}
|
|
2152
2152
|
}
|
|
2153
2153
|
async hasValue(entityId) {
|
|
2154
|
-
|
|
2154
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_HAS_VALUE, {
|
|
2155
2155
|
entityName: this.entityName,
|
|
2156
2156
|
entityId,
|
|
2157
2157
|
});
|
|
@@ -2168,7 +2168,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2168
2168
|
}
|
|
2169
2169
|
}
|
|
2170
2170
|
async writeValue(entityId, entity) {
|
|
2171
|
-
|
|
2171
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_WRITE_VALUE, {
|
|
2172
2172
|
entityName: this.entityName,
|
|
2173
2173
|
entityId,
|
|
2174
2174
|
});
|
|
@@ -2189,7 +2189,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2189
2189
|
* @throws Error if entity not found or deletion fails
|
|
2190
2190
|
*/
|
|
2191
2191
|
async removeValue(entityId) {
|
|
2192
|
-
|
|
2192
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_REMOVE_VALUE, {
|
|
2193
2193
|
entityName: this.entityName,
|
|
2194
2194
|
entityId,
|
|
2195
2195
|
});
|
|
@@ -2211,7 +2211,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2211
2211
|
* @throws Error if deletion fails
|
|
2212
2212
|
*/
|
|
2213
2213
|
async removeAll() {
|
|
2214
|
-
|
|
2214
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_REMOVE_ALL, {
|
|
2215
2215
|
entityName: this.entityName,
|
|
2216
2216
|
});
|
|
2217
2217
|
try {
|
|
@@ -2233,7 +2233,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2233
2233
|
* @throws Error if reading fails
|
|
2234
2234
|
*/
|
|
2235
2235
|
async *values() {
|
|
2236
|
-
|
|
2236
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_VALUES, {
|
|
2237
2237
|
entityName: this.entityName,
|
|
2238
2238
|
});
|
|
2239
2239
|
try {
|
|
@@ -2262,7 +2262,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2262
2262
|
* @throws Error if reading fails
|
|
2263
2263
|
*/
|
|
2264
2264
|
async *keys() {
|
|
2265
|
-
|
|
2265
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_KEYS, {
|
|
2266
2266
|
entityName: this.entityName,
|
|
2267
2267
|
});
|
|
2268
2268
|
try {
|
|
@@ -2367,7 +2367,7 @@ class PersistSignalUtils {
|
|
|
2367
2367
|
* @returns Promise resolving to signal or null
|
|
2368
2368
|
*/
|
|
2369
2369
|
this.readSignalData = async (symbol, strategyName) => {
|
|
2370
|
-
|
|
2370
|
+
bt.loggerService.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_READ_DATA);
|
|
2371
2371
|
const key = `${symbol}:${strategyName}`;
|
|
2372
2372
|
const isInitial = !this.getSignalStorage.has(key);
|
|
2373
2373
|
const stateStorage = this.getSignalStorage(symbol, strategyName);
|
|
@@ -2389,7 +2389,7 @@ class PersistSignalUtils {
|
|
|
2389
2389
|
* @returns Promise that resolves when write is complete
|
|
2390
2390
|
*/
|
|
2391
2391
|
this.writeSignalData = async (signalRow, symbol, strategyName) => {
|
|
2392
|
-
|
|
2392
|
+
bt.loggerService.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2393
2393
|
const key = `${symbol}:${strategyName}`;
|
|
2394
2394
|
const isInitial = !this.getSignalStorage.has(key);
|
|
2395
2395
|
const stateStorage = this.getSignalStorage(symbol, strategyName);
|
|
@@ -2412,7 +2412,7 @@ class PersistSignalUtils {
|
|
|
2412
2412
|
* ```
|
|
2413
2413
|
*/
|
|
2414
2414
|
usePersistSignalAdapter(Ctor) {
|
|
2415
|
-
|
|
2415
|
+
bt.loggerService.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_PERSIST_SIGNAL_ADAPTER);
|
|
2416
2416
|
this.PersistSignalFactory = Ctor;
|
|
2417
2417
|
}
|
|
2418
2418
|
}
|
|
@@ -2464,7 +2464,7 @@ class PersistRiskUtils {
|
|
|
2464
2464
|
* @returns Promise resolving to Map of active positions
|
|
2465
2465
|
*/
|
|
2466
2466
|
this.readPositionData = async (riskName) => {
|
|
2467
|
-
|
|
2467
|
+
bt.loggerService.info(PERSIST_RISK_UTILS_METHOD_NAME_READ_DATA);
|
|
2468
2468
|
const isInitial = !this.getRiskStorage.has(riskName);
|
|
2469
2469
|
const stateStorage = this.getRiskStorage(riskName);
|
|
2470
2470
|
await stateStorage.waitForInit(isInitial);
|
|
@@ -2485,7 +2485,7 @@ class PersistRiskUtils {
|
|
|
2485
2485
|
* @returns Promise that resolves when write is complete
|
|
2486
2486
|
*/
|
|
2487
2487
|
this.writePositionData = async (riskRow, riskName) => {
|
|
2488
|
-
|
|
2488
|
+
bt.loggerService.info(PERSIST_RISK_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2489
2489
|
const isInitial = !this.getRiskStorage.has(riskName);
|
|
2490
2490
|
const stateStorage = this.getRiskStorage(riskName);
|
|
2491
2491
|
await stateStorage.waitForInit(isInitial);
|
|
@@ -2508,7 +2508,7 @@ class PersistRiskUtils {
|
|
|
2508
2508
|
* ```
|
|
2509
2509
|
*/
|
|
2510
2510
|
usePersistRiskAdapter(Ctor) {
|
|
2511
|
-
|
|
2511
|
+
bt.loggerService.info(PERSIST_RISK_UTILS_METHOD_NAME_USE_PERSIST_RISK_ADAPTER);
|
|
2512
2512
|
this.PersistRiskFactory = Ctor;
|
|
2513
2513
|
}
|
|
2514
2514
|
}
|
|
@@ -2558,7 +2558,7 @@ class PersistScheduleUtils {
|
|
|
2558
2558
|
* @returns Promise resolving to scheduled signal or null
|
|
2559
2559
|
*/
|
|
2560
2560
|
this.readScheduleData = async (symbol, strategyName) => {
|
|
2561
|
-
|
|
2561
|
+
bt.loggerService.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_READ_DATA);
|
|
2562
2562
|
const key = `${symbol}:${strategyName}`;
|
|
2563
2563
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
2564
2564
|
const stateStorage = this.getScheduleStorage(symbol, strategyName);
|
|
@@ -2580,7 +2580,7 @@ class PersistScheduleUtils {
|
|
|
2580
2580
|
* @returns Promise that resolves when write is complete
|
|
2581
2581
|
*/
|
|
2582
2582
|
this.writeScheduleData = async (scheduledSignalRow, symbol, strategyName) => {
|
|
2583
|
-
|
|
2583
|
+
bt.loggerService.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2584
2584
|
const key = `${symbol}:${strategyName}`;
|
|
2585
2585
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
2586
2586
|
const stateStorage = this.getScheduleStorage(symbol, strategyName);
|
|
@@ -2603,7 +2603,7 @@ class PersistScheduleUtils {
|
|
|
2603
2603
|
* ```
|
|
2604
2604
|
*/
|
|
2605
2605
|
usePersistScheduleAdapter(Ctor) {
|
|
2606
|
-
|
|
2606
|
+
bt.loggerService.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_PERSIST_SCHEDULE_ADAPTER);
|
|
2607
2607
|
this.PersistScheduleFactory = Ctor;
|
|
2608
2608
|
}
|
|
2609
2609
|
}
|
|
@@ -2653,7 +2653,7 @@ class PersistPartialUtils {
|
|
|
2653
2653
|
* @returns Promise resolving to partial data record
|
|
2654
2654
|
*/
|
|
2655
2655
|
this.readPartialData = async (symbol, strategyName) => {
|
|
2656
|
-
|
|
2656
|
+
bt.loggerService.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_READ_DATA);
|
|
2657
2657
|
const key = `${symbol}:${strategyName}`;
|
|
2658
2658
|
const isInitial = !this.getPartialStorage.has(key);
|
|
2659
2659
|
const stateStorage = this.getPartialStorage(symbol, strategyName);
|
|
@@ -2676,7 +2676,7 @@ class PersistPartialUtils {
|
|
|
2676
2676
|
* @returns Promise that resolves when write is complete
|
|
2677
2677
|
*/
|
|
2678
2678
|
this.writePartialData = async (partialData, symbol, strategyName) => {
|
|
2679
|
-
|
|
2679
|
+
bt.loggerService.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2680
2680
|
const key = `${symbol}:${strategyName}`;
|
|
2681
2681
|
const isInitial = !this.getPartialStorage.has(key);
|
|
2682
2682
|
const stateStorage = this.getPartialStorage(symbol, strategyName);
|
|
@@ -2700,7 +2700,7 @@ class PersistPartialUtils {
|
|
|
2700
2700
|
* ```
|
|
2701
2701
|
*/
|
|
2702
2702
|
usePersistPartialAdapter(Ctor) {
|
|
2703
|
-
|
|
2703
|
+
bt.loggerService.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_PERSIST_PARTIAL_ADAPTER);
|
|
2704
2704
|
this.PersistPartialFactory = Ctor;
|
|
2705
2705
|
}
|
|
2706
2706
|
}
|
|
@@ -3169,7 +3169,7 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
3169
3169
|
error: functoolsKit.errorData(error),
|
|
3170
3170
|
message: functoolsKit.getErrorMessage(error),
|
|
3171
3171
|
};
|
|
3172
|
-
|
|
3172
|
+
bt.loggerService.warn(message, payload);
|
|
3173
3173
|
console.warn(message, payload);
|
|
3174
3174
|
errorEmitter.next(error);
|
|
3175
3175
|
},
|
|
@@ -3248,6 +3248,7 @@ const CHECK_SCHEDULED_SIGNAL_TIMEOUT_FN = async (self, scheduled, currentPrice)
|
|
|
3248
3248
|
strategyName: self.params.method.context.strategyName,
|
|
3249
3249
|
exchangeName: self.params.method.context.exchangeName,
|
|
3250
3250
|
symbol: self.params.execution.context.symbol,
|
|
3251
|
+
backtest: self.params.execution.context.backtest,
|
|
3251
3252
|
};
|
|
3252
3253
|
if (self.params.callbacks?.onTick) {
|
|
3253
3254
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3299,6 +3300,7 @@ const CANCEL_SCHEDULED_SIGNAL_BY_STOPLOSS_FN = async (self, scheduled, currentPr
|
|
|
3299
3300
|
exchangeName: self.params.method.context.exchangeName,
|
|
3300
3301
|
symbol: self.params.execution.context.symbol,
|
|
3301
3302
|
currentPrice: currentPrice,
|
|
3303
|
+
backtest: self.params.execution.context.backtest,
|
|
3302
3304
|
};
|
|
3303
3305
|
if (self.params.callbacks?.onTick) {
|
|
3304
3306
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3366,6 +3368,7 @@ const ACTIVATE_SCHEDULED_SIGNAL_FN = async (self, scheduled, activationTimestamp
|
|
|
3366
3368
|
exchangeName: self.params.method.context.exchangeName,
|
|
3367
3369
|
symbol: self.params.execution.context.symbol,
|
|
3368
3370
|
currentPrice: self._pendingSignal.priceOpen,
|
|
3371
|
+
backtest: self.params.execution.context.backtest,
|
|
3369
3372
|
};
|
|
3370
3373
|
if (self.params.callbacks?.onTick) {
|
|
3371
3374
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3382,6 +3385,7 @@ const RETURN_SCHEDULED_SIGNAL_ACTIVE_FN = async (self, scheduled, currentPrice)
|
|
|
3382
3385
|
symbol: self.params.execution.context.symbol,
|
|
3383
3386
|
percentTp: 0,
|
|
3384
3387
|
percentSl: 0,
|
|
3388
|
+
backtest: self.params.execution.context.backtest,
|
|
3385
3389
|
};
|
|
3386
3390
|
if (self.params.callbacks?.onTick) {
|
|
3387
3391
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3407,6 +3411,7 @@ const OPEN_NEW_SCHEDULED_SIGNAL_FN = async (self, signal) => {
|
|
|
3407
3411
|
exchangeName: self.params.method.context.exchangeName,
|
|
3408
3412
|
symbol: self.params.execution.context.symbol,
|
|
3409
3413
|
currentPrice: currentPrice,
|
|
3414
|
+
backtest: self.params.execution.context.backtest,
|
|
3410
3415
|
};
|
|
3411
3416
|
if (self.params.callbacks?.onTick) {
|
|
3412
3417
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3438,6 +3443,7 @@ const OPEN_NEW_PENDING_SIGNAL_FN = async (self, signal) => {
|
|
|
3438
3443
|
exchangeName: self.params.method.context.exchangeName,
|
|
3439
3444
|
symbol: self.params.execution.context.symbol,
|
|
3440
3445
|
currentPrice: signal.priceOpen,
|
|
3446
|
+
backtest: self.params.execution.context.backtest,
|
|
3441
3447
|
};
|
|
3442
3448
|
if (self.params.callbacks?.onTick) {
|
|
3443
3449
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3502,6 +3508,7 @@ const CLOSE_PENDING_SIGNAL_FN = async (self, signal, currentPrice, closeReason)
|
|
|
3502
3508
|
strategyName: self.params.method.context.strategyName,
|
|
3503
3509
|
exchangeName: self.params.method.context.exchangeName,
|
|
3504
3510
|
symbol: self.params.execution.context.symbol,
|
|
3511
|
+
backtest: self.params.execution.context.backtest,
|
|
3505
3512
|
};
|
|
3506
3513
|
if (self.params.callbacks?.onTick) {
|
|
3507
3514
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3571,6 +3578,7 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice) => {
|
|
|
3571
3578
|
symbol: self.params.execution.context.symbol,
|
|
3572
3579
|
percentTp,
|
|
3573
3580
|
percentSl,
|
|
3581
|
+
backtest: self.params.execution.context.backtest,
|
|
3574
3582
|
};
|
|
3575
3583
|
if (self.params.callbacks?.onTick) {
|
|
3576
3584
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3588,6 +3596,7 @@ const RETURN_IDLE_FN = async (self, currentPrice) => {
|
|
|
3588
3596
|
exchangeName: self.params.method.context.exchangeName,
|
|
3589
3597
|
symbol: self.params.execution.context.symbol,
|
|
3590
3598
|
currentPrice: currentPrice,
|
|
3599
|
+
backtest: self.params.execution.context.backtest,
|
|
3591
3600
|
};
|
|
3592
3601
|
if (self.params.callbacks?.onTick) {
|
|
3593
3602
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3614,6 +3623,7 @@ const CANCEL_SCHEDULED_SIGNAL_IN_BACKTEST_FN = async (self, scheduled, averagePr
|
|
|
3614
3623
|
strategyName: self.params.method.context.strategyName,
|
|
3615
3624
|
exchangeName: self.params.method.context.exchangeName,
|
|
3616
3625
|
symbol: self.params.execution.context.symbol,
|
|
3626
|
+
backtest: self.params.execution.context.backtest,
|
|
3617
3627
|
};
|
|
3618
3628
|
if (self.params.callbacks?.onTick) {
|
|
3619
3629
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3709,6 +3719,7 @@ const CLOSE_PENDING_SIGNAL_IN_BACKTEST_FN = async (self, signal, averagePrice, c
|
|
|
3709
3719
|
strategyName: self.params.method.context.strategyName,
|
|
3710
3720
|
exchangeName: self.params.method.context.exchangeName,
|
|
3711
3721
|
symbol: self.params.execution.context.symbol,
|
|
3722
|
+
backtest: self.params.execution.context.backtest,
|
|
3712
3723
|
};
|
|
3713
3724
|
if (self.params.callbacks?.onTick) {
|
|
3714
3725
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -4207,6 +4218,7 @@ class ClientStrategy {
|
|
|
4207
4218
|
strategyName: this.params.method.context.strategyName,
|
|
4208
4219
|
exchangeName: this.params.method.context.exchangeName,
|
|
4209
4220
|
symbol: this.params.execution.context.symbol,
|
|
4221
|
+
backtest: this.params.execution.context.backtest,
|
|
4210
4222
|
};
|
|
4211
4223
|
return result; // Cast to IStrategyBacktestResult (which includes Active)
|
|
4212
4224
|
}
|
|
@@ -4337,7 +4349,7 @@ class MergeRisk {
|
|
|
4337
4349
|
* @returns Promise resolving to true if all risks approve, false if any risk rejects
|
|
4338
4350
|
*/
|
|
4339
4351
|
async checkSignal(params) {
|
|
4340
|
-
|
|
4352
|
+
bt.loggerService.info("MergeRisk checkSignal", {
|
|
4341
4353
|
params,
|
|
4342
4354
|
});
|
|
4343
4355
|
const riskCheck = await Promise.all(this._riskList.map(async (risk) => await risk.checkSignal(params)));
|
|
@@ -4354,7 +4366,7 @@ class MergeRisk {
|
|
|
4354
4366
|
* @returns Promise that resolves when all risks have registered the signal
|
|
4355
4367
|
*/
|
|
4356
4368
|
async addSignal(symbol, context) {
|
|
4357
|
-
|
|
4369
|
+
bt.loggerService.info("MergeRisk addSignal", {
|
|
4358
4370
|
symbol,
|
|
4359
4371
|
context,
|
|
4360
4372
|
});
|
|
@@ -4371,7 +4383,7 @@ class MergeRisk {
|
|
|
4371
4383
|
* @returns Promise that resolves when all risks have removed the signal
|
|
4372
4384
|
*/
|
|
4373
4385
|
async removeSignal(symbol, context) {
|
|
4374
|
-
|
|
4386
|
+
bt.loggerService.info("MergeRisk removeSignal", {
|
|
4375
4387
|
symbol,
|
|
4376
4388
|
context,
|
|
4377
4389
|
});
|
|
@@ -4439,19 +4451,19 @@ class RiskUtils {
|
|
|
4439
4451
|
* }
|
|
4440
4452
|
* ```
|
|
4441
4453
|
*/
|
|
4442
|
-
this.getData = async (symbol, strategyName) => {
|
|
4443
|
-
|
|
4454
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
4455
|
+
bt.loggerService.info(RISK_METHOD_NAME_GET_DATA, {
|
|
4444
4456
|
symbol,
|
|
4445
4457
|
strategyName,
|
|
4446
4458
|
});
|
|
4447
|
-
|
|
4459
|
+
bt.strategyValidationService.validate(strategyName, RISK_METHOD_NAME_GET_DATA);
|
|
4448
4460
|
{
|
|
4449
|
-
const { riskName, riskList } =
|
|
4461
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
4450
4462
|
riskName &&
|
|
4451
|
-
|
|
4452
|
-
riskList && riskList.forEach((riskName) =>
|
|
4463
|
+
bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_DATA);
|
|
4464
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_DATA));
|
|
4453
4465
|
}
|
|
4454
|
-
return await
|
|
4466
|
+
return await bt.riskMarkdownService.getData(symbol, strategyName, backtest);
|
|
4455
4467
|
};
|
|
4456
4468
|
/**
|
|
4457
4469
|
* Generates markdown report with all risk rejection events for a symbol-strategy pair.
|
|
@@ -4494,19 +4506,19 @@ class RiskUtils {
|
|
|
4494
4506
|
* // - my-strategy: 1
|
|
4495
4507
|
* ```
|
|
4496
4508
|
*/
|
|
4497
|
-
this.getReport = async (symbol, strategyName, columns) => {
|
|
4498
|
-
|
|
4509
|
+
this.getReport = async (symbol, strategyName, backtest, columns) => {
|
|
4510
|
+
bt.loggerService.info(RISK_METHOD_NAME_GET_REPORT, {
|
|
4499
4511
|
symbol,
|
|
4500
4512
|
strategyName,
|
|
4501
4513
|
});
|
|
4502
|
-
|
|
4514
|
+
bt.strategyValidationService.validate(strategyName, RISK_METHOD_NAME_GET_REPORT);
|
|
4503
4515
|
{
|
|
4504
|
-
const { riskName, riskList } =
|
|
4516
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
4505
4517
|
riskName &&
|
|
4506
|
-
|
|
4507
|
-
riskList && riskList.forEach((riskName) =>
|
|
4518
|
+
bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_REPORT);
|
|
4519
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_REPORT));
|
|
4508
4520
|
}
|
|
4509
|
-
return await
|
|
4521
|
+
return await bt.riskMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
4510
4522
|
};
|
|
4511
4523
|
/**
|
|
4512
4524
|
* Generates and saves markdown report to file.
|
|
@@ -4540,20 +4552,20 @@ class RiskUtils {
|
|
|
4540
4552
|
* }
|
|
4541
4553
|
* ```
|
|
4542
4554
|
*/
|
|
4543
|
-
this.dump = async (symbol, strategyName, path, columns) => {
|
|
4544
|
-
|
|
4555
|
+
this.dump = async (symbol, strategyName, backtest, path, columns) => {
|
|
4556
|
+
bt.loggerService.info(RISK_METHOD_NAME_DUMP, {
|
|
4545
4557
|
symbol,
|
|
4546
4558
|
strategyName,
|
|
4547
4559
|
path,
|
|
4548
4560
|
});
|
|
4549
|
-
|
|
4561
|
+
bt.strategyValidationService.validate(strategyName, RISK_METHOD_NAME_DUMP);
|
|
4550
4562
|
{
|
|
4551
|
-
const { riskName, riskList } =
|
|
4563
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
4552
4564
|
riskName &&
|
|
4553
|
-
|
|
4554
|
-
riskList && riskList.forEach((riskName) =>
|
|
4565
|
+
bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_DUMP);
|
|
4566
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_DUMP));
|
|
4555
4567
|
}
|
|
4556
|
-
await
|
|
4568
|
+
await bt.riskMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
4557
4569
|
};
|
|
4558
4570
|
}
|
|
4559
4571
|
}
|
|
@@ -5171,7 +5183,7 @@ const DO_VALIDATION_FN = functoolsKit.trycatch(async (validation, params) => {
|
|
|
5171
5183
|
error: functoolsKit.errorData(error),
|
|
5172
5184
|
message: functoolsKit.getErrorMessage(error),
|
|
5173
5185
|
};
|
|
5174
|
-
|
|
5186
|
+
bt.loggerService.warn(message, payload);
|
|
5175
5187
|
console.warn(message, payload);
|
|
5176
5188
|
validationSubject.next(error);
|
|
5177
5189
|
},
|
|
@@ -5266,7 +5278,7 @@ class ClientRisk {
|
|
|
5266
5278
|
}
|
|
5267
5279
|
if (!isValid) {
|
|
5268
5280
|
// Call params.onRejected for riskSubject emission
|
|
5269
|
-
await this.params.onRejected(params.symbol, params, riskMap.size, rejectionNote, Date.now());
|
|
5281
|
+
await this.params.onRejected(params.symbol, params, riskMap.size, rejectionNote, Date.now(), this.params.backtest);
|
|
5270
5282
|
// Call schema callbacks.onRejected if defined
|
|
5271
5283
|
if (this.params.callbacks?.onRejected) {
|
|
5272
5284
|
this.params.callbacks.onRejected(params.symbol, params);
|
|
@@ -5347,8 +5359,9 @@ class ClientRisk {
|
|
|
5347
5359
|
* @param activePositionCount - Number of active positions at rejection time
|
|
5348
5360
|
* @param comment - Rejection reason from validation note or "N/A"
|
|
5349
5361
|
* @param timestamp - Event timestamp in milliseconds
|
|
5362
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
5350
5363
|
*/
|
|
5351
|
-
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, comment, timestamp) => await riskSubject.next({
|
|
5364
|
+
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, comment, timestamp, backtest) => await riskSubject.next({
|
|
5352
5365
|
symbol,
|
|
5353
5366
|
pendingSignal: params.pendingSignal,
|
|
5354
5367
|
strategyName: params.strategyName,
|
|
@@ -5357,6 +5370,7 @@ const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, comment,
|
|
|
5357
5370
|
activePositionCount,
|
|
5358
5371
|
comment,
|
|
5359
5372
|
timestamp,
|
|
5373
|
+
backtest,
|
|
5360
5374
|
});
|
|
5361
5375
|
/**
|
|
5362
5376
|
* Connection service routing risk operations to correct ClientRisk instance.
|
|
@@ -6427,6 +6441,13 @@ class WalkerSchemaService {
|
|
|
6427
6441
|
if (walkerSchema.strategies.length === 0) {
|
|
6428
6442
|
throw new Error(`walker schema validation failed: strategies array cannot be empty for walkerName=${walkerSchema.walkerName}`);
|
|
6429
6443
|
}
|
|
6444
|
+
if (walkerSchema.strategies &&
|
|
6445
|
+
walkerSchema.strategies.length !== new Set(walkerSchema.strategies).size) {
|
|
6446
|
+
throw new Error(`walker schema validation failed: found duplicate strategies for walkerName=${walkerSchema.walkerName} strategies=[${walkerSchema.strategies}]`);
|
|
6447
|
+
}
|
|
6448
|
+
if (walkerSchema.strategies?.some((value) => typeof value !== "string")) {
|
|
6449
|
+
throw new Error(`walker schema validation failed: invalid strategies for walkerName=${walkerSchema.walkerName} strategies=[${walkerSchema.strategies}]`);
|
|
6450
|
+
}
|
|
6430
6451
|
};
|
|
6431
6452
|
/**
|
|
6432
6453
|
* Overrides an existing walker schema with partial updates.
|
|
@@ -7031,7 +7052,7 @@ class WalkerLogicPrivateService {
|
|
|
7031
7052
|
symbol,
|
|
7032
7053
|
});
|
|
7033
7054
|
// Get statistics from BacktestMarkdownService
|
|
7034
|
-
const stats = await this.backtestMarkdownService.getData(symbol, strategyName);
|
|
7055
|
+
const stats = await this.backtestMarkdownService.getData(symbol, strategyName, true);
|
|
7035
7056
|
// Extract metric value
|
|
7036
7057
|
const value = stats[metric];
|
|
7037
7058
|
const metricValue = value !== null &&
|
|
@@ -7095,7 +7116,7 @@ class WalkerLogicPrivateService {
|
|
|
7095
7116
|
bestStrategy,
|
|
7096
7117
|
bestMetric,
|
|
7097
7118
|
bestStats: bestStrategy !== null
|
|
7098
|
-
? await this.backtestMarkdownService.getData(symbol, bestStrategy)
|
|
7119
|
+
? await this.backtestMarkdownService.getData(symbol, bestStrategy, true)
|
|
7099
7120
|
: null,
|
|
7100
7121
|
};
|
|
7101
7122
|
// Call onComplete callback if provided with final best results
|
|
@@ -7608,10 +7629,10 @@ class BacktestMarkdownService {
|
|
|
7608
7629
|
/** Logger service for debug output */
|
|
7609
7630
|
this.loggerService = inject(TYPES.loggerService);
|
|
7610
7631
|
/**
|
|
7611
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
7612
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
7632
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
7633
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
7613
7634
|
*/
|
|
7614
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$5());
|
|
7635
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$5());
|
|
7615
7636
|
/**
|
|
7616
7637
|
* Processes tick events and accumulates closed signals.
|
|
7617
7638
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -7638,7 +7659,7 @@ class BacktestMarkdownService {
|
|
|
7638
7659
|
if (data.action !== "closed") {
|
|
7639
7660
|
return;
|
|
7640
7661
|
}
|
|
7641
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
7662
|
+
const storage = this.getStorage(data.symbol, data.strategyName, true);
|
|
7642
7663
|
storage.addSignal(data);
|
|
7643
7664
|
};
|
|
7644
7665
|
/**
|
|
@@ -7647,21 +7668,23 @@ class BacktestMarkdownService {
|
|
|
7647
7668
|
*
|
|
7648
7669
|
* @param symbol - Trading pair symbol
|
|
7649
7670
|
* @param strategyName - Strategy name to get data for
|
|
7671
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
7650
7672
|
* @returns Statistical data object with all metrics
|
|
7651
7673
|
*
|
|
7652
7674
|
* @example
|
|
7653
7675
|
* ```typescript
|
|
7654
7676
|
* const service = new BacktestMarkdownService();
|
|
7655
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
7677
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", true);
|
|
7656
7678
|
* console.log(stats.sharpeRatio, stats.winRate);
|
|
7657
7679
|
* ```
|
|
7658
7680
|
*/
|
|
7659
|
-
this.getData = async (symbol, strategyName) => {
|
|
7681
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
7660
7682
|
this.loggerService.log("backtestMarkdownService getData", {
|
|
7661
7683
|
symbol,
|
|
7662
7684
|
strategyName,
|
|
7685
|
+
backtest,
|
|
7663
7686
|
});
|
|
7664
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
7687
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
7665
7688
|
return storage.getData();
|
|
7666
7689
|
};
|
|
7667
7690
|
/**
|
|
@@ -7670,22 +7693,24 @@ class BacktestMarkdownService {
|
|
|
7670
7693
|
*
|
|
7671
7694
|
* @param symbol - Trading pair symbol
|
|
7672
7695
|
* @param strategyName - Strategy name to generate report for
|
|
7696
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
7673
7697
|
* @param columns - Column configuration for formatting the table
|
|
7674
7698
|
* @returns Markdown formatted report string with table of all closed signals
|
|
7675
7699
|
*
|
|
7676
7700
|
* @example
|
|
7677
7701
|
* ```typescript
|
|
7678
7702
|
* const service = new BacktestMarkdownService();
|
|
7679
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
7703
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", true);
|
|
7680
7704
|
* console.log(markdown);
|
|
7681
7705
|
* ```
|
|
7682
7706
|
*/
|
|
7683
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7707
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7684
7708
|
this.loggerService.log("backtestMarkdownService getReport", {
|
|
7685
7709
|
symbol,
|
|
7686
7710
|
strategyName,
|
|
7711
|
+
backtest,
|
|
7687
7712
|
});
|
|
7688
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
7713
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
7689
7714
|
return storage.getReport(strategyName, columns);
|
|
7690
7715
|
};
|
|
7691
7716
|
/**
|
|
@@ -7695,6 +7720,7 @@ class BacktestMarkdownService {
|
|
|
7695
7720
|
*
|
|
7696
7721
|
* @param symbol - Trading pair symbol
|
|
7697
7722
|
* @param strategyName - Strategy name to save report for
|
|
7723
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
7698
7724
|
* @param path - Directory path to save report (default: "./dump/backtest")
|
|
7699
7725
|
* @param columns - Column configuration for formatting the table
|
|
7700
7726
|
*
|
|
@@ -7703,45 +7729,48 @@ class BacktestMarkdownService {
|
|
|
7703
7729
|
* const service = new BacktestMarkdownService();
|
|
7704
7730
|
*
|
|
7705
7731
|
* // Save to default path: ./dump/backtest/my-strategy.md
|
|
7706
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
7732
|
+
* await service.dump("BTCUSDT", "my-strategy", true);
|
|
7707
7733
|
*
|
|
7708
7734
|
* // Save to custom path: ./custom/path/my-strategy.md
|
|
7709
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
7735
|
+
* await service.dump("BTCUSDT", "my-strategy", true, "./custom/path");
|
|
7710
7736
|
* ```
|
|
7711
7737
|
*/
|
|
7712
|
-
this.dump = async (symbol, strategyName, path = "./dump/backtest", columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7738
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/backtest", columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7713
7739
|
this.loggerService.log("backtestMarkdownService dump", {
|
|
7714
7740
|
symbol,
|
|
7715
7741
|
strategyName,
|
|
7742
|
+
backtest,
|
|
7716
7743
|
path,
|
|
7717
7744
|
});
|
|
7718
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
7745
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
7719
7746
|
await storage.dump(strategyName, path, columns);
|
|
7720
7747
|
};
|
|
7721
7748
|
/**
|
|
7722
7749
|
* Clears accumulated signal data from storage.
|
|
7723
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
7750
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
7724
7751
|
* If nothing is provided, clears all data.
|
|
7725
7752
|
*
|
|
7753
|
+
* @param backtest - Backtest mode flag
|
|
7726
7754
|
* @param ctx - Optional context with symbol and strategyName
|
|
7727
7755
|
*
|
|
7728
7756
|
* @example
|
|
7729
7757
|
* ```typescript
|
|
7730
7758
|
* const service = new BacktestMarkdownService();
|
|
7731
7759
|
*
|
|
7732
|
-
* // Clear specific symbol-strategy
|
|
7733
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
7760
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
7761
|
+
* await service.clear(true, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
7734
7762
|
*
|
|
7735
7763
|
* // Clear all data
|
|
7736
7764
|
* await service.clear();
|
|
7737
7765
|
* ```
|
|
7738
7766
|
*/
|
|
7739
|
-
this.clear = async (ctx) => {
|
|
7767
|
+
this.clear = async (backtest, ctx) => {
|
|
7740
7768
|
this.loggerService.log("backtestMarkdownService clear", {
|
|
7769
|
+
backtest,
|
|
7741
7770
|
ctx,
|
|
7742
7771
|
});
|
|
7743
7772
|
if (ctx) {
|
|
7744
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
7773
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
7745
7774
|
this.getStorage.clear(key);
|
|
7746
7775
|
}
|
|
7747
7776
|
else {
|
|
@@ -8092,10 +8121,10 @@ class LiveMarkdownService {
|
|
|
8092
8121
|
/** Logger service for debug output */
|
|
8093
8122
|
this.loggerService = inject(TYPES.loggerService);
|
|
8094
8123
|
/**
|
|
8095
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
8096
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
8124
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
8125
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
8097
8126
|
*/
|
|
8098
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$4());
|
|
8127
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$4());
|
|
8099
8128
|
/**
|
|
8100
8129
|
* Processes tick events and accumulates all event types.
|
|
8101
8130
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -8121,7 +8150,7 @@ class LiveMarkdownService {
|
|
|
8121
8150
|
this.loggerService.log("liveMarkdownService tick", {
|
|
8122
8151
|
data,
|
|
8123
8152
|
});
|
|
8124
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
8153
|
+
const storage = this.getStorage(data.symbol, data.strategyName, false);
|
|
8125
8154
|
if (data.action === "idle") {
|
|
8126
8155
|
storage.addIdleEvent(data.currentPrice);
|
|
8127
8156
|
}
|
|
@@ -8141,21 +8170,23 @@ class LiveMarkdownService {
|
|
|
8141
8170
|
*
|
|
8142
8171
|
* @param symbol - Trading pair symbol
|
|
8143
8172
|
* @param strategyName - Strategy name to get data for
|
|
8173
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8144
8174
|
* @returns Statistical data object with all metrics
|
|
8145
8175
|
*
|
|
8146
8176
|
* @example
|
|
8147
8177
|
* ```typescript
|
|
8148
8178
|
* const service = new LiveMarkdownService();
|
|
8149
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
8179
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
8150
8180
|
* console.log(stats.sharpeRatio, stats.winRate);
|
|
8151
8181
|
* ```
|
|
8152
8182
|
*/
|
|
8153
|
-
this.getData = async (symbol, strategyName) => {
|
|
8183
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
8154
8184
|
this.loggerService.log("liveMarkdownService getData", {
|
|
8155
8185
|
symbol,
|
|
8156
8186
|
strategyName,
|
|
8187
|
+
backtest,
|
|
8157
8188
|
});
|
|
8158
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8189
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8159
8190
|
return storage.getData();
|
|
8160
8191
|
};
|
|
8161
8192
|
/**
|
|
@@ -8164,22 +8195,24 @@ class LiveMarkdownService {
|
|
|
8164
8195
|
*
|
|
8165
8196
|
* @param symbol - Trading pair symbol
|
|
8166
8197
|
* @param strategyName - Strategy name to generate report for
|
|
8198
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8167
8199
|
* @param columns - Column configuration for formatting the table
|
|
8168
8200
|
* @returns Markdown formatted report string with table of all events
|
|
8169
8201
|
*
|
|
8170
8202
|
* @example
|
|
8171
8203
|
* ```typescript
|
|
8172
8204
|
* const service = new LiveMarkdownService();
|
|
8173
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
8205
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
8174
8206
|
* console.log(markdown);
|
|
8175
8207
|
* ```
|
|
8176
8208
|
*/
|
|
8177
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.live_columns) => {
|
|
8209
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.live_columns) => {
|
|
8178
8210
|
this.loggerService.log("liveMarkdownService getReport", {
|
|
8179
8211
|
symbol,
|
|
8180
8212
|
strategyName,
|
|
8213
|
+
backtest,
|
|
8181
8214
|
});
|
|
8182
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8215
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8183
8216
|
return storage.getReport(strategyName, columns);
|
|
8184
8217
|
};
|
|
8185
8218
|
/**
|
|
@@ -8189,6 +8222,7 @@ class LiveMarkdownService {
|
|
|
8189
8222
|
*
|
|
8190
8223
|
* @param symbol - Trading pair symbol
|
|
8191
8224
|
* @param strategyName - Strategy name to save report for
|
|
8225
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8192
8226
|
* @param path - Directory path to save report (default: "./dump/live")
|
|
8193
8227
|
* @param columns - Column configuration for formatting the table
|
|
8194
8228
|
*
|
|
@@ -8197,45 +8231,48 @@ class LiveMarkdownService {
|
|
|
8197
8231
|
* const service = new LiveMarkdownService();
|
|
8198
8232
|
*
|
|
8199
8233
|
* // Save to default path: ./dump/live/my-strategy.md
|
|
8200
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
8234
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
8201
8235
|
*
|
|
8202
8236
|
* // Save to custom path: ./custom/path/my-strategy.md
|
|
8203
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
8237
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
8204
8238
|
* ```
|
|
8205
8239
|
*/
|
|
8206
|
-
this.dump = async (symbol, strategyName, path = "./dump/live", columns = COLUMN_CONFIG.live_columns) => {
|
|
8240
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/live", columns = COLUMN_CONFIG.live_columns) => {
|
|
8207
8241
|
this.loggerService.log("liveMarkdownService dump", {
|
|
8208
8242
|
symbol,
|
|
8209
8243
|
strategyName,
|
|
8244
|
+
backtest,
|
|
8210
8245
|
path,
|
|
8211
8246
|
});
|
|
8212
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8247
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8213
8248
|
await storage.dump(strategyName, path, columns);
|
|
8214
8249
|
};
|
|
8215
8250
|
/**
|
|
8216
8251
|
* Clears accumulated event data from storage.
|
|
8217
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
8252
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
8218
8253
|
* If nothing is provided, clears all data.
|
|
8219
8254
|
*
|
|
8255
|
+
* @param backtest - Backtest mode flag
|
|
8220
8256
|
* @param ctx - Optional context with symbol and strategyName
|
|
8221
8257
|
*
|
|
8222
8258
|
* @example
|
|
8223
8259
|
* ```typescript
|
|
8224
8260
|
* const service = new LiveMarkdownService();
|
|
8225
8261
|
*
|
|
8226
|
-
* // Clear specific symbol-strategy
|
|
8227
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8262
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
8263
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8228
8264
|
*
|
|
8229
8265
|
* // Clear all data
|
|
8230
8266
|
* await service.clear();
|
|
8231
8267
|
* ```
|
|
8232
8268
|
*/
|
|
8233
|
-
this.clear = async (ctx) => {
|
|
8269
|
+
this.clear = async (backtest, ctx) => {
|
|
8234
8270
|
this.loggerService.log("liveMarkdownService clear", {
|
|
8271
|
+
backtest,
|
|
8235
8272
|
ctx,
|
|
8236
8273
|
});
|
|
8237
8274
|
if (ctx) {
|
|
8238
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
8275
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
8239
8276
|
this.getStorage.clear(key);
|
|
8240
8277
|
}
|
|
8241
8278
|
else {
|
|
@@ -8490,10 +8527,10 @@ class ScheduleMarkdownService {
|
|
|
8490
8527
|
/** Logger service for debug output */
|
|
8491
8528
|
this.loggerService = inject(TYPES.loggerService);
|
|
8492
8529
|
/**
|
|
8493
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
8494
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
8530
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
8531
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
8495
8532
|
*/
|
|
8496
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$3());
|
|
8533
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$3());
|
|
8497
8534
|
/**
|
|
8498
8535
|
* Processes tick events and accumulates scheduled/opened/cancelled events.
|
|
8499
8536
|
* Should be called from signalEmitter subscription.
|
|
@@ -8512,7 +8549,7 @@ class ScheduleMarkdownService {
|
|
|
8512
8549
|
this.loggerService.log("scheduleMarkdownService tick", {
|
|
8513
8550
|
data,
|
|
8514
8551
|
});
|
|
8515
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
8552
|
+
const storage = this.getStorage(data.symbol, data.strategyName, data.backtest);
|
|
8516
8553
|
if (data.action === "scheduled") {
|
|
8517
8554
|
storage.addScheduledEvent(data);
|
|
8518
8555
|
}
|
|
@@ -8533,21 +8570,23 @@ class ScheduleMarkdownService {
|
|
|
8533
8570
|
*
|
|
8534
8571
|
* @param symbol - Trading pair symbol
|
|
8535
8572
|
* @param strategyName - Strategy name to get data for
|
|
8573
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8536
8574
|
* @returns Statistical data object with all metrics
|
|
8537
8575
|
*
|
|
8538
8576
|
* @example
|
|
8539
8577
|
* ```typescript
|
|
8540
8578
|
* const service = new ScheduleMarkdownService();
|
|
8541
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
8579
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
8542
8580
|
* console.log(stats.cancellationRate, stats.avgWaitTime);
|
|
8543
8581
|
* ```
|
|
8544
8582
|
*/
|
|
8545
|
-
this.getData = async (symbol, strategyName) => {
|
|
8583
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
8546
8584
|
this.loggerService.log("scheduleMarkdownService getData", {
|
|
8547
8585
|
symbol,
|
|
8548
8586
|
strategyName,
|
|
8587
|
+
backtest,
|
|
8549
8588
|
});
|
|
8550
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8589
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8551
8590
|
return storage.getData();
|
|
8552
8591
|
};
|
|
8553
8592
|
/**
|
|
@@ -8556,22 +8595,24 @@ class ScheduleMarkdownService {
|
|
|
8556
8595
|
*
|
|
8557
8596
|
* @param symbol - Trading pair symbol
|
|
8558
8597
|
* @param strategyName - Strategy name to generate report for
|
|
8598
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8559
8599
|
* @param columns - Column configuration for formatting the table
|
|
8560
8600
|
* @returns Markdown formatted report string with table of all events
|
|
8561
8601
|
*
|
|
8562
8602
|
* @example
|
|
8563
8603
|
* ```typescript
|
|
8564
8604
|
* const service = new ScheduleMarkdownService();
|
|
8565
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
8605
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
8566
8606
|
* console.log(markdown);
|
|
8567
8607
|
* ```
|
|
8568
8608
|
*/
|
|
8569
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8609
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8570
8610
|
this.loggerService.log("scheduleMarkdownService getReport", {
|
|
8571
8611
|
symbol,
|
|
8572
8612
|
strategyName,
|
|
8613
|
+
backtest,
|
|
8573
8614
|
});
|
|
8574
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8615
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8575
8616
|
return storage.getReport(strategyName, columns);
|
|
8576
8617
|
};
|
|
8577
8618
|
/**
|
|
@@ -8581,6 +8622,7 @@ class ScheduleMarkdownService {
|
|
|
8581
8622
|
*
|
|
8582
8623
|
* @param symbol - Trading pair symbol
|
|
8583
8624
|
* @param strategyName - Strategy name to save report for
|
|
8625
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8584
8626
|
* @param path - Directory path to save report (default: "./dump/schedule")
|
|
8585
8627
|
* @param columns - Column configuration for formatting the table
|
|
8586
8628
|
*
|
|
@@ -8589,45 +8631,48 @@ class ScheduleMarkdownService {
|
|
|
8589
8631
|
* const service = new ScheduleMarkdownService();
|
|
8590
8632
|
*
|
|
8591
8633
|
* // Save to default path: ./dump/schedule/my-strategy.md
|
|
8592
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
8634
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
8593
8635
|
*
|
|
8594
8636
|
* // Save to custom path: ./custom/path/my-strategy.md
|
|
8595
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
8637
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
8596
8638
|
* ```
|
|
8597
8639
|
*/
|
|
8598
|
-
this.dump = async (symbol, strategyName, path = "./dump/schedule", columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8640
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/schedule", columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8599
8641
|
this.loggerService.log("scheduleMarkdownService dump", {
|
|
8600
8642
|
symbol,
|
|
8601
8643
|
strategyName,
|
|
8644
|
+
backtest,
|
|
8602
8645
|
path,
|
|
8603
8646
|
});
|
|
8604
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8647
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8605
8648
|
await storage.dump(strategyName, path, columns);
|
|
8606
8649
|
};
|
|
8607
8650
|
/**
|
|
8608
8651
|
* Clears accumulated event data from storage.
|
|
8609
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
8652
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
8610
8653
|
* If nothing is provided, clears all data.
|
|
8611
8654
|
*
|
|
8655
|
+
* @param backtest - Backtest mode flag
|
|
8612
8656
|
* @param ctx - Optional context with symbol and strategyName
|
|
8613
8657
|
*
|
|
8614
8658
|
* @example
|
|
8615
8659
|
* ```typescript
|
|
8616
8660
|
* const service = new ScheduleMarkdownService();
|
|
8617
8661
|
*
|
|
8618
|
-
* // Clear specific symbol-strategy
|
|
8619
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8662
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
8663
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8620
8664
|
*
|
|
8621
8665
|
* // Clear all data
|
|
8622
8666
|
* await service.clear();
|
|
8623
8667
|
* ```
|
|
8624
8668
|
*/
|
|
8625
|
-
this.clear = async (ctx) => {
|
|
8669
|
+
this.clear = async (backtest, ctx) => {
|
|
8626
8670
|
this.loggerService.log("scheduleMarkdownService clear", {
|
|
8671
|
+
backtest,
|
|
8627
8672
|
ctx,
|
|
8628
8673
|
});
|
|
8629
8674
|
if (ctx) {
|
|
8630
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
8675
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
8631
8676
|
this.getStorage.clear(key);
|
|
8632
8677
|
}
|
|
8633
8678
|
else {
|
|
@@ -8866,10 +8911,10 @@ class PerformanceMarkdownService {
|
|
|
8866
8911
|
/** Logger service for debug output */
|
|
8867
8912
|
this.loggerService = inject(TYPES.loggerService);
|
|
8868
8913
|
/**
|
|
8869
|
-
* Memoized function to get or create PerformanceStorage for a symbol-strategy
|
|
8870
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
8914
|
+
* Memoized function to get or create PerformanceStorage for a symbol-strategy-backtest triple.
|
|
8915
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
8871
8916
|
*/
|
|
8872
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new PerformanceStorage());
|
|
8917
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new PerformanceStorage());
|
|
8873
8918
|
/**
|
|
8874
8919
|
* Processes performance events and accumulates metrics.
|
|
8875
8920
|
* Should be called from performance tracking code.
|
|
@@ -8882,7 +8927,7 @@ class PerformanceMarkdownService {
|
|
|
8882
8927
|
});
|
|
8883
8928
|
const symbol = event.symbol || "global";
|
|
8884
8929
|
const strategyName = event.strategyName || "global";
|
|
8885
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8930
|
+
const storage = this.getStorage(symbol, strategyName, event.backtest);
|
|
8886
8931
|
storage.addEvent(event);
|
|
8887
8932
|
};
|
|
8888
8933
|
/**
|
|
@@ -8890,22 +8935,24 @@ class PerformanceMarkdownService {
|
|
|
8890
8935
|
*
|
|
8891
8936
|
* @param symbol - Trading pair symbol
|
|
8892
8937
|
* @param strategyName - Strategy name to get data for
|
|
8938
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8893
8939
|
* @returns Performance statistics with aggregated metrics
|
|
8894
8940
|
*
|
|
8895
8941
|
* @example
|
|
8896
8942
|
* ```typescript
|
|
8897
|
-
* const stats = await performanceService.getData("BTCUSDT", "my-strategy");
|
|
8943
|
+
* const stats = await performanceService.getData("BTCUSDT", "my-strategy", false);
|
|
8898
8944
|
* console.log("Total time:", stats.totalDuration);
|
|
8899
8945
|
* console.log("Slowest operation:", Object.values(stats.metricStats)
|
|
8900
8946
|
* .sort((a, b) => b.avgDuration - a.avgDuration)[0]);
|
|
8901
8947
|
* ```
|
|
8902
8948
|
*/
|
|
8903
|
-
this.getData = async (symbol, strategyName) => {
|
|
8949
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
8904
8950
|
this.loggerService.log("performanceMarkdownService getData", {
|
|
8905
8951
|
symbol,
|
|
8906
8952
|
strategyName,
|
|
8953
|
+
backtest,
|
|
8907
8954
|
});
|
|
8908
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8955
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8909
8956
|
return storage.getData(strategyName);
|
|
8910
8957
|
};
|
|
8911
8958
|
/**
|
|
@@ -8913,21 +8960,23 @@ class PerformanceMarkdownService {
|
|
|
8913
8960
|
*
|
|
8914
8961
|
* @param symbol - Trading pair symbol
|
|
8915
8962
|
* @param strategyName - Strategy name to generate report for
|
|
8963
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8916
8964
|
* @param columns - Column configuration for formatting the table
|
|
8917
8965
|
* @returns Markdown formatted report string
|
|
8918
8966
|
*
|
|
8919
8967
|
* @example
|
|
8920
8968
|
* ```typescript
|
|
8921
|
-
* const markdown = await performanceService.getReport("BTCUSDT", "my-strategy");
|
|
8969
|
+
* const markdown = await performanceService.getReport("BTCUSDT", "my-strategy", false);
|
|
8922
8970
|
* console.log(markdown);
|
|
8923
8971
|
* ```
|
|
8924
8972
|
*/
|
|
8925
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.performance_columns) => {
|
|
8973
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.performance_columns) => {
|
|
8926
8974
|
this.loggerService.log("performanceMarkdownService getReport", {
|
|
8927
8975
|
symbol,
|
|
8928
8976
|
strategyName,
|
|
8977
|
+
backtest,
|
|
8929
8978
|
});
|
|
8930
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8979
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8931
8980
|
return storage.getReport(strategyName, columns);
|
|
8932
8981
|
};
|
|
8933
8982
|
/**
|
|
@@ -8935,42 +8984,45 @@ class PerformanceMarkdownService {
|
|
|
8935
8984
|
*
|
|
8936
8985
|
* @param symbol - Trading pair symbol
|
|
8937
8986
|
* @param strategyName - Strategy name to save report for
|
|
8987
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8938
8988
|
* @param path - Directory path to save report
|
|
8939
8989
|
* @param columns - Column configuration for formatting the table
|
|
8940
8990
|
*
|
|
8941
8991
|
* @example
|
|
8942
8992
|
* ```typescript
|
|
8943
8993
|
* // Save to default path: ./dump/performance/my-strategy.md
|
|
8944
|
-
* await performanceService.dump("BTCUSDT", "my-strategy");
|
|
8994
|
+
* await performanceService.dump("BTCUSDT", "my-strategy", false);
|
|
8945
8995
|
*
|
|
8946
8996
|
* // Save to custom path
|
|
8947
|
-
* await performanceService.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
8997
|
+
* await performanceService.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
8948
8998
|
* ```
|
|
8949
8999
|
*/
|
|
8950
|
-
this.dump = async (symbol, strategyName, path = "./dump/performance", columns = COLUMN_CONFIG.performance_columns) => {
|
|
9000
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/performance", columns = COLUMN_CONFIG.performance_columns) => {
|
|
8951
9001
|
this.loggerService.log("performanceMarkdownService dump", {
|
|
8952
9002
|
symbol,
|
|
8953
9003
|
strategyName,
|
|
9004
|
+
backtest,
|
|
8954
9005
|
path,
|
|
8955
9006
|
});
|
|
8956
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
9007
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8957
9008
|
await storage.dump(strategyName, path, columns);
|
|
8958
9009
|
};
|
|
8959
9010
|
/**
|
|
8960
9011
|
* Clears accumulated performance data from storage.
|
|
8961
9012
|
*
|
|
8962
|
-
* @param
|
|
8963
|
-
* @param
|
|
9013
|
+
* @param backtest - Backtest mode flag
|
|
9014
|
+
* @param ctx - Optional context with symbol and strategyName
|
|
8964
9015
|
*/
|
|
8965
|
-
this.clear = async (ctx) => {
|
|
9016
|
+
this.clear = async (backtest, ctx) => {
|
|
8966
9017
|
this.loggerService.log("performanceMarkdownService clear", {
|
|
9018
|
+
backtest,
|
|
8967
9019
|
ctx,
|
|
8968
9020
|
});
|
|
8969
9021
|
if (ctx) {
|
|
8970
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
9022
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
8971
9023
|
this.getStorage.clear(key);
|
|
8972
9024
|
}
|
|
8973
|
-
{
|
|
9025
|
+
else {
|
|
8974
9026
|
this.getStorage.clear();
|
|
8975
9027
|
}
|
|
8976
9028
|
};
|
|
@@ -9734,10 +9786,10 @@ class HeatMarkdownService {
|
|
|
9734
9786
|
/** Logger service for debug output */
|
|
9735
9787
|
this.loggerService = inject(TYPES.loggerService);
|
|
9736
9788
|
/**
|
|
9737
|
-
* Memoized function to get or create HeatmapStorage for a strategy.
|
|
9738
|
-
* Each strategy gets its own isolated heatmap storage instance.
|
|
9789
|
+
* Memoized function to get or create HeatmapStorage for a strategy and backtest mode.
|
|
9790
|
+
* Each strategy + backtest mode combination gets its own isolated heatmap storage instance.
|
|
9739
9791
|
*/
|
|
9740
|
-
this.getStorage = functoolsKit.memoize(([strategyName]) => `${strategyName}`, () => new HeatmapStorage());
|
|
9792
|
+
this.getStorage = functoolsKit.memoize(([strategyName, backtest]) => `${strategyName}:${backtest ? "backtest" : "live"}`, () => new HeatmapStorage());
|
|
9741
9793
|
/**
|
|
9742
9794
|
* Processes tick events and accumulates closed signals.
|
|
9743
9795
|
* Should be called from signal emitter subscription.
|
|
@@ -9753,19 +9805,20 @@ class HeatMarkdownService {
|
|
|
9753
9805
|
if (data.action !== "closed") {
|
|
9754
9806
|
return;
|
|
9755
9807
|
}
|
|
9756
|
-
const storage = this.getStorage(data.strategyName);
|
|
9808
|
+
const storage = this.getStorage(data.strategyName, data.backtest);
|
|
9757
9809
|
storage.addSignal(data);
|
|
9758
9810
|
};
|
|
9759
9811
|
/**
|
|
9760
9812
|
* Gets aggregated portfolio heatmap statistics for a strategy.
|
|
9761
9813
|
*
|
|
9762
9814
|
* @param strategyName - Strategy name to get heatmap data for
|
|
9815
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
9763
9816
|
* @returns Promise resolving to heatmap statistics with per-symbol and portfolio-wide metrics
|
|
9764
9817
|
*
|
|
9765
9818
|
* @example
|
|
9766
9819
|
* ```typescript
|
|
9767
9820
|
* const service = new HeatMarkdownService();
|
|
9768
|
-
* const stats = await service.getData("my-strategy");
|
|
9821
|
+
* const stats = await service.getData("my-strategy", true);
|
|
9769
9822
|
*
|
|
9770
9823
|
* console.log(`Total symbols: ${stats.totalSymbols}`);
|
|
9771
9824
|
* console.log(`Portfolio PNL: ${stats.portfolioTotalPnl}%`);
|
|
@@ -9775,24 +9828,26 @@ class HeatMarkdownService {
|
|
|
9775
9828
|
* });
|
|
9776
9829
|
* ```
|
|
9777
9830
|
*/
|
|
9778
|
-
this.getData = async (strategyName) => {
|
|
9831
|
+
this.getData = async (strategyName, backtest) => {
|
|
9779
9832
|
this.loggerService.log(HEATMAP_METHOD_NAME_GET_DATA, {
|
|
9780
9833
|
strategyName,
|
|
9834
|
+
backtest,
|
|
9781
9835
|
});
|
|
9782
|
-
const storage = this.getStorage(strategyName);
|
|
9836
|
+
const storage = this.getStorage(strategyName, backtest);
|
|
9783
9837
|
return storage.getData();
|
|
9784
9838
|
};
|
|
9785
9839
|
/**
|
|
9786
9840
|
* Generates markdown report with portfolio heatmap table for a strategy.
|
|
9787
9841
|
*
|
|
9788
9842
|
* @param strategyName - Strategy name to generate heatmap report for
|
|
9843
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
9789
9844
|
* @param columns - Column configuration for formatting the table
|
|
9790
9845
|
* @returns Promise resolving to markdown formatted report string
|
|
9791
9846
|
*
|
|
9792
9847
|
* @example
|
|
9793
9848
|
* ```typescript
|
|
9794
9849
|
* const service = new HeatMarkdownService();
|
|
9795
|
-
* const markdown = await service.getReport("my-strategy");
|
|
9850
|
+
* const markdown = await service.getReport("my-strategy", true);
|
|
9796
9851
|
* console.log(markdown);
|
|
9797
9852
|
* // Output:
|
|
9798
9853
|
* // # Portfolio Heatmap: my-strategy
|
|
@@ -9806,11 +9861,12 @@ class HeatMarkdownService {
|
|
|
9806
9861
|
* // ...
|
|
9807
9862
|
* ```
|
|
9808
9863
|
*/
|
|
9809
|
-
this.getReport = async (strategyName, columns = COLUMN_CONFIG.heat_columns) => {
|
|
9864
|
+
this.getReport = async (strategyName, backtest, columns = COLUMN_CONFIG.heat_columns) => {
|
|
9810
9865
|
this.loggerService.log(HEATMAP_METHOD_NAME_GET_REPORT, {
|
|
9811
9866
|
strategyName,
|
|
9867
|
+
backtest,
|
|
9812
9868
|
});
|
|
9813
|
-
const storage = this.getStorage(strategyName);
|
|
9869
|
+
const storage = this.getStorage(strategyName, backtest);
|
|
9814
9870
|
return storage.getReport(strategyName, columns);
|
|
9815
9871
|
};
|
|
9816
9872
|
/**
|
|
@@ -9820,6 +9876,7 @@ class HeatMarkdownService {
|
|
|
9820
9876
|
* Default filename: {strategyName}.md
|
|
9821
9877
|
*
|
|
9822
9878
|
* @param strategyName - Strategy name to save heatmap report for
|
|
9879
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
9823
9880
|
* @param path - Optional directory path to save report (default: "./dump/heatmap")
|
|
9824
9881
|
* @param columns - Column configuration for formatting the table
|
|
9825
9882
|
*
|
|
@@ -9828,43 +9885,52 @@ class HeatMarkdownService {
|
|
|
9828
9885
|
* const service = new HeatMarkdownService();
|
|
9829
9886
|
*
|
|
9830
9887
|
* // Save to default path: ./dump/heatmap/my-strategy.md
|
|
9831
|
-
* await service.dump("my-strategy");
|
|
9888
|
+
* await service.dump("my-strategy", true);
|
|
9832
9889
|
*
|
|
9833
9890
|
* // Save to custom path: ./reports/my-strategy.md
|
|
9834
|
-
* await service.dump("my-strategy", "./reports");
|
|
9891
|
+
* await service.dump("my-strategy", true, "./reports");
|
|
9835
9892
|
* ```
|
|
9836
9893
|
*/
|
|
9837
|
-
this.dump = async (strategyName, path = "./dump/heatmap", columns = COLUMN_CONFIG.heat_columns) => {
|
|
9894
|
+
this.dump = async (strategyName, backtest, path = "./dump/heatmap", columns = COLUMN_CONFIG.heat_columns) => {
|
|
9838
9895
|
this.loggerService.log(HEATMAP_METHOD_NAME_DUMP, {
|
|
9839
9896
|
strategyName,
|
|
9897
|
+
backtest,
|
|
9840
9898
|
path,
|
|
9841
9899
|
});
|
|
9842
|
-
const storage = this.getStorage(strategyName);
|
|
9900
|
+
const storage = this.getStorage(strategyName, backtest);
|
|
9843
9901
|
await storage.dump(strategyName, path, columns);
|
|
9844
9902
|
};
|
|
9845
9903
|
/**
|
|
9846
9904
|
* Clears accumulated heatmap data from storage.
|
|
9847
|
-
* If
|
|
9848
|
-
* If
|
|
9905
|
+
* If ctx is provided, clears only that strategy+backtest combination's data.
|
|
9906
|
+
* If ctx is omitted, clears all data.
|
|
9849
9907
|
*
|
|
9850
|
-
* @param
|
|
9908
|
+
* @param backtest - Backtest mode flag
|
|
9909
|
+
* @param ctx - Optional context with strategyName to clear specific data
|
|
9851
9910
|
*
|
|
9852
9911
|
* @example
|
|
9853
9912
|
* ```typescript
|
|
9854
9913
|
* const service = new HeatMarkdownService();
|
|
9855
9914
|
*
|
|
9856
|
-
* // Clear specific strategy data
|
|
9857
|
-
* await service.clear("my-strategy");
|
|
9915
|
+
* // Clear specific strategy+backtest data
|
|
9916
|
+
* await service.clear(true, { strategyName: "my-strategy" });
|
|
9858
9917
|
*
|
|
9859
|
-
* // Clear all
|
|
9918
|
+
* // Clear all data
|
|
9860
9919
|
* await service.clear();
|
|
9861
9920
|
* ```
|
|
9862
9921
|
*/
|
|
9863
|
-
this.clear = async (
|
|
9922
|
+
this.clear = async (backtest, ctx) => {
|
|
9864
9923
|
this.loggerService.log(HEATMAP_METHOD_NAME_CLEAR, {
|
|
9865
|
-
|
|
9924
|
+
backtest,
|
|
9925
|
+
ctx,
|
|
9866
9926
|
});
|
|
9867
|
-
|
|
9927
|
+
if (ctx) {
|
|
9928
|
+
const key = `${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
9929
|
+
this.getStorage.clear(key);
|
|
9930
|
+
}
|
|
9931
|
+
else {
|
|
9932
|
+
this.getStorage.clear();
|
|
9933
|
+
}
|
|
9868
9934
|
};
|
|
9869
9935
|
/**
|
|
9870
9936
|
* Initializes the service by subscribing to signal events.
|
|
@@ -12433,10 +12499,10 @@ class PartialMarkdownService {
|
|
|
12433
12499
|
/** Logger service for debug output */
|
|
12434
12500
|
this.loggerService = inject(TYPES.loggerService);
|
|
12435
12501
|
/**
|
|
12436
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
12437
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
12502
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
12503
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
12438
12504
|
*/
|
|
12439
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$1());
|
|
12505
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$1());
|
|
12440
12506
|
/**
|
|
12441
12507
|
* Processes profit events and accumulates them.
|
|
12442
12508
|
* Should be called from partialProfitSubject subscription.
|
|
@@ -12453,7 +12519,7 @@ class PartialMarkdownService {
|
|
|
12453
12519
|
this.loggerService.log("partialMarkdownService tickProfit", {
|
|
12454
12520
|
data,
|
|
12455
12521
|
});
|
|
12456
|
-
const storage = this.getStorage(data.symbol, data.data.strategyName);
|
|
12522
|
+
const storage = this.getStorage(data.symbol, data.data.strategyName, data.backtest);
|
|
12457
12523
|
storage.addProfitEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
|
|
12458
12524
|
};
|
|
12459
12525
|
/**
|
|
@@ -12472,7 +12538,7 @@ class PartialMarkdownService {
|
|
|
12472
12538
|
this.loggerService.log("partialMarkdownService tickLoss", {
|
|
12473
12539
|
data,
|
|
12474
12540
|
});
|
|
12475
|
-
const storage = this.getStorage(data.symbol, data.data.strategyName);
|
|
12541
|
+
const storage = this.getStorage(data.symbol, data.data.strategyName, data.backtest);
|
|
12476
12542
|
storage.addLossEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
|
|
12477
12543
|
};
|
|
12478
12544
|
/**
|
|
@@ -12481,21 +12547,23 @@ class PartialMarkdownService {
|
|
|
12481
12547
|
*
|
|
12482
12548
|
* @param symbol - Trading pair symbol to get data for
|
|
12483
12549
|
* @param strategyName - Strategy name to get data for
|
|
12550
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
12484
12551
|
* @returns Statistical data object with all metrics
|
|
12485
12552
|
*
|
|
12486
12553
|
* @example
|
|
12487
12554
|
* ```typescript
|
|
12488
12555
|
* const service = new PartialMarkdownService();
|
|
12489
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
12556
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
12490
12557
|
* console.log(stats.totalProfit, stats.totalLoss);
|
|
12491
12558
|
* ```
|
|
12492
12559
|
*/
|
|
12493
|
-
this.getData = async (symbol, strategyName) => {
|
|
12560
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
12494
12561
|
this.loggerService.log("partialMarkdownService getData", {
|
|
12495
12562
|
symbol,
|
|
12496
12563
|
strategyName,
|
|
12564
|
+
backtest,
|
|
12497
12565
|
});
|
|
12498
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
12566
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
12499
12567
|
return storage.getData();
|
|
12500
12568
|
};
|
|
12501
12569
|
/**
|
|
@@ -12504,22 +12572,24 @@ class PartialMarkdownService {
|
|
|
12504
12572
|
*
|
|
12505
12573
|
* @param symbol - Trading pair symbol to generate report for
|
|
12506
12574
|
* @param strategyName - Strategy name to generate report for
|
|
12575
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
12507
12576
|
* @param columns - Column configuration for formatting the table
|
|
12508
12577
|
* @returns Markdown formatted report string with table of all events
|
|
12509
12578
|
*
|
|
12510
12579
|
* @example
|
|
12511
12580
|
* ```typescript
|
|
12512
12581
|
* const service = new PartialMarkdownService();
|
|
12513
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
12582
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
12514
12583
|
* console.log(markdown);
|
|
12515
12584
|
* ```
|
|
12516
12585
|
*/
|
|
12517
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.partial_columns) => {
|
|
12586
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.partial_columns) => {
|
|
12518
12587
|
this.loggerService.log("partialMarkdownService getReport", {
|
|
12519
12588
|
symbol,
|
|
12520
12589
|
strategyName,
|
|
12590
|
+
backtest,
|
|
12521
12591
|
});
|
|
12522
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
12592
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
12523
12593
|
return storage.getReport(symbol, strategyName, columns);
|
|
12524
12594
|
};
|
|
12525
12595
|
/**
|
|
@@ -12529,6 +12599,7 @@ class PartialMarkdownService {
|
|
|
12529
12599
|
*
|
|
12530
12600
|
* @param symbol - Trading pair symbol to save report for
|
|
12531
12601
|
* @param strategyName - Strategy name to save report for
|
|
12602
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
12532
12603
|
* @param path - Directory path to save report (default: "./dump/partial")
|
|
12533
12604
|
* @param columns - Column configuration for formatting the table
|
|
12534
12605
|
*
|
|
@@ -12537,45 +12608,48 @@ class PartialMarkdownService {
|
|
|
12537
12608
|
* const service = new PartialMarkdownService();
|
|
12538
12609
|
*
|
|
12539
12610
|
* // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
|
|
12540
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
12611
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
12541
12612
|
*
|
|
12542
12613
|
* // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
|
|
12543
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
12614
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
12544
12615
|
* ```
|
|
12545
12616
|
*/
|
|
12546
|
-
this.dump = async (symbol, strategyName, path = "./dump/partial", columns = COLUMN_CONFIG.partial_columns) => {
|
|
12617
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/partial", columns = COLUMN_CONFIG.partial_columns) => {
|
|
12547
12618
|
this.loggerService.log("partialMarkdownService dump", {
|
|
12548
12619
|
symbol,
|
|
12549
12620
|
strategyName,
|
|
12621
|
+
backtest,
|
|
12550
12622
|
path,
|
|
12551
12623
|
});
|
|
12552
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
12624
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
12553
12625
|
await storage.dump(symbol, strategyName, path, columns);
|
|
12554
12626
|
};
|
|
12555
12627
|
/**
|
|
12556
12628
|
* Clears accumulated event data from storage.
|
|
12557
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
12629
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
12558
12630
|
* If nothing is provided, clears all data.
|
|
12559
12631
|
*
|
|
12632
|
+
* @param backtest - Backtest mode flag
|
|
12560
12633
|
* @param ctx - Optional context with symbol and strategyName
|
|
12561
12634
|
*
|
|
12562
12635
|
* @example
|
|
12563
12636
|
* ```typescript
|
|
12564
12637
|
* const service = new PartialMarkdownService();
|
|
12565
12638
|
*
|
|
12566
|
-
* // Clear specific symbol-strategy
|
|
12567
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
12639
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
12640
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
12568
12641
|
*
|
|
12569
12642
|
* // Clear all data
|
|
12570
12643
|
* await service.clear();
|
|
12571
12644
|
* ```
|
|
12572
12645
|
*/
|
|
12573
|
-
this.clear = async (ctx) => {
|
|
12646
|
+
this.clear = async (backtest, ctx) => {
|
|
12574
12647
|
this.loggerService.log("partialMarkdownService clear", {
|
|
12648
|
+
backtest,
|
|
12575
12649
|
ctx,
|
|
12576
12650
|
});
|
|
12577
12651
|
if (ctx) {
|
|
12578
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
12652
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
12579
12653
|
this.getStorage.clear(key);
|
|
12580
12654
|
}
|
|
12581
12655
|
else {
|
|
@@ -13151,10 +13225,10 @@ class RiskMarkdownService {
|
|
|
13151
13225
|
/** Logger service for debug output */
|
|
13152
13226
|
this.loggerService = inject(TYPES.loggerService);
|
|
13153
13227
|
/**
|
|
13154
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
13155
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
13228
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
13229
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
13156
13230
|
*/
|
|
13157
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage());
|
|
13231
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage());
|
|
13158
13232
|
/**
|
|
13159
13233
|
* Processes risk rejection events and accumulates them.
|
|
13160
13234
|
* Should be called from riskSubject subscription.
|
|
@@ -13171,7 +13245,7 @@ class RiskMarkdownService {
|
|
|
13171
13245
|
this.loggerService.log("riskMarkdownService tickRejection", {
|
|
13172
13246
|
data,
|
|
13173
13247
|
});
|
|
13174
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
13248
|
+
const storage = this.getStorage(data.symbol, data.strategyName, data.backtest);
|
|
13175
13249
|
storage.addRejectionEvent(data);
|
|
13176
13250
|
};
|
|
13177
13251
|
/**
|
|
@@ -13180,21 +13254,23 @@ class RiskMarkdownService {
|
|
|
13180
13254
|
*
|
|
13181
13255
|
* @param symbol - Trading pair symbol to get data for
|
|
13182
13256
|
* @param strategyName - Strategy name to get data for
|
|
13257
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
13183
13258
|
* @returns Statistical data object with all metrics
|
|
13184
13259
|
*
|
|
13185
13260
|
* @example
|
|
13186
13261
|
* ```typescript
|
|
13187
13262
|
* const service = new RiskMarkdownService();
|
|
13188
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
13263
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
13189
13264
|
* console.log(stats.totalRejections, stats.bySymbol);
|
|
13190
13265
|
* ```
|
|
13191
13266
|
*/
|
|
13192
|
-
this.getData = async (symbol, strategyName) => {
|
|
13267
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
13193
13268
|
this.loggerService.log("riskMarkdownService getData", {
|
|
13194
13269
|
symbol,
|
|
13195
13270
|
strategyName,
|
|
13271
|
+
backtest,
|
|
13196
13272
|
});
|
|
13197
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
13273
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
13198
13274
|
return storage.getData();
|
|
13199
13275
|
};
|
|
13200
13276
|
/**
|
|
@@ -13203,22 +13279,24 @@ class RiskMarkdownService {
|
|
|
13203
13279
|
*
|
|
13204
13280
|
* @param symbol - Trading pair symbol to generate report for
|
|
13205
13281
|
* @param strategyName - Strategy name to generate report for
|
|
13282
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
13206
13283
|
* @param columns - Column configuration for formatting the table
|
|
13207
13284
|
* @returns Markdown formatted report string with table of all events
|
|
13208
13285
|
*
|
|
13209
13286
|
* @example
|
|
13210
13287
|
* ```typescript
|
|
13211
13288
|
* const service = new RiskMarkdownService();
|
|
13212
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
13289
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
13213
13290
|
* console.log(markdown);
|
|
13214
13291
|
* ```
|
|
13215
13292
|
*/
|
|
13216
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.risk_columns) => {
|
|
13293
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.risk_columns) => {
|
|
13217
13294
|
this.loggerService.log("riskMarkdownService getReport", {
|
|
13218
13295
|
symbol,
|
|
13219
13296
|
strategyName,
|
|
13297
|
+
backtest,
|
|
13220
13298
|
});
|
|
13221
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
13299
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
13222
13300
|
return storage.getReport(symbol, strategyName, columns);
|
|
13223
13301
|
};
|
|
13224
13302
|
/**
|
|
@@ -13228,6 +13306,7 @@ class RiskMarkdownService {
|
|
|
13228
13306
|
*
|
|
13229
13307
|
* @param symbol - Trading pair symbol to save report for
|
|
13230
13308
|
* @param strategyName - Strategy name to save report for
|
|
13309
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
13231
13310
|
* @param path - Directory path to save report (default: "./dump/risk")
|
|
13232
13311
|
* @param columns - Column configuration for formatting the table
|
|
13233
13312
|
*
|
|
@@ -13236,45 +13315,48 @@ class RiskMarkdownService {
|
|
|
13236
13315
|
* const service = new RiskMarkdownService();
|
|
13237
13316
|
*
|
|
13238
13317
|
* // Save to default path: ./dump/risk/BTCUSDT_my-strategy.md
|
|
13239
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
13318
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
13240
13319
|
*
|
|
13241
13320
|
* // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
|
|
13242
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
13321
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
13243
13322
|
* ```
|
|
13244
13323
|
*/
|
|
13245
|
-
this.dump = async (symbol, strategyName, path = "./dump/risk", columns = COLUMN_CONFIG.risk_columns) => {
|
|
13324
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/risk", columns = COLUMN_CONFIG.risk_columns) => {
|
|
13246
13325
|
this.loggerService.log("riskMarkdownService dump", {
|
|
13247
13326
|
symbol,
|
|
13248
13327
|
strategyName,
|
|
13328
|
+
backtest,
|
|
13249
13329
|
path,
|
|
13250
13330
|
});
|
|
13251
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
13331
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
13252
13332
|
await storage.dump(symbol, strategyName, path, columns);
|
|
13253
13333
|
};
|
|
13254
13334
|
/**
|
|
13255
13335
|
* Clears accumulated event data from storage.
|
|
13256
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
13336
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
13257
13337
|
* If nothing is provided, clears all data.
|
|
13258
13338
|
*
|
|
13339
|
+
* @param backtest - Backtest mode flag
|
|
13259
13340
|
* @param ctx - Optional context with symbol and strategyName
|
|
13260
13341
|
*
|
|
13261
13342
|
* @example
|
|
13262
13343
|
* ```typescript
|
|
13263
13344
|
* const service = new RiskMarkdownService();
|
|
13264
13345
|
*
|
|
13265
|
-
* // Clear specific symbol-strategy
|
|
13266
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
13346
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
13347
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
13267
13348
|
*
|
|
13268
13349
|
* // Clear all data
|
|
13269
13350
|
* await service.clear();
|
|
13270
13351
|
* ```
|
|
13271
13352
|
*/
|
|
13272
|
-
this.clear = async (ctx) => {
|
|
13353
|
+
this.clear = async (backtest, ctx) => {
|
|
13273
13354
|
this.loggerService.log("riskMarkdownService clear", {
|
|
13355
|
+
backtest,
|
|
13274
13356
|
ctx,
|
|
13275
13357
|
});
|
|
13276
13358
|
if (ctx) {
|
|
13277
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
13359
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
13278
13360
|
this.getStorage.clear(key);
|
|
13279
13361
|
}
|
|
13280
13362
|
else {
|
|
@@ -13579,7 +13661,7 @@ const backtest = {
|
|
|
13579
13661
|
...templateServices,
|
|
13580
13662
|
};
|
|
13581
13663
|
init();
|
|
13582
|
-
var
|
|
13664
|
+
var bt = backtest;
|
|
13583
13665
|
|
|
13584
13666
|
/**
|
|
13585
13667
|
* Sets custom logger implementation for the framework.
|
|
@@ -13599,7 +13681,7 @@ var backtest$1 = backtest;
|
|
|
13599
13681
|
* ```
|
|
13600
13682
|
*/
|
|
13601
13683
|
function setLogger(logger) {
|
|
13602
|
-
|
|
13684
|
+
bt.loggerService.setLogger(logger);
|
|
13603
13685
|
}
|
|
13604
13686
|
/**
|
|
13605
13687
|
* Sets global configuration parameters for the framework.
|
|
@@ -13617,7 +13699,7 @@ function setConfig(config, _unsafe) {
|
|
|
13617
13699
|
const prevConfig = Object.assign({}, GLOBAL_CONFIG);
|
|
13618
13700
|
try {
|
|
13619
13701
|
Object.assign(GLOBAL_CONFIG, config);
|
|
13620
|
-
!_unsafe &&
|
|
13702
|
+
!_unsafe && bt.configValidationService.validate();
|
|
13621
13703
|
}
|
|
13622
13704
|
catch (error) {
|
|
13623
13705
|
console.warn(`backtest-kit setConfig failed: ${functoolsKit.getErrorMessage(error)}`, config);
|
|
@@ -13688,7 +13770,7 @@ function setColumns(columns, _unsafe) {
|
|
|
13688
13770
|
const prevConfig = Object.assign({}, COLUMN_CONFIG);
|
|
13689
13771
|
try {
|
|
13690
13772
|
Object.assign(COLUMN_CONFIG, columns);
|
|
13691
|
-
!_unsafe &&
|
|
13773
|
+
!_unsafe && bt.columnValidationService.validate();
|
|
13692
13774
|
}
|
|
13693
13775
|
catch (error) {
|
|
13694
13776
|
console.warn(`backtest-kit setColumns failed: ${functoolsKit.getErrorMessage(error)}`, columns);
|
|
@@ -13773,11 +13855,11 @@ const ADD_OPTIMIZER_METHOD_NAME = "add.addOptimizer";
|
|
|
13773
13855
|
* ```
|
|
13774
13856
|
*/
|
|
13775
13857
|
function addStrategy(strategySchema) {
|
|
13776
|
-
|
|
13858
|
+
bt.loggerService.info(ADD_STRATEGY_METHOD_NAME, {
|
|
13777
13859
|
strategySchema,
|
|
13778
13860
|
});
|
|
13779
|
-
|
|
13780
|
-
|
|
13861
|
+
bt.strategyValidationService.addStrategy(strategySchema.strategyName, strategySchema);
|
|
13862
|
+
bt.strategySchemaService.register(strategySchema.strategyName, strategySchema);
|
|
13781
13863
|
}
|
|
13782
13864
|
/**
|
|
13783
13865
|
* Registers an exchange data source in the framework.
|
|
@@ -13815,11 +13897,11 @@ function addStrategy(strategySchema) {
|
|
|
13815
13897
|
* ```
|
|
13816
13898
|
*/
|
|
13817
13899
|
function addExchange(exchangeSchema) {
|
|
13818
|
-
|
|
13900
|
+
bt.loggerService.info(ADD_EXCHANGE_METHOD_NAME, {
|
|
13819
13901
|
exchangeSchema,
|
|
13820
13902
|
});
|
|
13821
|
-
|
|
13822
|
-
|
|
13903
|
+
bt.exchangeValidationService.addExchange(exchangeSchema.exchangeName, exchangeSchema);
|
|
13904
|
+
bt.exchangeSchemaService.register(exchangeSchema.exchangeName, exchangeSchema);
|
|
13823
13905
|
}
|
|
13824
13906
|
/**
|
|
13825
13907
|
* Registers a timeframe generator for backtesting.
|
|
@@ -13852,11 +13934,11 @@ function addExchange(exchangeSchema) {
|
|
|
13852
13934
|
* ```
|
|
13853
13935
|
*/
|
|
13854
13936
|
function addFrame(frameSchema) {
|
|
13855
|
-
|
|
13937
|
+
bt.loggerService.info(ADD_FRAME_METHOD_NAME, {
|
|
13856
13938
|
frameSchema,
|
|
13857
13939
|
});
|
|
13858
|
-
|
|
13859
|
-
|
|
13940
|
+
bt.frameValidationService.addFrame(frameSchema.frameName, frameSchema);
|
|
13941
|
+
bt.frameSchemaService.register(frameSchema.frameName, frameSchema);
|
|
13860
13942
|
}
|
|
13861
13943
|
/**
|
|
13862
13944
|
* Registers a walker for strategy comparison.
|
|
@@ -13896,11 +13978,11 @@ function addFrame(frameSchema) {
|
|
|
13896
13978
|
* ```
|
|
13897
13979
|
*/
|
|
13898
13980
|
function addWalker(walkerSchema) {
|
|
13899
|
-
|
|
13981
|
+
bt.loggerService.info(ADD_WALKER_METHOD_NAME, {
|
|
13900
13982
|
walkerSchema,
|
|
13901
13983
|
});
|
|
13902
|
-
|
|
13903
|
-
|
|
13984
|
+
bt.walkerValidationService.addWalker(walkerSchema.walkerName, walkerSchema);
|
|
13985
|
+
bt.walkerSchemaService.register(walkerSchema.walkerName, walkerSchema);
|
|
13904
13986
|
}
|
|
13905
13987
|
/**
|
|
13906
13988
|
* Registers a position sizing configuration in the framework.
|
|
@@ -13955,11 +14037,11 @@ function addWalker(walkerSchema) {
|
|
|
13955
14037
|
* ```
|
|
13956
14038
|
*/
|
|
13957
14039
|
function addSizing(sizingSchema) {
|
|
13958
|
-
|
|
14040
|
+
bt.loggerService.info(ADD_SIZING_METHOD_NAME, {
|
|
13959
14041
|
sizingSchema,
|
|
13960
14042
|
});
|
|
13961
|
-
|
|
13962
|
-
|
|
14043
|
+
bt.sizingValidationService.addSizing(sizingSchema.sizingName, sizingSchema);
|
|
14044
|
+
bt.sizingSchemaService.register(sizingSchema.sizingName, sizingSchema);
|
|
13963
14045
|
}
|
|
13964
14046
|
/**
|
|
13965
14047
|
* Registers a risk management configuration in the framework.
|
|
@@ -14023,11 +14105,11 @@ function addSizing(sizingSchema) {
|
|
|
14023
14105
|
* ```
|
|
14024
14106
|
*/
|
|
14025
14107
|
function addRisk(riskSchema) {
|
|
14026
|
-
|
|
14108
|
+
bt.loggerService.info(ADD_RISK_METHOD_NAME, {
|
|
14027
14109
|
riskSchema,
|
|
14028
14110
|
});
|
|
14029
|
-
|
|
14030
|
-
|
|
14111
|
+
bt.riskValidationService.addRisk(riskSchema.riskName, riskSchema);
|
|
14112
|
+
bt.riskSchemaService.register(riskSchema.riskName, riskSchema);
|
|
14031
14113
|
}
|
|
14032
14114
|
/**
|
|
14033
14115
|
* Registers an optimizer configuration in the framework.
|
|
@@ -14117,11 +14199,11 @@ function addRisk(riskSchema) {
|
|
|
14117
14199
|
* ```
|
|
14118
14200
|
*/
|
|
14119
14201
|
function addOptimizer(optimizerSchema) {
|
|
14120
|
-
|
|
14202
|
+
bt.loggerService.info(ADD_OPTIMIZER_METHOD_NAME, {
|
|
14121
14203
|
optimizerSchema,
|
|
14122
14204
|
});
|
|
14123
|
-
|
|
14124
|
-
|
|
14205
|
+
bt.optimizerValidationService.addOptimizer(optimizerSchema.optimizerName, optimizerSchema);
|
|
14206
|
+
bt.optimizerSchemaService.register(optimizerSchema.optimizerName, optimizerSchema);
|
|
14125
14207
|
}
|
|
14126
14208
|
|
|
14127
14209
|
const LIST_EXCHANGES_METHOD_NAME = "list.listExchanges";
|
|
@@ -14157,8 +14239,8 @@ const LIST_OPTIMIZERS_METHOD_NAME = "list.listOptimizers";
|
|
|
14157
14239
|
* ```
|
|
14158
14240
|
*/
|
|
14159
14241
|
async function listExchanges() {
|
|
14160
|
-
|
|
14161
|
-
return await
|
|
14242
|
+
bt.loggerService.log(LIST_EXCHANGES_METHOD_NAME);
|
|
14243
|
+
return await bt.exchangeValidationService.list();
|
|
14162
14244
|
}
|
|
14163
14245
|
/**
|
|
14164
14246
|
* Returns a list of all registered strategy schemas.
|
|
@@ -14191,8 +14273,8 @@ async function listExchanges() {
|
|
|
14191
14273
|
* ```
|
|
14192
14274
|
*/
|
|
14193
14275
|
async function listStrategies() {
|
|
14194
|
-
|
|
14195
|
-
return await
|
|
14276
|
+
bt.loggerService.log(LIST_STRATEGIES_METHOD_NAME);
|
|
14277
|
+
return await bt.strategyValidationService.list();
|
|
14196
14278
|
}
|
|
14197
14279
|
/**
|
|
14198
14280
|
* Returns a list of all registered frame schemas.
|
|
@@ -14220,8 +14302,8 @@ async function listStrategies() {
|
|
|
14220
14302
|
* ```
|
|
14221
14303
|
*/
|
|
14222
14304
|
async function listFrames() {
|
|
14223
|
-
|
|
14224
|
-
return await
|
|
14305
|
+
bt.loggerService.log(LIST_FRAMES_METHOD_NAME);
|
|
14306
|
+
return await bt.frameValidationService.list();
|
|
14225
14307
|
}
|
|
14226
14308
|
/**
|
|
14227
14309
|
* Returns a list of all registered walker schemas.
|
|
@@ -14250,8 +14332,8 @@ async function listFrames() {
|
|
|
14250
14332
|
* ```
|
|
14251
14333
|
*/
|
|
14252
14334
|
async function listWalkers() {
|
|
14253
|
-
|
|
14254
|
-
return await
|
|
14335
|
+
bt.loggerService.log(LIST_WALKERS_METHOD_NAME);
|
|
14336
|
+
return await bt.walkerValidationService.list();
|
|
14255
14337
|
}
|
|
14256
14338
|
/**
|
|
14257
14339
|
* Returns a list of all registered sizing schemas.
|
|
@@ -14289,8 +14371,8 @@ async function listWalkers() {
|
|
|
14289
14371
|
* ```
|
|
14290
14372
|
*/
|
|
14291
14373
|
async function listSizings() {
|
|
14292
|
-
|
|
14293
|
-
return await
|
|
14374
|
+
bt.loggerService.log(LIST_SIZINGS_METHOD_NAME);
|
|
14375
|
+
return await bt.sizingValidationService.list();
|
|
14294
14376
|
}
|
|
14295
14377
|
/**
|
|
14296
14378
|
* Returns a list of all registered risk schemas.
|
|
@@ -14325,8 +14407,8 @@ async function listSizings() {
|
|
|
14325
14407
|
* ```
|
|
14326
14408
|
*/
|
|
14327
14409
|
async function listRisks() {
|
|
14328
|
-
|
|
14329
|
-
return await
|
|
14410
|
+
bt.loggerService.log(LIST_RISKS_METHOD_NAME);
|
|
14411
|
+
return await bt.riskValidationService.list();
|
|
14330
14412
|
}
|
|
14331
14413
|
/**
|
|
14332
14414
|
* Returns a list of all registered optimizer schemas.
|
|
@@ -14365,8 +14447,8 @@ async function listRisks() {
|
|
|
14365
14447
|
* ```
|
|
14366
14448
|
*/
|
|
14367
14449
|
async function listOptimizers() {
|
|
14368
|
-
|
|
14369
|
-
return await
|
|
14450
|
+
bt.loggerService.log(LIST_OPTIMIZERS_METHOD_NAME);
|
|
14451
|
+
return await bt.optimizerValidationService.list();
|
|
14370
14452
|
}
|
|
14371
14453
|
|
|
14372
14454
|
const LISTEN_SIGNAL_METHOD_NAME = "event.listenSignal";
|
|
@@ -14423,7 +14505,7 @@ const LISTEN_RISK_ONCE_METHOD_NAME = "event.listenRiskOnce";
|
|
|
14423
14505
|
* ```
|
|
14424
14506
|
*/
|
|
14425
14507
|
function listenSignal(fn) {
|
|
14426
|
-
|
|
14508
|
+
bt.loggerService.log(LISTEN_SIGNAL_METHOD_NAME);
|
|
14427
14509
|
return signalEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14428
14510
|
}
|
|
14429
14511
|
/**
|
|
@@ -14459,7 +14541,7 @@ function listenSignal(fn) {
|
|
|
14459
14541
|
* ```
|
|
14460
14542
|
*/
|
|
14461
14543
|
function listenSignalOnce(filterFn, fn) {
|
|
14462
|
-
|
|
14544
|
+
bt.loggerService.log(LISTEN_SIGNAL_ONCE_METHOD_NAME);
|
|
14463
14545
|
return signalEmitter.filter(filterFn).once(fn);
|
|
14464
14546
|
}
|
|
14465
14547
|
/**
|
|
@@ -14483,7 +14565,7 @@ function listenSignalOnce(filterFn, fn) {
|
|
|
14483
14565
|
* ```
|
|
14484
14566
|
*/
|
|
14485
14567
|
function listenSignalLive(fn) {
|
|
14486
|
-
|
|
14568
|
+
bt.loggerService.log(LISTEN_SIGNAL_LIVE_METHOD_NAME);
|
|
14487
14569
|
return signalLiveEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14488
14570
|
}
|
|
14489
14571
|
/**
|
|
@@ -14508,7 +14590,7 @@ function listenSignalLive(fn) {
|
|
|
14508
14590
|
* ```
|
|
14509
14591
|
*/
|
|
14510
14592
|
function listenSignalLiveOnce(filterFn, fn) {
|
|
14511
|
-
|
|
14593
|
+
bt.loggerService.log(LISTEN_SIGNAL_LIVE_ONCE_METHOD_NAME);
|
|
14512
14594
|
return signalLiveEmitter.filter(filterFn).once(fn);
|
|
14513
14595
|
}
|
|
14514
14596
|
/**
|
|
@@ -14532,7 +14614,7 @@ function listenSignalLiveOnce(filterFn, fn) {
|
|
|
14532
14614
|
* ```
|
|
14533
14615
|
*/
|
|
14534
14616
|
function listenSignalBacktest(fn) {
|
|
14535
|
-
|
|
14617
|
+
bt.loggerService.log(LISTEN_SIGNAL_BACKTEST_METHOD_NAME);
|
|
14536
14618
|
return signalBacktestEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14537
14619
|
}
|
|
14538
14620
|
/**
|
|
@@ -14557,7 +14639,7 @@ function listenSignalBacktest(fn) {
|
|
|
14557
14639
|
* ```
|
|
14558
14640
|
*/
|
|
14559
14641
|
function listenSignalBacktestOnce(filterFn, fn) {
|
|
14560
|
-
|
|
14642
|
+
bt.loggerService.log(LISTEN_SIGNAL_BACKTEST_ONCE_METHOD_NAME);
|
|
14561
14643
|
return signalBacktestEmitter.filter(filterFn).once(fn);
|
|
14562
14644
|
}
|
|
14563
14645
|
/**
|
|
@@ -14585,7 +14667,7 @@ function listenSignalBacktestOnce(filterFn, fn) {
|
|
|
14585
14667
|
* ```
|
|
14586
14668
|
*/
|
|
14587
14669
|
function listenError(fn) {
|
|
14588
|
-
|
|
14670
|
+
bt.loggerService.log(LISTEN_ERROR_METHOD_NAME);
|
|
14589
14671
|
return errorEmitter.subscribe(functoolsKit.queued(async (error) => fn(error)));
|
|
14590
14672
|
}
|
|
14591
14673
|
/**
|
|
@@ -14613,7 +14695,7 @@ function listenError(fn) {
|
|
|
14613
14695
|
* ```
|
|
14614
14696
|
*/
|
|
14615
14697
|
function listenExit(fn) {
|
|
14616
|
-
|
|
14698
|
+
bt.loggerService.log(LISTEN_EXIT_METHOD_NAME);
|
|
14617
14699
|
return exitEmitter.subscribe(functoolsKit.queued(async (error) => fn(error)));
|
|
14618
14700
|
}
|
|
14619
14701
|
/**
|
|
@@ -14644,7 +14726,7 @@ function listenExit(fn) {
|
|
|
14644
14726
|
* ```
|
|
14645
14727
|
*/
|
|
14646
14728
|
function listenDoneLive(fn) {
|
|
14647
|
-
|
|
14729
|
+
bt.loggerService.log(LISTEN_DONE_LIVE_METHOD_NAME);
|
|
14648
14730
|
return doneLiveSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14649
14731
|
}
|
|
14650
14732
|
/**
|
|
@@ -14674,7 +14756,7 @@ function listenDoneLive(fn) {
|
|
|
14674
14756
|
* ```
|
|
14675
14757
|
*/
|
|
14676
14758
|
function listenDoneLiveOnce(filterFn, fn) {
|
|
14677
|
-
|
|
14759
|
+
bt.loggerService.log(LISTEN_DONE_LIVE_ONCE_METHOD_NAME);
|
|
14678
14760
|
return doneLiveSubject.filter(filterFn).once(fn);
|
|
14679
14761
|
}
|
|
14680
14762
|
/**
|
|
@@ -14706,7 +14788,7 @@ function listenDoneLiveOnce(filterFn, fn) {
|
|
|
14706
14788
|
* ```
|
|
14707
14789
|
*/
|
|
14708
14790
|
function listenDoneBacktest(fn) {
|
|
14709
|
-
|
|
14791
|
+
bt.loggerService.log(LISTEN_DONE_BACKTEST_METHOD_NAME);
|
|
14710
14792
|
return doneBacktestSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14711
14793
|
}
|
|
14712
14794
|
/**
|
|
@@ -14737,7 +14819,7 @@ function listenDoneBacktest(fn) {
|
|
|
14737
14819
|
* ```
|
|
14738
14820
|
*/
|
|
14739
14821
|
function listenDoneBacktestOnce(filterFn, fn) {
|
|
14740
|
-
|
|
14822
|
+
bt.loggerService.log(LISTEN_DONE_BACKTEST_ONCE_METHOD_NAME);
|
|
14741
14823
|
return doneBacktestSubject.filter(filterFn).once(fn);
|
|
14742
14824
|
}
|
|
14743
14825
|
/**
|
|
@@ -14767,7 +14849,7 @@ function listenDoneBacktestOnce(filterFn, fn) {
|
|
|
14767
14849
|
* ```
|
|
14768
14850
|
*/
|
|
14769
14851
|
function listenDoneWalker(fn) {
|
|
14770
|
-
|
|
14852
|
+
bt.loggerService.log(LISTEN_DONE_WALKER_METHOD_NAME);
|
|
14771
14853
|
return doneWalkerSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14772
14854
|
}
|
|
14773
14855
|
/**
|
|
@@ -14796,7 +14878,7 @@ function listenDoneWalker(fn) {
|
|
|
14796
14878
|
* ```
|
|
14797
14879
|
*/
|
|
14798
14880
|
function listenDoneWalkerOnce(filterFn, fn) {
|
|
14799
|
-
|
|
14881
|
+
bt.loggerService.log(LISTEN_DONE_WALKER_ONCE_METHOD_NAME);
|
|
14800
14882
|
return doneWalkerSubject.filter(filterFn).once(fn);
|
|
14801
14883
|
}
|
|
14802
14884
|
/**
|
|
@@ -14830,7 +14912,7 @@ function listenDoneWalkerOnce(filterFn, fn) {
|
|
|
14830
14912
|
* ```
|
|
14831
14913
|
*/
|
|
14832
14914
|
function listenBacktestProgress(fn) {
|
|
14833
|
-
|
|
14915
|
+
bt.loggerService.log(LISTEN_PROGRESS_METHOD_NAME);
|
|
14834
14916
|
return progressBacktestEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14835
14917
|
}
|
|
14836
14918
|
/**
|
|
@@ -14864,7 +14946,7 @@ function listenBacktestProgress(fn) {
|
|
|
14864
14946
|
* ```
|
|
14865
14947
|
*/
|
|
14866
14948
|
function listenWalkerProgress(fn) {
|
|
14867
|
-
|
|
14949
|
+
bt.loggerService.log(LISTEN_PROGRESS_WALKER_METHOD_NAME);
|
|
14868
14950
|
return progressWalkerEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14869
14951
|
}
|
|
14870
14952
|
/**
|
|
@@ -14892,7 +14974,7 @@ function listenWalkerProgress(fn) {
|
|
|
14892
14974
|
* ```
|
|
14893
14975
|
*/
|
|
14894
14976
|
function listenOptimizerProgress(fn) {
|
|
14895
|
-
|
|
14977
|
+
bt.loggerService.log(LISTEN_PROGRESS_OPTIMIZER_METHOD_NAME);
|
|
14896
14978
|
return progressOptimizerEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14897
14979
|
}
|
|
14898
14980
|
/**
|
|
@@ -14928,7 +15010,7 @@ function listenOptimizerProgress(fn) {
|
|
|
14928
15010
|
* ```
|
|
14929
15011
|
*/
|
|
14930
15012
|
function listenPerformance(fn) {
|
|
14931
|
-
|
|
15013
|
+
bt.loggerService.log(LISTEN_PERFORMANCE_METHOD_NAME);
|
|
14932
15014
|
return performanceEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14933
15015
|
}
|
|
14934
15016
|
/**
|
|
@@ -14962,7 +15044,7 @@ function listenPerformance(fn) {
|
|
|
14962
15044
|
* ```
|
|
14963
15045
|
*/
|
|
14964
15046
|
function listenWalker(fn) {
|
|
14965
|
-
|
|
15047
|
+
bt.loggerService.log(LISTEN_WALKER_METHOD_NAME);
|
|
14966
15048
|
return walkerEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14967
15049
|
}
|
|
14968
15050
|
/**
|
|
@@ -15005,7 +15087,7 @@ function listenWalker(fn) {
|
|
|
15005
15087
|
* ```
|
|
15006
15088
|
*/
|
|
15007
15089
|
function listenWalkerOnce(filterFn, fn) {
|
|
15008
|
-
|
|
15090
|
+
bt.loggerService.log(LISTEN_WALKER_ONCE_METHOD_NAME);
|
|
15009
15091
|
return walkerEmitter.filter(filterFn).once(fn);
|
|
15010
15092
|
}
|
|
15011
15093
|
/**
|
|
@@ -15040,7 +15122,7 @@ function listenWalkerOnce(filterFn, fn) {
|
|
|
15040
15122
|
* ```
|
|
15041
15123
|
*/
|
|
15042
15124
|
function listenWalkerComplete(fn) {
|
|
15043
|
-
|
|
15125
|
+
bt.loggerService.log(LISTEN_WALKER_COMPLETE_METHOD_NAME);
|
|
15044
15126
|
return walkerCompleteSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
15045
15127
|
}
|
|
15046
15128
|
/**
|
|
@@ -15068,7 +15150,7 @@ function listenWalkerComplete(fn) {
|
|
|
15068
15150
|
* ```
|
|
15069
15151
|
*/
|
|
15070
15152
|
function listenValidation(fn) {
|
|
15071
|
-
|
|
15153
|
+
bt.loggerService.log(LISTEN_VALIDATION_METHOD_NAME);
|
|
15072
15154
|
return validationSubject.subscribe(functoolsKit.queued(async (error) => fn(error)));
|
|
15073
15155
|
}
|
|
15074
15156
|
/**
|
|
@@ -15096,7 +15178,7 @@ function listenValidation(fn) {
|
|
|
15096
15178
|
* ```
|
|
15097
15179
|
*/
|
|
15098
15180
|
function listenPartialProfit(fn) {
|
|
15099
|
-
|
|
15181
|
+
bt.loggerService.log(LISTEN_PARTIAL_PROFIT_METHOD_NAME);
|
|
15100
15182
|
return partialProfitSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
15101
15183
|
}
|
|
15102
15184
|
/**
|
|
@@ -15130,7 +15212,7 @@ function listenPartialProfit(fn) {
|
|
|
15130
15212
|
* ```
|
|
15131
15213
|
*/
|
|
15132
15214
|
function listenPartialProfitOnce(filterFn, fn) {
|
|
15133
|
-
|
|
15215
|
+
bt.loggerService.log(LISTEN_PARTIAL_PROFIT_ONCE_METHOD_NAME);
|
|
15134
15216
|
return partialProfitSubject.filter(filterFn).once(fn);
|
|
15135
15217
|
}
|
|
15136
15218
|
/**
|
|
@@ -15158,7 +15240,7 @@ function listenPartialProfitOnce(filterFn, fn) {
|
|
|
15158
15240
|
* ```
|
|
15159
15241
|
*/
|
|
15160
15242
|
function listenPartialLoss(fn) {
|
|
15161
|
-
|
|
15243
|
+
bt.loggerService.log(LISTEN_PARTIAL_LOSS_METHOD_NAME);
|
|
15162
15244
|
return partialLossSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
15163
15245
|
}
|
|
15164
15246
|
/**
|
|
@@ -15192,7 +15274,7 @@ function listenPartialLoss(fn) {
|
|
|
15192
15274
|
* ```
|
|
15193
15275
|
*/
|
|
15194
15276
|
function listenPartialLossOnce(filterFn, fn) {
|
|
15195
|
-
|
|
15277
|
+
bt.loggerService.log(LISTEN_PARTIAL_LOSS_ONCE_METHOD_NAME);
|
|
15196
15278
|
return partialLossSubject.filter(filterFn).once(fn);
|
|
15197
15279
|
}
|
|
15198
15280
|
/**
|
|
@@ -15224,7 +15306,7 @@ function listenPartialLossOnce(filterFn, fn) {
|
|
|
15224
15306
|
* ```
|
|
15225
15307
|
*/
|
|
15226
15308
|
function listenRisk(fn) {
|
|
15227
|
-
|
|
15309
|
+
bt.loggerService.log(LISTEN_RISK_METHOD_NAME);
|
|
15228
15310
|
return riskSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
15229
15311
|
}
|
|
15230
15312
|
/**
|
|
@@ -15261,7 +15343,7 @@ function listenRisk(fn) {
|
|
|
15261
15343
|
* ```
|
|
15262
15344
|
*/
|
|
15263
15345
|
function listenRiskOnce(filterFn, fn) {
|
|
15264
|
-
|
|
15346
|
+
bt.loggerService.log(LISTEN_RISK_ONCE_METHOD_NAME);
|
|
15265
15347
|
return riskSubject.filter(filterFn).once(fn);
|
|
15266
15348
|
}
|
|
15267
15349
|
|
|
@@ -15289,12 +15371,12 @@ const GET_MODE_METHOD_NAME = "exchange.getMode";
|
|
|
15289
15371
|
* ```
|
|
15290
15372
|
*/
|
|
15291
15373
|
async function getCandles(symbol, interval, limit) {
|
|
15292
|
-
|
|
15374
|
+
bt.loggerService.info(GET_CANDLES_METHOD_NAME, {
|
|
15293
15375
|
symbol,
|
|
15294
15376
|
interval,
|
|
15295
15377
|
limit,
|
|
15296
15378
|
});
|
|
15297
|
-
return await
|
|
15379
|
+
return await bt.exchangeConnectionService.getCandles(symbol, interval, limit);
|
|
15298
15380
|
}
|
|
15299
15381
|
/**
|
|
15300
15382
|
* Calculates VWAP (Volume Weighted Average Price) for a symbol.
|
|
@@ -15315,10 +15397,10 @@ async function getCandles(symbol, interval, limit) {
|
|
|
15315
15397
|
* ```
|
|
15316
15398
|
*/
|
|
15317
15399
|
async function getAveragePrice(symbol) {
|
|
15318
|
-
|
|
15400
|
+
bt.loggerService.info(GET_AVERAGE_PRICE_METHOD_NAME, {
|
|
15319
15401
|
symbol,
|
|
15320
15402
|
});
|
|
15321
|
-
return await
|
|
15403
|
+
return await bt.exchangeConnectionService.getAveragePrice(symbol);
|
|
15322
15404
|
}
|
|
15323
15405
|
/**
|
|
15324
15406
|
* Formats a price value according to exchange rules.
|
|
@@ -15336,11 +15418,11 @@ async function getAveragePrice(symbol) {
|
|
|
15336
15418
|
* ```
|
|
15337
15419
|
*/
|
|
15338
15420
|
async function formatPrice(symbol, price) {
|
|
15339
|
-
|
|
15421
|
+
bt.loggerService.info(FORMAT_PRICE_METHOD_NAME, {
|
|
15340
15422
|
symbol,
|
|
15341
15423
|
price,
|
|
15342
15424
|
});
|
|
15343
|
-
return await
|
|
15425
|
+
return await bt.exchangeConnectionService.formatPrice(symbol, price);
|
|
15344
15426
|
}
|
|
15345
15427
|
/**
|
|
15346
15428
|
* Formats a quantity value according to exchange rules.
|
|
@@ -15358,11 +15440,11 @@ async function formatPrice(symbol, price) {
|
|
|
15358
15440
|
* ```
|
|
15359
15441
|
*/
|
|
15360
15442
|
async function formatQuantity(symbol, quantity) {
|
|
15361
|
-
|
|
15443
|
+
bt.loggerService.info(FORMAT_QUANTITY_METHOD_NAME, {
|
|
15362
15444
|
symbol,
|
|
15363
15445
|
quantity,
|
|
15364
15446
|
});
|
|
15365
|
-
return await
|
|
15447
|
+
return await bt.exchangeConnectionService.formatQuantity(symbol, quantity);
|
|
15366
15448
|
}
|
|
15367
15449
|
/**
|
|
15368
15450
|
* Gets the current date from execution context.
|
|
@@ -15379,8 +15461,8 @@ async function formatQuantity(symbol, quantity) {
|
|
|
15379
15461
|
* ```
|
|
15380
15462
|
*/
|
|
15381
15463
|
async function getDate() {
|
|
15382
|
-
|
|
15383
|
-
const { when } =
|
|
15464
|
+
bt.loggerService.info(GET_DATE_METHOD_NAME);
|
|
15465
|
+
const { when } = bt.executionContextService.context;
|
|
15384
15466
|
return new Date(when.getTime());
|
|
15385
15467
|
}
|
|
15386
15468
|
/**
|
|
@@ -15399,9 +15481,9 @@ async function getDate() {
|
|
|
15399
15481
|
* ```
|
|
15400
15482
|
*/
|
|
15401
15483
|
async function getMode() {
|
|
15402
|
-
|
|
15403
|
-
const { backtest: bt } =
|
|
15404
|
-
return bt ? "backtest" : "live";
|
|
15484
|
+
bt.loggerService.info(GET_MODE_METHOD_NAME);
|
|
15485
|
+
const { backtest: bt$1 } = bt.executionContextService.context;
|
|
15486
|
+
return bt$1 ? "backtest" : "live";
|
|
15405
15487
|
}
|
|
15406
15488
|
|
|
15407
15489
|
const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
|
|
@@ -15472,13 +15554,13 @@ const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
|
|
|
15472
15554
|
* ```
|
|
15473
15555
|
*/
|
|
15474
15556
|
async function dumpSignal(signalId, history, signal, outputDir = "./dump/strategy") {
|
|
15475
|
-
|
|
15557
|
+
bt.loggerService.info(DUMP_SIGNAL_METHOD_NAME, {
|
|
15476
15558
|
signalId,
|
|
15477
15559
|
history,
|
|
15478
15560
|
signal,
|
|
15479
15561
|
outputDir,
|
|
15480
15562
|
});
|
|
15481
|
-
return await
|
|
15563
|
+
return await bt.outlineMarkdownService.dumpSignal(signalId, history, signal, outputDir);
|
|
15482
15564
|
}
|
|
15483
15565
|
|
|
15484
15566
|
const BACKTEST_METHOD_NAME_RUN = "BacktestUtils.run";
|
|
@@ -15565,7 +15647,7 @@ class BacktestInstance {
|
|
|
15565
15647
|
* @internal
|
|
15566
15648
|
*/
|
|
15567
15649
|
this.task = functoolsKit.singlerun(async (symbol, context) => {
|
|
15568
|
-
|
|
15650
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_TASK, {
|
|
15569
15651
|
symbol,
|
|
15570
15652
|
context,
|
|
15571
15653
|
});
|
|
@@ -15584,7 +15666,7 @@ class BacktestInstance {
|
|
|
15584
15666
|
* ```
|
|
15585
15667
|
*/
|
|
15586
15668
|
this.getStatus = async () => {
|
|
15587
|
-
|
|
15669
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_GET_STATUS);
|
|
15588
15670
|
return {
|
|
15589
15671
|
id: this.id,
|
|
15590
15672
|
symbol: this.symbol,
|
|
@@ -15600,23 +15682,27 @@ class BacktestInstance {
|
|
|
15600
15682
|
* @returns Async generator yielding closed signals with PNL
|
|
15601
15683
|
*/
|
|
15602
15684
|
this.run = (symbol, context) => {
|
|
15603
|
-
|
|
15685
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_RUN, {
|
|
15604
15686
|
symbol,
|
|
15605
15687
|
context,
|
|
15606
15688
|
});
|
|
15607
15689
|
{
|
|
15608
|
-
|
|
15609
|
-
|
|
15690
|
+
bt.backtestMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15691
|
+
bt.liveMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15692
|
+
bt.scheduleMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15693
|
+
bt.performanceMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15694
|
+
bt.partialMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15695
|
+
bt.riskMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15610
15696
|
}
|
|
15611
15697
|
{
|
|
15612
|
-
|
|
15698
|
+
bt.strategyCoreService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15613
15699
|
}
|
|
15614
15700
|
{
|
|
15615
|
-
const { riskName, riskList } =
|
|
15616
|
-
riskName &&
|
|
15617
|
-
riskList && riskList.forEach((riskName) =>
|
|
15701
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
15702
|
+
riskName && bt.riskGlobalService.clear(true, riskName);
|
|
15703
|
+
riskList && riskList.forEach((riskName) => bt.riskGlobalService.clear(true, riskName));
|
|
15618
15704
|
}
|
|
15619
|
-
return
|
|
15705
|
+
return bt.backtestCommandService.run(symbol, context);
|
|
15620
15706
|
};
|
|
15621
15707
|
/**
|
|
15622
15708
|
* Runs backtest in background without yielding results.
|
|
@@ -15639,14 +15725,23 @@ class BacktestInstance {
|
|
|
15639
15725
|
* ```
|
|
15640
15726
|
*/
|
|
15641
15727
|
this.background = (symbol, context) => {
|
|
15642
|
-
|
|
15728
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_BACKGROUND, {
|
|
15643
15729
|
symbol,
|
|
15644
15730
|
context,
|
|
15645
15731
|
});
|
|
15732
|
+
{
|
|
15733
|
+
const currentStatus = this.task.getStatus();
|
|
15734
|
+
if (currentStatus === "pending") {
|
|
15735
|
+
throw new Error(`Backtest.background is already running for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName} frameName=${context.frameName}`);
|
|
15736
|
+
}
|
|
15737
|
+
if (currentStatus === "rejected") {
|
|
15738
|
+
throw new Error(`Backtest.background has failed for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName} frameName=${context.frameName}`);
|
|
15739
|
+
}
|
|
15740
|
+
}
|
|
15646
15741
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
|
|
15647
15742
|
return () => {
|
|
15648
|
-
|
|
15649
|
-
|
|
15743
|
+
bt.strategyCoreService.stop(true, { symbol, strategyName: context.strategyName });
|
|
15744
|
+
bt.strategyCoreService
|
|
15650
15745
|
.getPendingSignal(true, symbol, context.strategyName)
|
|
15651
15746
|
.then(async (pendingSignal) => {
|
|
15652
15747
|
if (pendingSignal) {
|
|
@@ -15683,11 +15778,11 @@ class BacktestInstance {
|
|
|
15683
15778
|
* ```
|
|
15684
15779
|
*/
|
|
15685
15780
|
this.stop = async (symbol, strategyName) => {
|
|
15686
|
-
|
|
15781
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_STOP, {
|
|
15687
15782
|
symbol,
|
|
15688
15783
|
strategyName,
|
|
15689
15784
|
});
|
|
15690
|
-
await
|
|
15785
|
+
await bt.strategyCoreService.stop(true, { symbol, strategyName });
|
|
15691
15786
|
};
|
|
15692
15787
|
/**
|
|
15693
15788
|
* Gets statistical data from all closed signals for a symbol-strategy pair.
|
|
@@ -15704,11 +15799,11 @@ class BacktestInstance {
|
|
|
15704
15799
|
* ```
|
|
15705
15800
|
*/
|
|
15706
15801
|
this.getData = async (symbol, strategyName) => {
|
|
15707
|
-
|
|
15802
|
+
bt.loggerService.info("BacktestUtils.getData", {
|
|
15708
15803
|
symbol,
|
|
15709
15804
|
strategyName,
|
|
15710
15805
|
});
|
|
15711
|
-
return await
|
|
15806
|
+
return await bt.backtestMarkdownService.getData(symbol, strategyName, true);
|
|
15712
15807
|
};
|
|
15713
15808
|
/**
|
|
15714
15809
|
* Generates markdown report with all closed signals for a symbol-strategy pair.
|
|
@@ -15726,11 +15821,11 @@ class BacktestInstance {
|
|
|
15726
15821
|
* ```
|
|
15727
15822
|
*/
|
|
15728
15823
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
15729
|
-
|
|
15824
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_GET_REPORT, {
|
|
15730
15825
|
symbol,
|
|
15731
15826
|
strategyName,
|
|
15732
15827
|
});
|
|
15733
|
-
return await
|
|
15828
|
+
return await bt.backtestMarkdownService.getReport(symbol, strategyName, true, columns);
|
|
15734
15829
|
};
|
|
15735
15830
|
/**
|
|
15736
15831
|
* Saves strategy report to disk.
|
|
@@ -15751,12 +15846,12 @@ class BacktestInstance {
|
|
|
15751
15846
|
* ```
|
|
15752
15847
|
*/
|
|
15753
15848
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
15754
|
-
|
|
15849
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_DUMP, {
|
|
15755
15850
|
symbol,
|
|
15756
15851
|
strategyName,
|
|
15757
15852
|
path,
|
|
15758
15853
|
});
|
|
15759
|
-
await
|
|
15854
|
+
await bt.backtestMarkdownService.dump(symbol, strategyName, true, path, columns);
|
|
15760
15855
|
};
|
|
15761
15856
|
}
|
|
15762
15857
|
}
|
|
@@ -15795,14 +15890,14 @@ class BacktestUtils {
|
|
|
15795
15890
|
*/
|
|
15796
15891
|
this.run = (symbol, context) => {
|
|
15797
15892
|
{
|
|
15798
|
-
|
|
15799
|
-
|
|
15800
|
-
|
|
15893
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_RUN);
|
|
15894
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_RUN);
|
|
15895
|
+
bt.frameValidationService.validate(context.frameName, BACKTEST_METHOD_NAME_RUN);
|
|
15801
15896
|
}
|
|
15802
15897
|
{
|
|
15803
|
-
const { riskName, riskList } =
|
|
15804
|
-
riskName &&
|
|
15805
|
-
riskList && riskList.forEach((riskName) =>
|
|
15898
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
15899
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_RUN);
|
|
15900
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_RUN));
|
|
15806
15901
|
}
|
|
15807
15902
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
15808
15903
|
return instance.run(symbol, context);
|
|
@@ -15829,13 +15924,13 @@ class BacktestUtils {
|
|
|
15829
15924
|
* ```
|
|
15830
15925
|
*/
|
|
15831
15926
|
this.background = (symbol, context) => {
|
|
15832
|
-
|
|
15833
|
-
|
|
15834
|
-
|
|
15927
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15928
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15929
|
+
bt.frameValidationService.validate(context.frameName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15835
15930
|
{
|
|
15836
|
-
const { riskName, riskList } =
|
|
15837
|
-
riskName &&
|
|
15838
|
-
riskList && riskList.forEach((riskName) =>
|
|
15931
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
15932
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15933
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BACKGROUND));
|
|
15839
15934
|
}
|
|
15840
15935
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
15841
15936
|
return instance.background(symbol, context);
|
|
@@ -15858,11 +15953,11 @@ class BacktestUtils {
|
|
|
15858
15953
|
* ```
|
|
15859
15954
|
*/
|
|
15860
15955
|
this.stop = async (symbol, strategyName) => {
|
|
15861
|
-
|
|
15956
|
+
bt.strategyValidationService.validate(strategyName, BACKTEST_METHOD_NAME_STOP);
|
|
15862
15957
|
{
|
|
15863
|
-
const { riskName, riskList } =
|
|
15864
|
-
riskName &&
|
|
15865
|
-
riskList && riskList.forEach((riskName) =>
|
|
15958
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
15959
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_STOP);
|
|
15960
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_STOP));
|
|
15866
15961
|
}
|
|
15867
15962
|
const instance = this._getInstance(symbol, strategyName);
|
|
15868
15963
|
return await instance.stop(symbol, strategyName);
|
|
@@ -15881,11 +15976,11 @@ class BacktestUtils {
|
|
|
15881
15976
|
* ```
|
|
15882
15977
|
*/
|
|
15883
15978
|
this.getData = async (symbol, strategyName) => {
|
|
15884
|
-
|
|
15979
|
+
bt.strategyValidationService.validate(strategyName, "BacktestUtils.getData");
|
|
15885
15980
|
{
|
|
15886
|
-
const { riskName, riskList } =
|
|
15887
|
-
riskName &&
|
|
15888
|
-
riskList && riskList.forEach((riskName) =>
|
|
15981
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
15982
|
+
riskName && bt.riskValidationService.validate(riskName, "BacktestUtils.getData");
|
|
15983
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, "BacktestUtils.getData"));
|
|
15889
15984
|
}
|
|
15890
15985
|
const instance = this._getInstance(symbol, strategyName);
|
|
15891
15986
|
return await instance.getData(symbol, strategyName);
|
|
@@ -15905,11 +16000,11 @@ class BacktestUtils {
|
|
|
15905
16000
|
* ```
|
|
15906
16001
|
*/
|
|
15907
16002
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
15908
|
-
|
|
16003
|
+
bt.strategyValidationService.validate(strategyName, BACKTEST_METHOD_NAME_GET_REPORT);
|
|
15909
16004
|
{
|
|
15910
|
-
const { riskName, riskList } =
|
|
15911
|
-
riskName &&
|
|
15912
|
-
riskList && riskList.forEach((riskName) =>
|
|
16005
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16006
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_REPORT);
|
|
16007
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_REPORT));
|
|
15913
16008
|
}
|
|
15914
16009
|
const instance = this._getInstance(symbol, strategyName);
|
|
15915
16010
|
return await instance.getReport(symbol, strategyName, columns);
|
|
@@ -15932,11 +16027,11 @@ class BacktestUtils {
|
|
|
15932
16027
|
* ```
|
|
15933
16028
|
*/
|
|
15934
16029
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
15935
|
-
|
|
16030
|
+
bt.strategyValidationService.validate(strategyName, BACKTEST_METHOD_NAME_DUMP);
|
|
15936
16031
|
{
|
|
15937
|
-
const { riskName, riskList } =
|
|
15938
|
-
riskName &&
|
|
15939
|
-
riskList && riskList.forEach((riskName) =>
|
|
16032
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16033
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_DUMP);
|
|
16034
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_DUMP));
|
|
15940
16035
|
}
|
|
15941
16036
|
const instance = this._getInstance(symbol, strategyName);
|
|
15942
16037
|
return await instance.dump(symbol, strategyName, path, columns);
|
|
@@ -16066,7 +16161,7 @@ class LiveInstance {
|
|
|
16066
16161
|
* @internal
|
|
16067
16162
|
*/
|
|
16068
16163
|
this.task = functoolsKit.singlerun(async (symbol, context) => {
|
|
16069
|
-
|
|
16164
|
+
bt.loggerService.info(LIVE_METHOD_NAME_TASK, {
|
|
16070
16165
|
symbol,
|
|
16071
16166
|
context,
|
|
16072
16167
|
});
|
|
@@ -16085,7 +16180,7 @@ class LiveInstance {
|
|
|
16085
16180
|
* ```
|
|
16086
16181
|
*/
|
|
16087
16182
|
this.getStatus = async () => {
|
|
16088
|
-
|
|
16183
|
+
bt.loggerService.info(LIVE_METHOD_NAME_GET_STATUS);
|
|
16089
16184
|
return {
|
|
16090
16185
|
id: this.id,
|
|
16091
16186
|
symbol: this.symbol,
|
|
@@ -16104,23 +16199,27 @@ class LiveInstance {
|
|
|
16104
16199
|
* @returns Infinite async generator yielding opened and closed signals
|
|
16105
16200
|
*/
|
|
16106
16201
|
this.run = (symbol, context) => {
|
|
16107
|
-
|
|
16202
|
+
bt.loggerService.info(LIVE_METHOD_NAME_RUN, {
|
|
16108
16203
|
symbol,
|
|
16109
16204
|
context,
|
|
16110
16205
|
});
|
|
16111
16206
|
{
|
|
16112
|
-
|
|
16113
|
-
|
|
16207
|
+
bt.backtestMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16208
|
+
bt.liveMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16209
|
+
bt.scheduleMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16210
|
+
bt.performanceMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16211
|
+
bt.partialMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16212
|
+
bt.riskMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16114
16213
|
}
|
|
16115
16214
|
{
|
|
16116
|
-
|
|
16215
|
+
bt.strategyCoreService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16117
16216
|
}
|
|
16118
16217
|
{
|
|
16119
|
-
const { riskName, riskList } =
|
|
16120
|
-
riskName &&
|
|
16121
|
-
riskList && riskList.forEach((riskName) =>
|
|
16218
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
16219
|
+
riskName && bt.riskGlobalService.clear(false, riskName);
|
|
16220
|
+
riskList && riskList.forEach((riskName) => bt.riskGlobalService.clear(false, riskName));
|
|
16122
16221
|
}
|
|
16123
|
-
return
|
|
16222
|
+
return bt.liveCommandService.run(symbol, context);
|
|
16124
16223
|
};
|
|
16125
16224
|
/**
|
|
16126
16225
|
* Runs live trading in background without yielding results.
|
|
@@ -16143,14 +16242,23 @@ class LiveInstance {
|
|
|
16143
16242
|
* ```
|
|
16144
16243
|
*/
|
|
16145
16244
|
this.background = (symbol, context) => {
|
|
16146
|
-
|
|
16245
|
+
bt.loggerService.info(LIVE_METHOD_NAME_BACKGROUND, {
|
|
16147
16246
|
symbol,
|
|
16148
16247
|
context,
|
|
16149
16248
|
});
|
|
16249
|
+
const currentStatus = this.task.getStatus();
|
|
16250
|
+
{
|
|
16251
|
+
if (currentStatus === "pending") {
|
|
16252
|
+
throw new Error(`Live.background is already running for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName}`);
|
|
16253
|
+
}
|
|
16254
|
+
if (currentStatus === "rejected") {
|
|
16255
|
+
throw new Error(`Live.background has failed for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName}`);
|
|
16256
|
+
}
|
|
16257
|
+
}
|
|
16150
16258
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
|
|
16151
16259
|
return () => {
|
|
16152
|
-
|
|
16153
|
-
|
|
16260
|
+
bt.strategyCoreService.stop(false, { symbol, strategyName: context.strategyName });
|
|
16261
|
+
bt.strategyCoreService
|
|
16154
16262
|
.getPendingSignal(false, symbol, context.strategyName)
|
|
16155
16263
|
.then(async (pendingSignal) => {
|
|
16156
16264
|
if (pendingSignal) {
|
|
@@ -16187,11 +16295,11 @@ class LiveInstance {
|
|
|
16187
16295
|
* ```
|
|
16188
16296
|
*/
|
|
16189
16297
|
this.stop = async (symbol, strategyName) => {
|
|
16190
|
-
|
|
16298
|
+
bt.loggerService.info(LIVE_METHOD_NAME_STOP, {
|
|
16191
16299
|
symbol,
|
|
16192
16300
|
strategyName,
|
|
16193
16301
|
});
|
|
16194
|
-
await
|
|
16302
|
+
await bt.strategyCoreService.stop(false, { symbol, strategyName });
|
|
16195
16303
|
};
|
|
16196
16304
|
/**
|
|
16197
16305
|
* Gets statistical data from all live trading events for a symbol-strategy pair.
|
|
@@ -16208,11 +16316,11 @@ class LiveInstance {
|
|
|
16208
16316
|
* ```
|
|
16209
16317
|
*/
|
|
16210
16318
|
this.getData = async (symbol, strategyName) => {
|
|
16211
|
-
|
|
16319
|
+
bt.loggerService.info("LiveUtils.getData", {
|
|
16212
16320
|
symbol,
|
|
16213
16321
|
strategyName,
|
|
16214
16322
|
});
|
|
16215
|
-
return await
|
|
16323
|
+
return await bt.liveMarkdownService.getData(symbol, strategyName, false);
|
|
16216
16324
|
};
|
|
16217
16325
|
/**
|
|
16218
16326
|
* Generates markdown report with all events for a symbol-strategy pair.
|
|
@@ -16230,11 +16338,11 @@ class LiveInstance {
|
|
|
16230
16338
|
* ```
|
|
16231
16339
|
*/
|
|
16232
16340
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
16233
|
-
|
|
16341
|
+
bt.loggerService.info(LIVE_METHOD_NAME_GET_REPORT, {
|
|
16234
16342
|
symbol,
|
|
16235
16343
|
strategyName,
|
|
16236
16344
|
});
|
|
16237
|
-
return await
|
|
16345
|
+
return await bt.liveMarkdownService.getReport(symbol, strategyName, false, columns);
|
|
16238
16346
|
};
|
|
16239
16347
|
/**
|
|
16240
16348
|
* Saves strategy report to disk.
|
|
@@ -16255,12 +16363,12 @@ class LiveInstance {
|
|
|
16255
16363
|
* ```
|
|
16256
16364
|
*/
|
|
16257
16365
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
16258
|
-
|
|
16366
|
+
bt.loggerService.info(LIVE_METHOD_NAME_DUMP, {
|
|
16259
16367
|
symbol,
|
|
16260
16368
|
strategyName,
|
|
16261
16369
|
path,
|
|
16262
16370
|
});
|
|
16263
|
-
await
|
|
16371
|
+
await bt.liveMarkdownService.dump(symbol, strategyName, false, path, columns);
|
|
16264
16372
|
};
|
|
16265
16373
|
}
|
|
16266
16374
|
}
|
|
@@ -16312,13 +16420,13 @@ class LiveUtils {
|
|
|
16312
16420
|
*/
|
|
16313
16421
|
this.run = (symbol, context) => {
|
|
16314
16422
|
{
|
|
16315
|
-
|
|
16316
|
-
|
|
16423
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_RUN);
|
|
16424
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_RUN);
|
|
16317
16425
|
}
|
|
16318
16426
|
{
|
|
16319
|
-
const { riskName, riskList } =
|
|
16320
|
-
riskName &&
|
|
16321
|
-
riskList && riskList.forEach((riskName) =>
|
|
16427
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
16428
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_RUN);
|
|
16429
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_RUN));
|
|
16322
16430
|
}
|
|
16323
16431
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
16324
16432
|
return instance.run(symbol, context);
|
|
@@ -16345,12 +16453,12 @@ class LiveUtils {
|
|
|
16345
16453
|
* ```
|
|
16346
16454
|
*/
|
|
16347
16455
|
this.background = (symbol, context) => {
|
|
16348
|
-
|
|
16349
|
-
|
|
16456
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_BACKGROUND);
|
|
16457
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_BACKGROUND);
|
|
16350
16458
|
{
|
|
16351
|
-
const { riskName, riskList } =
|
|
16352
|
-
riskName &&
|
|
16353
|
-
riskList && riskList.forEach((riskName) =>
|
|
16459
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
16460
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_BACKGROUND);
|
|
16461
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_BACKGROUND));
|
|
16354
16462
|
}
|
|
16355
16463
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
16356
16464
|
return instance.background(symbol, context);
|
|
@@ -16373,11 +16481,11 @@ class LiveUtils {
|
|
|
16373
16481
|
* ```
|
|
16374
16482
|
*/
|
|
16375
16483
|
this.stop = async (symbol, strategyName) => {
|
|
16376
|
-
|
|
16484
|
+
bt.strategyValidationService.validate(strategyName, LIVE_METHOD_NAME_STOP);
|
|
16377
16485
|
{
|
|
16378
|
-
const { riskName, riskList } =
|
|
16379
|
-
riskName &&
|
|
16380
|
-
riskList && riskList.forEach((riskName) =>
|
|
16486
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16487
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_STOP);
|
|
16488
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_STOP));
|
|
16381
16489
|
}
|
|
16382
16490
|
const instance = this._getInstance(symbol, strategyName);
|
|
16383
16491
|
return await instance.stop(symbol, strategyName);
|
|
@@ -16396,11 +16504,11 @@ class LiveUtils {
|
|
|
16396
16504
|
* ```
|
|
16397
16505
|
*/
|
|
16398
16506
|
this.getData = async (symbol, strategyName) => {
|
|
16399
|
-
|
|
16507
|
+
bt.strategyValidationService.validate(strategyName, "LiveUtils.getData");
|
|
16400
16508
|
{
|
|
16401
|
-
const { riskName, riskList } =
|
|
16402
|
-
riskName &&
|
|
16403
|
-
riskList && riskList.forEach((riskName) =>
|
|
16509
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16510
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_DATA);
|
|
16511
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_DATA));
|
|
16404
16512
|
}
|
|
16405
16513
|
const instance = this._getInstance(symbol, strategyName);
|
|
16406
16514
|
return await instance.getData(symbol, strategyName);
|
|
@@ -16420,11 +16528,11 @@ class LiveUtils {
|
|
|
16420
16528
|
* ```
|
|
16421
16529
|
*/
|
|
16422
16530
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
16423
|
-
|
|
16531
|
+
bt.strategyValidationService.validate(strategyName, LIVE_METHOD_NAME_GET_REPORT);
|
|
16424
16532
|
{
|
|
16425
|
-
const { riskName, riskList } =
|
|
16426
|
-
riskName &&
|
|
16427
|
-
riskList && riskList.forEach((riskName) =>
|
|
16533
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16534
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_REPORT);
|
|
16535
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_REPORT));
|
|
16428
16536
|
}
|
|
16429
16537
|
const instance = this._getInstance(symbol, strategyName);
|
|
16430
16538
|
return await instance.getReport(symbol, strategyName, columns);
|
|
@@ -16447,11 +16555,11 @@ class LiveUtils {
|
|
|
16447
16555
|
* ```
|
|
16448
16556
|
*/
|
|
16449
16557
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
16450
|
-
|
|
16558
|
+
bt.strategyValidationService.validate(strategyName, LIVE_METHOD_NAME_DUMP);
|
|
16451
16559
|
{
|
|
16452
|
-
const { riskName, riskList } =
|
|
16453
|
-
riskName &&
|
|
16454
|
-
riskList && riskList.forEach((riskName) =>
|
|
16560
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16561
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_DUMP);
|
|
16562
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_DUMP));
|
|
16455
16563
|
}
|
|
16456
16564
|
const instance = this._getInstance(symbol, strategyName);
|
|
16457
16565
|
return await instance.dump(symbol, strategyName, path, columns);
|
|
@@ -16535,18 +16643,19 @@ class ScheduleUtils {
|
|
|
16535
16643
|
* console.log(stats.cancellationRate, stats.avgWaitTime);
|
|
16536
16644
|
* ```
|
|
16537
16645
|
*/
|
|
16538
|
-
this.getData = async (symbol, strategyName) => {
|
|
16539
|
-
|
|
16646
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
16647
|
+
bt.loggerService.info(SCHEDULE_METHOD_NAME_GET_DATA, {
|
|
16540
16648
|
symbol,
|
|
16541
16649
|
strategyName,
|
|
16650
|
+
backtest,
|
|
16542
16651
|
});
|
|
16543
|
-
|
|
16652
|
+
bt.strategyValidationService.validate(strategyName, SCHEDULE_METHOD_NAME_GET_DATA);
|
|
16544
16653
|
{
|
|
16545
|
-
const { riskName, riskList } =
|
|
16546
|
-
riskName &&
|
|
16547
|
-
riskList && riskList.forEach((riskName) =>
|
|
16654
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16655
|
+
riskName && bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_DATA);
|
|
16656
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_DATA));
|
|
16548
16657
|
}
|
|
16549
|
-
return await
|
|
16658
|
+
return await bt.scheduleMarkdownService.getData(symbol, strategyName, backtest);
|
|
16550
16659
|
};
|
|
16551
16660
|
/**
|
|
16552
16661
|
* Generates markdown report with all scheduled events for a symbol-strategy pair.
|
|
@@ -16562,18 +16671,19 @@ class ScheduleUtils {
|
|
|
16562
16671
|
* console.log(markdown);
|
|
16563
16672
|
* ```
|
|
16564
16673
|
*/
|
|
16565
|
-
this.getReport = async (symbol, strategyName, columns) => {
|
|
16566
|
-
|
|
16674
|
+
this.getReport = async (symbol, strategyName, backtest, columns) => {
|
|
16675
|
+
bt.loggerService.info(SCHEDULE_METHOD_NAME_GET_REPORT, {
|
|
16567
16676
|
symbol,
|
|
16568
16677
|
strategyName,
|
|
16678
|
+
backtest,
|
|
16569
16679
|
});
|
|
16570
|
-
|
|
16680
|
+
bt.strategyValidationService.validate(strategyName, SCHEDULE_METHOD_NAME_GET_REPORT);
|
|
16571
16681
|
{
|
|
16572
|
-
const { riskName, riskList } =
|
|
16573
|
-
riskName &&
|
|
16574
|
-
riskList && riskList.forEach((riskName) =>
|
|
16682
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16683
|
+
riskName && bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_REPORT);
|
|
16684
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_REPORT));
|
|
16575
16685
|
}
|
|
16576
|
-
return await
|
|
16686
|
+
return await bt.scheduleMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
16577
16687
|
};
|
|
16578
16688
|
/**
|
|
16579
16689
|
* Saves strategy report to disk.
|
|
@@ -16592,19 +16702,20 @@ class ScheduleUtils {
|
|
|
16592
16702
|
* await Schedule.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
16593
16703
|
* ```
|
|
16594
16704
|
*/
|
|
16595
|
-
this.dump = async (symbol, strategyName, path, columns) => {
|
|
16596
|
-
|
|
16705
|
+
this.dump = async (symbol, strategyName, backtest, path, columns) => {
|
|
16706
|
+
bt.loggerService.info(SCHEDULE_METHOD_NAME_DUMP, {
|
|
16597
16707
|
symbol,
|
|
16598
16708
|
strategyName,
|
|
16709
|
+
backtest,
|
|
16599
16710
|
path,
|
|
16600
16711
|
});
|
|
16601
|
-
|
|
16712
|
+
bt.strategyValidationService.validate(strategyName, SCHEDULE_METHOD_NAME_DUMP);
|
|
16602
16713
|
{
|
|
16603
|
-
const { riskName, riskList } =
|
|
16604
|
-
riskName &&
|
|
16605
|
-
riskList && riskList.forEach((riskName) =>
|
|
16714
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16715
|
+
riskName && bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_DUMP);
|
|
16716
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_DUMP));
|
|
16606
16717
|
}
|
|
16607
|
-
await
|
|
16718
|
+
await bt.scheduleMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
16608
16719
|
};
|
|
16609
16720
|
}
|
|
16610
16721
|
}
|
|
@@ -16642,7 +16753,7 @@ const PERFORMANCE_METHOD_NAME_DUMP = "Performance.dump";
|
|
|
16642
16753
|
* console.log(`${event.metricType}: ${event.duration.toFixed(2)}ms`);
|
|
16643
16754
|
* });
|
|
16644
16755
|
*
|
|
16645
|
-
* // Run
|
|
16756
|
+
* // Run bt...
|
|
16646
16757
|
*
|
|
16647
16758
|
* // Get aggregated statistics
|
|
16648
16759
|
* const stats = await Performance.getData("my-strategy");
|
|
@@ -16685,14 +16796,14 @@ class Performance {
|
|
|
16685
16796
|
* }
|
|
16686
16797
|
* ```
|
|
16687
16798
|
*/
|
|
16688
|
-
static async getData(symbol, strategyName) {
|
|
16689
|
-
|
|
16799
|
+
static async getData(symbol, strategyName, backtest) {
|
|
16800
|
+
bt.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_DATA);
|
|
16690
16801
|
{
|
|
16691
|
-
const { riskName, riskList } =
|
|
16692
|
-
riskName &&
|
|
16693
|
-
riskList && riskList.forEach((riskName) =>
|
|
16802
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16803
|
+
riskName && bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_DATA);
|
|
16804
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_DATA));
|
|
16694
16805
|
}
|
|
16695
|
-
return
|
|
16806
|
+
return bt.performanceMarkdownService.getData(symbol, strategyName, backtest);
|
|
16696
16807
|
}
|
|
16697
16808
|
/**
|
|
16698
16809
|
* Generates markdown report with performance analysis.
|
|
@@ -16717,14 +16828,14 @@ class Performance {
|
|
|
16717
16828
|
* await fs.writeFile("performance-report.md", markdown);
|
|
16718
16829
|
* ```
|
|
16719
16830
|
*/
|
|
16720
|
-
static async getReport(symbol, strategyName, columns) {
|
|
16721
|
-
|
|
16831
|
+
static async getReport(symbol, strategyName, backtest, columns) {
|
|
16832
|
+
bt.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_REPORT);
|
|
16722
16833
|
{
|
|
16723
|
-
const { riskName, riskList } =
|
|
16724
|
-
riskName &&
|
|
16725
|
-
riskList && riskList.forEach((riskName) =>
|
|
16834
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16835
|
+
riskName && bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_REPORT);
|
|
16836
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_REPORT));
|
|
16726
16837
|
}
|
|
16727
|
-
return
|
|
16838
|
+
return bt.performanceMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
16728
16839
|
}
|
|
16729
16840
|
/**
|
|
16730
16841
|
* Saves performance report to disk.
|
|
@@ -16746,14 +16857,14 @@ class Performance {
|
|
|
16746
16857
|
* await Performance.dump("BTCUSDT", "my-strategy", "./reports/perf");
|
|
16747
16858
|
* ```
|
|
16748
16859
|
*/
|
|
16749
|
-
static async dump(symbol, strategyName, path = "./dump/performance", columns) {
|
|
16750
|
-
|
|
16860
|
+
static async dump(symbol, strategyName, backtest, path = "./dump/performance", columns) {
|
|
16861
|
+
bt.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_DUMP);
|
|
16751
16862
|
{
|
|
16752
|
-
const { riskName, riskList } =
|
|
16753
|
-
riskName &&
|
|
16754
|
-
riskList && riskList.forEach((riskName) =>
|
|
16863
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16864
|
+
riskName && bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_DUMP);
|
|
16865
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_DUMP));
|
|
16755
16866
|
}
|
|
16756
|
-
return
|
|
16867
|
+
return bt.performanceMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
16757
16868
|
}
|
|
16758
16869
|
}
|
|
16759
16870
|
|
|
@@ -16787,7 +16898,7 @@ const INSTANCE_TASK_FN = async (symbol, context, self) => {
|
|
|
16787
16898
|
}
|
|
16788
16899
|
}
|
|
16789
16900
|
if (!self._isDone) {
|
|
16790
|
-
const walkerSchema =
|
|
16901
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
16791
16902
|
await doneWalkerSubject.next({
|
|
16792
16903
|
exchangeName: walkerSchema.exchangeName,
|
|
16793
16904
|
strategyName: context.walkerName,
|
|
@@ -16841,7 +16952,7 @@ class WalkerInstance {
|
|
|
16841
16952
|
* @internal
|
|
16842
16953
|
*/
|
|
16843
16954
|
this.task = functoolsKit.singlerun(async (symbol, context) => {
|
|
16844
|
-
|
|
16955
|
+
bt.loggerService.info(WALKER_METHOD_NAME_TASK, {
|
|
16845
16956
|
symbol,
|
|
16846
16957
|
context,
|
|
16847
16958
|
});
|
|
@@ -16860,7 +16971,7 @@ class WalkerInstance {
|
|
|
16860
16971
|
* ```
|
|
16861
16972
|
*/
|
|
16862
16973
|
this.getStatus = async () => {
|
|
16863
|
-
|
|
16974
|
+
bt.loggerService.info(WALKER_METHOD_NAME_GET_STATUS);
|
|
16864
16975
|
return {
|
|
16865
16976
|
id: this.id,
|
|
16866
16977
|
symbol: this.symbol,
|
|
@@ -16876,35 +16987,39 @@ class WalkerInstance {
|
|
|
16876
16987
|
* @returns Async generator yielding progress updates after each strategy
|
|
16877
16988
|
*/
|
|
16878
16989
|
this.run = (symbol, context) => {
|
|
16879
|
-
|
|
16990
|
+
bt.loggerService.info(WALKER_METHOD_NAME_RUN, {
|
|
16880
16991
|
symbol,
|
|
16881
16992
|
context,
|
|
16882
16993
|
});
|
|
16883
|
-
|
|
16884
|
-
const walkerSchema =
|
|
16885
|
-
|
|
16886
|
-
|
|
16994
|
+
bt.walkerValidationService.validate(context.walkerName, WALKER_METHOD_NAME_RUN);
|
|
16995
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
16996
|
+
bt.exchangeValidationService.validate(walkerSchema.exchangeName, WALKER_METHOD_NAME_RUN);
|
|
16997
|
+
bt.frameValidationService.validate(walkerSchema.frameName, WALKER_METHOD_NAME_RUN);
|
|
16887
16998
|
for (const strategyName of walkerSchema.strategies) {
|
|
16888
|
-
|
|
16999
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_RUN);
|
|
16889
17000
|
}
|
|
16890
|
-
|
|
17001
|
+
bt.walkerMarkdownService.clear(context.walkerName);
|
|
16891
17002
|
// Clear backtest data for all strategies
|
|
16892
17003
|
for (const strategyName of walkerSchema.strategies) {
|
|
16893
17004
|
{
|
|
16894
|
-
|
|
16895
|
-
|
|
17005
|
+
bt.backtestMarkdownService.clear(true, { symbol, strategyName });
|
|
17006
|
+
bt.liveMarkdownService.clear(true, { symbol, strategyName });
|
|
17007
|
+
bt.scheduleMarkdownService.clear(true, { symbol, strategyName });
|
|
17008
|
+
bt.performanceMarkdownService.clear(true, { symbol, strategyName });
|
|
17009
|
+
bt.partialMarkdownService.clear(true, { symbol, strategyName });
|
|
17010
|
+
bt.riskMarkdownService.clear(true, { symbol, strategyName });
|
|
16896
17011
|
}
|
|
16897
17012
|
{
|
|
16898
|
-
|
|
17013
|
+
bt.strategyCoreService.clear(true, { symbol, strategyName });
|
|
16899
17014
|
}
|
|
16900
17015
|
{
|
|
16901
|
-
const { riskName, riskList } =
|
|
16902
|
-
riskName &&
|
|
17016
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17017
|
+
riskName && bt.riskGlobalService.clear(true, riskName);
|
|
16903
17018
|
riskList &&
|
|
16904
|
-
riskList.forEach((riskName) =>
|
|
17019
|
+
riskList.forEach((riskName) => bt.riskGlobalService.clear(true, riskName));
|
|
16905
17020
|
}
|
|
16906
17021
|
}
|
|
16907
|
-
return
|
|
17022
|
+
return bt.walkerCommandService.run(symbol, {
|
|
16908
17023
|
walkerName: context.walkerName,
|
|
16909
17024
|
exchangeName: walkerSchema.exchangeName,
|
|
16910
17025
|
frameName: walkerSchema.frameName,
|
|
@@ -16929,15 +17044,24 @@ class WalkerInstance {
|
|
|
16929
17044
|
* ```
|
|
16930
17045
|
*/
|
|
16931
17046
|
this.background = (symbol, context) => {
|
|
16932
|
-
|
|
17047
|
+
bt.loggerService.info(WALKER_METHOD_NAME_BACKGROUND, {
|
|
16933
17048
|
symbol,
|
|
16934
17049
|
context,
|
|
16935
17050
|
});
|
|
16936
|
-
const walkerSchema =
|
|
17051
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
17052
|
+
{
|
|
17053
|
+
const currentStatus = this.task.getStatus();
|
|
17054
|
+
if (currentStatus === "pending") {
|
|
17055
|
+
throw new Error(`Walker.background is already running for symbol=${symbol} walkerName=${context.walkerName}`);
|
|
17056
|
+
}
|
|
17057
|
+
if (currentStatus === "rejected") {
|
|
17058
|
+
throw new Error(`Walker.background has failed for symbol=${symbol} walkerName=${context.walkerName}`);
|
|
17059
|
+
}
|
|
17060
|
+
}
|
|
16937
17061
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
|
|
16938
17062
|
return () => {
|
|
16939
17063
|
for (const strategyName of walkerSchema.strategies) {
|
|
16940
|
-
|
|
17064
|
+
bt.strategyCoreService.stop(true, { symbol, strategyName });
|
|
16941
17065
|
walkerStopSubject.next({
|
|
16942
17066
|
symbol,
|
|
16943
17067
|
strategyName,
|
|
@@ -16980,14 +17104,14 @@ class WalkerInstance {
|
|
|
16980
17104
|
* ```
|
|
16981
17105
|
*/
|
|
16982
17106
|
this.stop = async (symbol, walkerName) => {
|
|
16983
|
-
|
|
17107
|
+
bt.loggerService.info(WALKER_METHOD_NAME_STOP, {
|
|
16984
17108
|
symbol,
|
|
16985
17109
|
walkerName,
|
|
16986
17110
|
});
|
|
16987
|
-
const walkerSchema =
|
|
17111
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
16988
17112
|
for (const strategyName of walkerSchema.strategies) {
|
|
16989
17113
|
await walkerStopSubject.next({ symbol, strategyName, walkerName });
|
|
16990
|
-
await
|
|
17114
|
+
await bt.strategyCoreService.stop(true, { symbol, strategyName });
|
|
16991
17115
|
}
|
|
16992
17116
|
};
|
|
16993
17117
|
/**
|
|
@@ -17005,12 +17129,12 @@ class WalkerInstance {
|
|
|
17005
17129
|
* ```
|
|
17006
17130
|
*/
|
|
17007
17131
|
this.getData = async (symbol, walkerName) => {
|
|
17008
|
-
|
|
17132
|
+
bt.loggerService.info(WALKER_METHOD_NAME_GET_DATA, {
|
|
17009
17133
|
symbol,
|
|
17010
17134
|
walkerName,
|
|
17011
17135
|
});
|
|
17012
|
-
const walkerSchema =
|
|
17013
|
-
return await
|
|
17136
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17137
|
+
return await bt.walkerMarkdownService.getData(walkerName, symbol, walkerSchema.metric || "sharpeRatio", {
|
|
17014
17138
|
exchangeName: walkerSchema.exchangeName,
|
|
17015
17139
|
frameName: walkerSchema.frameName,
|
|
17016
17140
|
});
|
|
@@ -17032,12 +17156,12 @@ class WalkerInstance {
|
|
|
17032
17156
|
* ```
|
|
17033
17157
|
*/
|
|
17034
17158
|
this.getReport = async (symbol, walkerName, strategyColumns, pnlColumns) => {
|
|
17035
|
-
|
|
17159
|
+
bt.loggerService.info(WALKER_METHOD_NAME_GET_REPORT, {
|
|
17036
17160
|
symbol,
|
|
17037
17161
|
walkerName,
|
|
17038
17162
|
});
|
|
17039
|
-
const walkerSchema =
|
|
17040
|
-
return await
|
|
17163
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17164
|
+
return await bt.walkerMarkdownService.getReport(walkerName, symbol, walkerSchema.metric || "sharpeRatio", {
|
|
17041
17165
|
exchangeName: walkerSchema.exchangeName,
|
|
17042
17166
|
frameName: walkerSchema.frameName,
|
|
17043
17167
|
}, strategyColumns, pnlColumns);
|
|
@@ -17062,13 +17186,13 @@ class WalkerInstance {
|
|
|
17062
17186
|
* ```
|
|
17063
17187
|
*/
|
|
17064
17188
|
this.dump = async (symbol, walkerName, path, strategyColumns, pnlColumns) => {
|
|
17065
|
-
|
|
17189
|
+
bt.loggerService.info(WALKER_METHOD_NAME_DUMP, {
|
|
17066
17190
|
symbol,
|
|
17067
17191
|
walkerName,
|
|
17068
17192
|
path,
|
|
17069
17193
|
});
|
|
17070
|
-
const walkerSchema =
|
|
17071
|
-
await
|
|
17194
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17195
|
+
await bt.walkerMarkdownService.dump(walkerName, symbol, walkerSchema.metric || "sharpeRatio", {
|
|
17072
17196
|
exchangeName: walkerSchema.exchangeName,
|
|
17073
17197
|
frameName: walkerSchema.frameName,
|
|
17074
17198
|
}, path, strategyColumns, pnlColumns);
|
|
@@ -17109,17 +17233,17 @@ class WalkerUtils {
|
|
|
17109
17233
|
* @returns Async generator yielding progress updates after each strategy
|
|
17110
17234
|
*/
|
|
17111
17235
|
this.run = (symbol, context) => {
|
|
17112
|
-
|
|
17113
|
-
const walkerSchema =
|
|
17114
|
-
|
|
17115
|
-
|
|
17236
|
+
bt.walkerValidationService.validate(context.walkerName, WALKER_METHOD_NAME_RUN);
|
|
17237
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
17238
|
+
bt.exchangeValidationService.validate(walkerSchema.exchangeName, WALKER_METHOD_NAME_RUN);
|
|
17239
|
+
bt.frameValidationService.validate(walkerSchema.frameName, WALKER_METHOD_NAME_RUN);
|
|
17116
17240
|
for (const strategyName of walkerSchema.strategies) {
|
|
17117
|
-
|
|
17118
|
-
const { riskName, riskList } =
|
|
17241
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_RUN);
|
|
17242
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17119
17243
|
riskName &&
|
|
17120
|
-
|
|
17244
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_RUN);
|
|
17121
17245
|
riskList &&
|
|
17122
|
-
riskList.forEach((riskName) =>
|
|
17246
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_RUN));
|
|
17123
17247
|
}
|
|
17124
17248
|
const instance = this._getInstance(symbol, context.walkerName);
|
|
17125
17249
|
return instance.run(symbol, context);
|
|
@@ -17144,17 +17268,17 @@ class WalkerUtils {
|
|
|
17144
17268
|
* ```
|
|
17145
17269
|
*/
|
|
17146
17270
|
this.background = (symbol, context) => {
|
|
17147
|
-
|
|
17148
|
-
const walkerSchema =
|
|
17149
|
-
|
|
17150
|
-
|
|
17271
|
+
bt.walkerValidationService.validate(context.walkerName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17272
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
17273
|
+
bt.exchangeValidationService.validate(walkerSchema.exchangeName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17274
|
+
bt.frameValidationService.validate(walkerSchema.frameName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17151
17275
|
for (const strategyName of walkerSchema.strategies) {
|
|
17152
|
-
|
|
17153
|
-
const { riskName, riskList } =
|
|
17276
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17277
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17154
17278
|
riskName &&
|
|
17155
|
-
|
|
17279
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17156
17280
|
riskList &&
|
|
17157
|
-
riskList.forEach((riskName) =>
|
|
17281
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_BACKGROUND));
|
|
17158
17282
|
}
|
|
17159
17283
|
const instance = this._getInstance(symbol, context.walkerName);
|
|
17160
17284
|
return instance.background(symbol, context);
|
|
@@ -17183,15 +17307,15 @@ class WalkerUtils {
|
|
|
17183
17307
|
* ```
|
|
17184
17308
|
*/
|
|
17185
17309
|
this.stop = async (symbol, walkerName) => {
|
|
17186
|
-
|
|
17187
|
-
const walkerSchema =
|
|
17310
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_STOP);
|
|
17311
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17188
17312
|
for (const strategyName of walkerSchema.strategies) {
|
|
17189
|
-
|
|
17190
|
-
const { riskName, riskList } =
|
|
17313
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_STOP);
|
|
17314
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17191
17315
|
riskName &&
|
|
17192
|
-
|
|
17316
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_STOP);
|
|
17193
17317
|
riskList &&
|
|
17194
|
-
riskList.forEach((riskName) =>
|
|
17318
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_STOP));
|
|
17195
17319
|
}
|
|
17196
17320
|
const instance = this._getInstance(symbol, walkerName);
|
|
17197
17321
|
return await instance.stop(symbol, walkerName);
|
|
@@ -17210,15 +17334,15 @@ class WalkerUtils {
|
|
|
17210
17334
|
* ```
|
|
17211
17335
|
*/
|
|
17212
17336
|
this.getData = async (symbol, walkerName) => {
|
|
17213
|
-
|
|
17214
|
-
const walkerSchema =
|
|
17337
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_GET_DATA);
|
|
17338
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17215
17339
|
for (const strategyName of walkerSchema.strategies) {
|
|
17216
|
-
|
|
17217
|
-
const { riskName, riskList } =
|
|
17340
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_GET_DATA);
|
|
17341
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17218
17342
|
riskName &&
|
|
17219
|
-
|
|
17343
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_DATA);
|
|
17220
17344
|
riskList &&
|
|
17221
|
-
riskList.forEach((riskName) =>
|
|
17345
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_DATA));
|
|
17222
17346
|
}
|
|
17223
17347
|
const instance = this._getInstance(symbol, walkerName);
|
|
17224
17348
|
return await instance.getData(symbol, walkerName);
|
|
@@ -17239,15 +17363,15 @@ class WalkerUtils {
|
|
|
17239
17363
|
* ```
|
|
17240
17364
|
*/
|
|
17241
17365
|
this.getReport = async (symbol, walkerName, strategyColumns, pnlColumns) => {
|
|
17242
|
-
|
|
17243
|
-
const walkerSchema =
|
|
17366
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_GET_REPORT);
|
|
17367
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17244
17368
|
for (const strategyName of walkerSchema.strategies) {
|
|
17245
|
-
|
|
17246
|
-
const { riskName, riskList } =
|
|
17369
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_GET_REPORT);
|
|
17370
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17247
17371
|
riskName &&
|
|
17248
|
-
|
|
17372
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_REPORT);
|
|
17249
17373
|
riskList &&
|
|
17250
|
-
riskList.forEach((riskName) =>
|
|
17374
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_REPORT));
|
|
17251
17375
|
}
|
|
17252
17376
|
const instance = this._getInstance(symbol, walkerName);
|
|
17253
17377
|
return await instance.getReport(symbol, walkerName, strategyColumns, pnlColumns);
|
|
@@ -17271,15 +17395,15 @@ class WalkerUtils {
|
|
|
17271
17395
|
* ```
|
|
17272
17396
|
*/
|
|
17273
17397
|
this.dump = async (symbol, walkerName, path, strategyColumns, pnlColumns) => {
|
|
17274
|
-
|
|
17275
|
-
const walkerSchema =
|
|
17398
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_DUMP);
|
|
17399
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17276
17400
|
for (const strategyName of walkerSchema.strategies) {
|
|
17277
|
-
|
|
17278
|
-
const { riskName, riskList } =
|
|
17401
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_DUMP);
|
|
17402
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17279
17403
|
riskName &&
|
|
17280
|
-
|
|
17404
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_DUMP);
|
|
17281
17405
|
riskList &&
|
|
17282
|
-
riskList.forEach((riskName) =>
|
|
17406
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_DUMP));
|
|
17283
17407
|
}
|
|
17284
17408
|
const instance = this._getInstance(symbol, walkerName);
|
|
17285
17409
|
return await instance.dump(symbol, walkerName, path, strategyColumns, pnlColumns);
|
|
@@ -17371,15 +17495,15 @@ class HeatUtils {
|
|
|
17371
17495
|
* });
|
|
17372
17496
|
* ```
|
|
17373
17497
|
*/
|
|
17374
|
-
this.getData = async (strategyName) => {
|
|
17375
|
-
|
|
17376
|
-
|
|
17498
|
+
this.getData = async (strategyName, backtest) => {
|
|
17499
|
+
bt.loggerService.info(HEAT_METHOD_NAME_GET_DATA, { strategyName });
|
|
17500
|
+
bt.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_DATA);
|
|
17377
17501
|
{
|
|
17378
|
-
const { riskName, riskList } =
|
|
17379
|
-
riskName &&
|
|
17380
|
-
riskList && riskList.forEach((riskName) =>
|
|
17502
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17503
|
+
riskName && bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_DATA);
|
|
17504
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_DATA));
|
|
17381
17505
|
}
|
|
17382
|
-
return await
|
|
17506
|
+
return await bt.heatMarkdownService.getData(strategyName, backtest);
|
|
17383
17507
|
};
|
|
17384
17508
|
/**
|
|
17385
17509
|
* Generates markdown report with portfolio heatmap table for a strategy.
|
|
@@ -17407,15 +17531,15 @@ class HeatUtils {
|
|
|
17407
17531
|
* // ...
|
|
17408
17532
|
* ```
|
|
17409
17533
|
*/
|
|
17410
|
-
this.getReport = async (strategyName, columns) => {
|
|
17411
|
-
|
|
17412
|
-
|
|
17534
|
+
this.getReport = async (strategyName, backtest, columns) => {
|
|
17535
|
+
bt.loggerService.info(HEAT_METHOD_NAME_GET_REPORT, { strategyName });
|
|
17536
|
+
bt.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_REPORT);
|
|
17413
17537
|
{
|
|
17414
|
-
const { riskName, riskList } =
|
|
17415
|
-
riskName &&
|
|
17416
|
-
riskList && riskList.forEach((riskName) =>
|
|
17538
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17539
|
+
riskName && bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_REPORT);
|
|
17540
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_REPORT));
|
|
17417
17541
|
}
|
|
17418
|
-
return await
|
|
17542
|
+
return await bt.heatMarkdownService.getReport(strategyName, backtest, columns);
|
|
17419
17543
|
};
|
|
17420
17544
|
/**
|
|
17421
17545
|
* Saves heatmap report to disk for a strategy.
|
|
@@ -17436,15 +17560,15 @@ class HeatUtils {
|
|
|
17436
17560
|
* await Heat.dump("my-strategy", "./reports");
|
|
17437
17561
|
* ```
|
|
17438
17562
|
*/
|
|
17439
|
-
this.dump = async (strategyName, path, columns) => {
|
|
17440
|
-
|
|
17441
|
-
|
|
17563
|
+
this.dump = async (strategyName, backtest, path, columns) => {
|
|
17564
|
+
bt.loggerService.info(HEAT_METHOD_NAME_DUMP, { strategyName, path });
|
|
17565
|
+
bt.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_DUMP);
|
|
17442
17566
|
{
|
|
17443
|
-
const { riskName, riskList } =
|
|
17444
|
-
riskName &&
|
|
17445
|
-
riskList && riskList.forEach((riskName) =>
|
|
17567
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17568
|
+
riskName && bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_DUMP);
|
|
17569
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_DUMP));
|
|
17446
17570
|
}
|
|
17447
|
-
await
|
|
17571
|
+
await bt.heatMarkdownService.dump(strategyName, backtest, path, columns);
|
|
17448
17572
|
};
|
|
17449
17573
|
}
|
|
17450
17574
|
}
|
|
@@ -17531,12 +17655,12 @@ class PositionSizeUtils {
|
|
|
17531
17655
|
* @throws Error if sizing schema method is not "fixed-percentage"
|
|
17532
17656
|
*/
|
|
17533
17657
|
PositionSizeUtils.fixedPercentage = async (symbol, accountBalance, priceOpen, priceStopLoss, context) => {
|
|
17534
|
-
|
|
17658
|
+
bt.loggerService.info(POSITION_SIZE_METHOD_NAME_FIXED, {
|
|
17535
17659
|
context,
|
|
17536
17660
|
symbol,
|
|
17537
17661
|
});
|
|
17538
|
-
|
|
17539
|
-
return await
|
|
17662
|
+
bt.sizingValidationService.validate(context.sizingName, POSITION_SIZE_METHOD_NAME_FIXED, "fixed-percentage");
|
|
17663
|
+
return await bt.sizingGlobalService.calculate({
|
|
17540
17664
|
symbol,
|
|
17541
17665
|
accountBalance,
|
|
17542
17666
|
priceOpen,
|
|
@@ -17557,12 +17681,12 @@ PositionSizeUtils.fixedPercentage = async (symbol, accountBalance, priceOpen, pr
|
|
|
17557
17681
|
* @throws Error if sizing schema method is not "kelly-criterion"
|
|
17558
17682
|
*/
|
|
17559
17683
|
PositionSizeUtils.kellyCriterion = async (symbol, accountBalance, priceOpen, winRate, winLossRatio, context) => {
|
|
17560
|
-
|
|
17684
|
+
bt.loggerService.info(POSITION_SIZE_METHOD_NAME_KELLY, {
|
|
17561
17685
|
context,
|
|
17562
17686
|
symbol,
|
|
17563
17687
|
});
|
|
17564
|
-
|
|
17565
|
-
return await
|
|
17688
|
+
bt.sizingValidationService.validate(context.sizingName, POSITION_SIZE_METHOD_NAME_KELLY, "kelly-criterion");
|
|
17689
|
+
return await bt.sizingGlobalService.calculate({
|
|
17566
17690
|
symbol,
|
|
17567
17691
|
accountBalance,
|
|
17568
17692
|
priceOpen,
|
|
@@ -17583,12 +17707,12 @@ PositionSizeUtils.kellyCriterion = async (symbol, accountBalance, priceOpen, win
|
|
|
17583
17707
|
* @throws Error if sizing schema method is not "atr-based"
|
|
17584
17708
|
*/
|
|
17585
17709
|
PositionSizeUtils.atrBased = async (symbol, accountBalance, priceOpen, atr, context) => {
|
|
17586
|
-
|
|
17710
|
+
bt.loggerService.info(POSITION_SIZE_METHOD_NAME_ATR, {
|
|
17587
17711
|
context,
|
|
17588
17712
|
symbol,
|
|
17589
17713
|
});
|
|
17590
|
-
|
|
17591
|
-
return await
|
|
17714
|
+
bt.sizingValidationService.validate(context.sizingName, POSITION_SIZE_METHOD_NAME_ATR, "atr-based");
|
|
17715
|
+
return await bt.sizingGlobalService.calculate({
|
|
17592
17716
|
symbol,
|
|
17593
17717
|
accountBalance,
|
|
17594
17718
|
priceOpen,
|
|
@@ -17637,12 +17761,12 @@ class OptimizerUtils {
|
|
|
17637
17761
|
* @throws Error if optimizer not found
|
|
17638
17762
|
*/
|
|
17639
17763
|
this.getData = async (symbol, context) => {
|
|
17640
|
-
|
|
17764
|
+
bt.loggerService.info(OPTIMIZER_METHOD_NAME_GET_DATA, {
|
|
17641
17765
|
symbol,
|
|
17642
17766
|
context,
|
|
17643
17767
|
});
|
|
17644
|
-
|
|
17645
|
-
return await
|
|
17768
|
+
bt.optimizerValidationService.validate(context.optimizerName, OPTIMIZER_METHOD_NAME_GET_DATA);
|
|
17769
|
+
return await bt.optimizerGlobalService.getData(symbol, context.optimizerName);
|
|
17646
17770
|
};
|
|
17647
17771
|
/**
|
|
17648
17772
|
* Generates complete executable strategy code.
|
|
@@ -17654,12 +17778,12 @@ class OptimizerUtils {
|
|
|
17654
17778
|
* @throws Error if optimizer not found
|
|
17655
17779
|
*/
|
|
17656
17780
|
this.getCode = async (symbol, context) => {
|
|
17657
|
-
|
|
17781
|
+
bt.loggerService.info(OPTIMIZER_METHOD_NAME_GET_CODE, {
|
|
17658
17782
|
symbol,
|
|
17659
17783
|
context,
|
|
17660
17784
|
});
|
|
17661
|
-
|
|
17662
|
-
return await
|
|
17785
|
+
bt.optimizerValidationService.validate(context.optimizerName, OPTIMIZER_METHOD_NAME_GET_CODE);
|
|
17786
|
+
return await bt.optimizerGlobalService.getCode(symbol, context.optimizerName);
|
|
17663
17787
|
};
|
|
17664
17788
|
/**
|
|
17665
17789
|
* Generates and saves strategy code to file.
|
|
@@ -17673,13 +17797,13 @@ class OptimizerUtils {
|
|
|
17673
17797
|
* @throws Error if optimizer not found or file write fails
|
|
17674
17798
|
*/
|
|
17675
17799
|
this.dump = async (symbol, context, path) => {
|
|
17676
|
-
|
|
17800
|
+
bt.loggerService.info(OPTIMIZER_METHOD_NAME_DUMP, {
|
|
17677
17801
|
symbol,
|
|
17678
17802
|
context,
|
|
17679
17803
|
path,
|
|
17680
17804
|
});
|
|
17681
|
-
|
|
17682
|
-
await
|
|
17805
|
+
bt.optimizerValidationService.validate(context.optimizerName, OPTIMIZER_METHOD_NAME_DUMP);
|
|
17806
|
+
await bt.optimizerGlobalService.dump(symbol, context.optimizerName, path);
|
|
17683
17807
|
};
|
|
17684
17808
|
}
|
|
17685
17809
|
}
|
|
@@ -17760,15 +17884,15 @@ class PartialUtils {
|
|
|
17760
17884
|
* }
|
|
17761
17885
|
* ```
|
|
17762
17886
|
*/
|
|
17763
|
-
this.getData = async (symbol, strategyName) => {
|
|
17764
|
-
|
|
17765
|
-
|
|
17887
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
17888
|
+
bt.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol, strategyName });
|
|
17889
|
+
bt.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_DATA);
|
|
17766
17890
|
{
|
|
17767
|
-
const { riskName, riskList } =
|
|
17768
|
-
riskName &&
|
|
17769
|
-
riskList && riskList.forEach((riskName) =>
|
|
17891
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17892
|
+
riskName && bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_DATA);
|
|
17893
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_DATA));
|
|
17770
17894
|
}
|
|
17771
|
-
return await
|
|
17895
|
+
return await bt.partialMarkdownService.getData(symbol, strategyName, backtest);
|
|
17772
17896
|
};
|
|
17773
17897
|
/**
|
|
17774
17898
|
* Generates markdown report with all partial profit/loss events for a symbol-strategy pair.
|
|
@@ -17809,15 +17933,15 @@ class PartialUtils {
|
|
|
17809
17933
|
* // **Loss events:** 1
|
|
17810
17934
|
* ```
|
|
17811
17935
|
*/
|
|
17812
|
-
this.getReport = async (symbol, strategyName, columns) => {
|
|
17813
|
-
|
|
17814
|
-
|
|
17936
|
+
this.getReport = async (symbol, strategyName, backtest, columns) => {
|
|
17937
|
+
bt.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol, strategyName });
|
|
17938
|
+
bt.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_REPORT);
|
|
17815
17939
|
{
|
|
17816
|
-
const { riskName, riskList } =
|
|
17817
|
-
riskName &&
|
|
17818
|
-
riskList && riskList.forEach((riskName) =>
|
|
17940
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17941
|
+
riskName && bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_REPORT);
|
|
17942
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_REPORT));
|
|
17819
17943
|
}
|
|
17820
|
-
return await
|
|
17944
|
+
return await bt.partialMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
17821
17945
|
};
|
|
17822
17946
|
/**
|
|
17823
17947
|
* Generates and saves markdown report to file.
|
|
@@ -17851,15 +17975,15 @@ class PartialUtils {
|
|
|
17851
17975
|
* }
|
|
17852
17976
|
* ```
|
|
17853
17977
|
*/
|
|
17854
|
-
this.dump = async (symbol, strategyName, path, columns) => {
|
|
17855
|
-
|
|
17856
|
-
|
|
17978
|
+
this.dump = async (symbol, strategyName, backtest, path, columns) => {
|
|
17979
|
+
bt.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, strategyName, path });
|
|
17980
|
+
bt.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_DUMP);
|
|
17857
17981
|
{
|
|
17858
|
-
const { riskName, riskList } =
|
|
17859
|
-
riskName &&
|
|
17860
|
-
riskList && riskList.forEach((riskName) =>
|
|
17982
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17983
|
+
riskName && bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_DUMP);
|
|
17984
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_DUMP));
|
|
17861
17985
|
}
|
|
17862
|
-
await
|
|
17986
|
+
await bt.partialMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
17863
17987
|
};
|
|
17864
17988
|
}
|
|
17865
17989
|
}
|