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