backtest-kit 1.5.26 → 1.5.28
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 +820 -628
- package/build/index.mjs +820 -628
- package/package.json +1 -1
- package/types.d.ts +197 -136
package/build/index.cjs
CHANGED
|
@@ -2043,7 +2043,7 @@ const BASE_WAIT_FOR_INIT_FN_METHOD_NAME = "PersistBase.waitForInitFn";
|
|
|
2043
2043
|
const BASE_UNLINK_RETRY_COUNT = 5;
|
|
2044
2044
|
const BASE_UNLINK_RETRY_DELAY = 1000;
|
|
2045
2045
|
const BASE_WAIT_FOR_INIT_FN = async (self) => {
|
|
2046
|
-
|
|
2046
|
+
bt.loggerService.debug(BASE_WAIT_FOR_INIT_FN_METHOD_NAME, {
|
|
2047
2047
|
entityName: self.entityName,
|
|
2048
2048
|
directory: self._directory,
|
|
2049
2049
|
});
|
|
@@ -2101,7 +2101,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2101
2101
|
this.entityName = entityName;
|
|
2102
2102
|
this.baseDir = baseDir;
|
|
2103
2103
|
this[_a] = functoolsKit.singleshot(async () => await BASE_WAIT_FOR_INIT_FN(this));
|
|
2104
|
-
|
|
2104
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_CTOR, {
|
|
2105
2105
|
entityName: this.entityName,
|
|
2106
2106
|
baseDir,
|
|
2107
2107
|
});
|
|
@@ -2117,7 +2117,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2117
2117
|
return path.join(this.baseDir, this.entityName, `${entityId}.json`);
|
|
2118
2118
|
}
|
|
2119
2119
|
async waitForInit(initial) {
|
|
2120
|
-
|
|
2120
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_WAIT_FOR_INIT, {
|
|
2121
2121
|
entityName: this.entityName,
|
|
2122
2122
|
initial,
|
|
2123
2123
|
});
|
|
@@ -2134,7 +2134,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2134
2134
|
return length;
|
|
2135
2135
|
}
|
|
2136
2136
|
async readValue(entityId) {
|
|
2137
|
-
|
|
2137
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_READ_VALUE, {
|
|
2138
2138
|
entityName: this.entityName,
|
|
2139
2139
|
entityId,
|
|
2140
2140
|
});
|
|
@@ -2151,7 +2151,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2151
2151
|
}
|
|
2152
2152
|
}
|
|
2153
2153
|
async hasValue(entityId) {
|
|
2154
|
-
|
|
2154
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_HAS_VALUE, {
|
|
2155
2155
|
entityName: this.entityName,
|
|
2156
2156
|
entityId,
|
|
2157
2157
|
});
|
|
@@ -2168,7 +2168,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2168
2168
|
}
|
|
2169
2169
|
}
|
|
2170
2170
|
async writeValue(entityId, entity) {
|
|
2171
|
-
|
|
2171
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_WRITE_VALUE, {
|
|
2172
2172
|
entityName: this.entityName,
|
|
2173
2173
|
entityId,
|
|
2174
2174
|
});
|
|
@@ -2189,7 +2189,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2189
2189
|
* @throws Error if entity not found or deletion fails
|
|
2190
2190
|
*/
|
|
2191
2191
|
async removeValue(entityId) {
|
|
2192
|
-
|
|
2192
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_REMOVE_VALUE, {
|
|
2193
2193
|
entityName: this.entityName,
|
|
2194
2194
|
entityId,
|
|
2195
2195
|
});
|
|
@@ -2211,7 +2211,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2211
2211
|
* @throws Error if deletion fails
|
|
2212
2212
|
*/
|
|
2213
2213
|
async removeAll() {
|
|
2214
|
-
|
|
2214
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_REMOVE_ALL, {
|
|
2215
2215
|
entityName: this.entityName,
|
|
2216
2216
|
});
|
|
2217
2217
|
try {
|
|
@@ -2233,7 +2233,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2233
2233
|
* @throws Error if reading fails
|
|
2234
2234
|
*/
|
|
2235
2235
|
async *values() {
|
|
2236
|
-
|
|
2236
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_VALUES, {
|
|
2237
2237
|
entityName: this.entityName,
|
|
2238
2238
|
});
|
|
2239
2239
|
try {
|
|
@@ -2262,7 +2262,7 @@ const PersistBase = functoolsKit.makeExtendable(class {
|
|
|
2262
2262
|
* @throws Error if reading fails
|
|
2263
2263
|
*/
|
|
2264
2264
|
async *keys() {
|
|
2265
|
-
|
|
2265
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_KEYS, {
|
|
2266
2266
|
entityName: this.entityName,
|
|
2267
2267
|
});
|
|
2268
2268
|
try {
|
|
@@ -2367,7 +2367,7 @@ class PersistSignalUtils {
|
|
|
2367
2367
|
* @returns Promise resolving to signal or null
|
|
2368
2368
|
*/
|
|
2369
2369
|
this.readSignalData = async (symbol, strategyName) => {
|
|
2370
|
-
|
|
2370
|
+
bt.loggerService.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_READ_DATA);
|
|
2371
2371
|
const key = `${symbol}:${strategyName}`;
|
|
2372
2372
|
const isInitial = !this.getSignalStorage.has(key);
|
|
2373
2373
|
const stateStorage = this.getSignalStorage(symbol, strategyName);
|
|
@@ -2389,7 +2389,7 @@ class PersistSignalUtils {
|
|
|
2389
2389
|
* @returns Promise that resolves when write is complete
|
|
2390
2390
|
*/
|
|
2391
2391
|
this.writeSignalData = async (signalRow, symbol, strategyName) => {
|
|
2392
|
-
|
|
2392
|
+
bt.loggerService.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2393
2393
|
const key = `${symbol}:${strategyName}`;
|
|
2394
2394
|
const isInitial = !this.getSignalStorage.has(key);
|
|
2395
2395
|
const stateStorage = this.getSignalStorage(symbol, strategyName);
|
|
@@ -2412,7 +2412,7 @@ class PersistSignalUtils {
|
|
|
2412
2412
|
* ```
|
|
2413
2413
|
*/
|
|
2414
2414
|
usePersistSignalAdapter(Ctor) {
|
|
2415
|
-
|
|
2415
|
+
bt.loggerService.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_PERSIST_SIGNAL_ADAPTER);
|
|
2416
2416
|
this.PersistSignalFactory = Ctor;
|
|
2417
2417
|
}
|
|
2418
2418
|
}
|
|
@@ -2464,7 +2464,7 @@ class PersistRiskUtils {
|
|
|
2464
2464
|
* @returns Promise resolving to Map of active positions
|
|
2465
2465
|
*/
|
|
2466
2466
|
this.readPositionData = async (riskName) => {
|
|
2467
|
-
|
|
2467
|
+
bt.loggerService.info(PERSIST_RISK_UTILS_METHOD_NAME_READ_DATA);
|
|
2468
2468
|
const isInitial = !this.getRiskStorage.has(riskName);
|
|
2469
2469
|
const stateStorage = this.getRiskStorage(riskName);
|
|
2470
2470
|
await stateStorage.waitForInit(isInitial);
|
|
@@ -2485,7 +2485,7 @@ class PersistRiskUtils {
|
|
|
2485
2485
|
* @returns Promise that resolves when write is complete
|
|
2486
2486
|
*/
|
|
2487
2487
|
this.writePositionData = async (riskRow, riskName) => {
|
|
2488
|
-
|
|
2488
|
+
bt.loggerService.info(PERSIST_RISK_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2489
2489
|
const isInitial = !this.getRiskStorage.has(riskName);
|
|
2490
2490
|
const stateStorage = this.getRiskStorage(riskName);
|
|
2491
2491
|
await stateStorage.waitForInit(isInitial);
|
|
@@ -2508,7 +2508,7 @@ class PersistRiskUtils {
|
|
|
2508
2508
|
* ```
|
|
2509
2509
|
*/
|
|
2510
2510
|
usePersistRiskAdapter(Ctor) {
|
|
2511
|
-
|
|
2511
|
+
bt.loggerService.info(PERSIST_RISK_UTILS_METHOD_NAME_USE_PERSIST_RISK_ADAPTER);
|
|
2512
2512
|
this.PersistRiskFactory = Ctor;
|
|
2513
2513
|
}
|
|
2514
2514
|
}
|
|
@@ -2558,7 +2558,7 @@ class PersistScheduleUtils {
|
|
|
2558
2558
|
* @returns Promise resolving to scheduled signal or null
|
|
2559
2559
|
*/
|
|
2560
2560
|
this.readScheduleData = async (symbol, strategyName) => {
|
|
2561
|
-
|
|
2561
|
+
bt.loggerService.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_READ_DATA);
|
|
2562
2562
|
const key = `${symbol}:${strategyName}`;
|
|
2563
2563
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
2564
2564
|
const stateStorage = this.getScheduleStorage(symbol, strategyName);
|
|
@@ -2580,7 +2580,7 @@ class PersistScheduleUtils {
|
|
|
2580
2580
|
* @returns Promise that resolves when write is complete
|
|
2581
2581
|
*/
|
|
2582
2582
|
this.writeScheduleData = async (scheduledSignalRow, symbol, strategyName) => {
|
|
2583
|
-
|
|
2583
|
+
bt.loggerService.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2584
2584
|
const key = `${symbol}:${strategyName}`;
|
|
2585
2585
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
2586
2586
|
const stateStorage = this.getScheduleStorage(symbol, strategyName);
|
|
@@ -2603,7 +2603,7 @@ class PersistScheduleUtils {
|
|
|
2603
2603
|
* ```
|
|
2604
2604
|
*/
|
|
2605
2605
|
usePersistScheduleAdapter(Ctor) {
|
|
2606
|
-
|
|
2606
|
+
bt.loggerService.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_PERSIST_SCHEDULE_ADAPTER);
|
|
2607
2607
|
this.PersistScheduleFactory = Ctor;
|
|
2608
2608
|
}
|
|
2609
2609
|
}
|
|
@@ -2628,7 +2628,7 @@ const PersistScheduleAdapter = new PersistScheduleUtils();
|
|
|
2628
2628
|
* Utility class for managing partial profit/loss levels persistence.
|
|
2629
2629
|
*
|
|
2630
2630
|
* Features:
|
|
2631
|
-
* - Memoized storage instances per symbol
|
|
2631
|
+
* - Memoized storage instances per symbol:strategyName
|
|
2632
2632
|
* - Custom adapter support
|
|
2633
2633
|
* - Atomic read/write operations for partial data
|
|
2634
2634
|
* - Crash-safe partial state management
|
|
@@ -2638,23 +2638,25 @@ const PersistScheduleAdapter = new PersistScheduleUtils();
|
|
|
2638
2638
|
class PersistPartialUtils {
|
|
2639
2639
|
constructor() {
|
|
2640
2640
|
this.PersistPartialFactory = PersistBase;
|
|
2641
|
-
this.getPartialStorage = functoolsKit.memoize(([symbol]) => `${symbol}`, (symbol) => Reflect.construct(this.PersistPartialFactory, [
|
|
2642
|
-
symbol
|
|
2641
|
+
this.getPartialStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, (symbol, strategyName) => Reflect.construct(this.PersistPartialFactory, [
|
|
2642
|
+
`${symbol}_${strategyName}`,
|
|
2643
2643
|
`./dump/data/partial/`,
|
|
2644
2644
|
]));
|
|
2645
2645
|
/**
|
|
2646
|
-
* Reads persisted partial data for a symbol.
|
|
2646
|
+
* Reads persisted partial data for a symbol and strategy.
|
|
2647
2647
|
*
|
|
2648
2648
|
* Called by ClientPartial.waitForInit() to restore state.
|
|
2649
2649
|
* Returns empty object if no partial data exists.
|
|
2650
2650
|
*
|
|
2651
2651
|
* @param symbol - Trading pair symbol
|
|
2652
|
+
* @param strategyName - Strategy identifier
|
|
2652
2653
|
* @returns Promise resolving to partial data record
|
|
2653
2654
|
*/
|
|
2654
|
-
this.readPartialData = async (symbol) => {
|
|
2655
|
-
|
|
2656
|
-
const
|
|
2657
|
-
const
|
|
2655
|
+
this.readPartialData = async (symbol, strategyName) => {
|
|
2656
|
+
bt.loggerService.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_READ_DATA);
|
|
2657
|
+
const key = `${symbol}:${strategyName}`;
|
|
2658
|
+
const isInitial = !this.getPartialStorage.has(key);
|
|
2659
|
+
const stateStorage = this.getPartialStorage(symbol, strategyName);
|
|
2658
2660
|
await stateStorage.waitForInit(isInitial);
|
|
2659
2661
|
const PARTIAL_STORAGE_KEY = "levels";
|
|
2660
2662
|
if (await stateStorage.hasValue(PARTIAL_STORAGE_KEY)) {
|
|
@@ -2670,12 +2672,14 @@ class PersistPartialUtils {
|
|
|
2670
2672
|
*
|
|
2671
2673
|
* @param partialData - Record of signal IDs to partial data
|
|
2672
2674
|
* @param symbol - Trading pair symbol
|
|
2675
|
+
* @param strategyName - Strategy identifier
|
|
2673
2676
|
* @returns Promise that resolves when write is complete
|
|
2674
2677
|
*/
|
|
2675
|
-
this.writePartialData = async (partialData, symbol) => {
|
|
2676
|
-
|
|
2677
|
-
const
|
|
2678
|
-
const
|
|
2678
|
+
this.writePartialData = async (partialData, symbol, strategyName) => {
|
|
2679
|
+
bt.loggerService.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2680
|
+
const key = `${symbol}:${strategyName}`;
|
|
2681
|
+
const isInitial = !this.getPartialStorage.has(key);
|
|
2682
|
+
const stateStorage = this.getPartialStorage(symbol, strategyName);
|
|
2679
2683
|
await stateStorage.waitForInit(isInitial);
|
|
2680
2684
|
const PARTIAL_STORAGE_KEY = "levels";
|
|
2681
2685
|
await stateStorage.writeValue(PARTIAL_STORAGE_KEY, partialData);
|
|
@@ -2696,7 +2700,7 @@ class PersistPartialUtils {
|
|
|
2696
2700
|
* ```
|
|
2697
2701
|
*/
|
|
2698
2702
|
usePersistPartialAdapter(Ctor) {
|
|
2699
|
-
|
|
2703
|
+
bt.loggerService.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_PERSIST_PARTIAL_ADAPTER);
|
|
2700
2704
|
this.PersistPartialFactory = Ctor;
|
|
2701
2705
|
}
|
|
2702
2706
|
}
|
|
@@ -2710,10 +2714,10 @@ class PersistPartialUtils {
|
|
|
2710
2714
|
* PersistPartialAdapter.usePersistPartialAdapter(RedisPersist);
|
|
2711
2715
|
*
|
|
2712
2716
|
* // Read partial data
|
|
2713
|
-
* const partialData = await PersistPartialAdapter.readPartialData("BTCUSDT");
|
|
2717
|
+
* const partialData = await PersistPartialAdapter.readPartialData("BTCUSDT", "my-strategy");
|
|
2714
2718
|
*
|
|
2715
2719
|
* // Write partial data
|
|
2716
|
-
* await PersistPartialAdapter.writePartialData(partialData, "BTCUSDT");
|
|
2720
|
+
* await PersistPartialAdapter.writePartialData(partialData, "BTCUSDT", "my-strategy");
|
|
2717
2721
|
* ```
|
|
2718
2722
|
*/
|
|
2719
2723
|
const PersistPartialAdapter = new PersistPartialUtils();
|
|
@@ -3165,7 +3169,7 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
3165
3169
|
error: functoolsKit.errorData(error),
|
|
3166
3170
|
message: functoolsKit.getErrorMessage(error),
|
|
3167
3171
|
};
|
|
3168
|
-
|
|
3172
|
+
bt.loggerService.warn(message, payload);
|
|
3169
3173
|
console.warn(message, payload);
|
|
3170
3174
|
errorEmitter.next(error);
|
|
3171
3175
|
},
|
|
@@ -3244,6 +3248,7 @@ const CHECK_SCHEDULED_SIGNAL_TIMEOUT_FN = async (self, scheduled, currentPrice)
|
|
|
3244
3248
|
strategyName: self.params.method.context.strategyName,
|
|
3245
3249
|
exchangeName: self.params.method.context.exchangeName,
|
|
3246
3250
|
symbol: self.params.execution.context.symbol,
|
|
3251
|
+
backtest: self.params.execution.context.backtest,
|
|
3247
3252
|
};
|
|
3248
3253
|
if (self.params.callbacks?.onTick) {
|
|
3249
3254
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3295,6 +3300,7 @@ const CANCEL_SCHEDULED_SIGNAL_BY_STOPLOSS_FN = async (self, scheduled, currentPr
|
|
|
3295
3300
|
exchangeName: self.params.method.context.exchangeName,
|
|
3296
3301
|
symbol: self.params.execution.context.symbol,
|
|
3297
3302
|
currentPrice: currentPrice,
|
|
3303
|
+
backtest: self.params.execution.context.backtest,
|
|
3298
3304
|
};
|
|
3299
3305
|
if (self.params.callbacks?.onTick) {
|
|
3300
3306
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3362,6 +3368,7 @@ const ACTIVATE_SCHEDULED_SIGNAL_FN = async (self, scheduled, activationTimestamp
|
|
|
3362
3368
|
exchangeName: self.params.method.context.exchangeName,
|
|
3363
3369
|
symbol: self.params.execution.context.symbol,
|
|
3364
3370
|
currentPrice: self._pendingSignal.priceOpen,
|
|
3371
|
+
backtest: self.params.execution.context.backtest,
|
|
3365
3372
|
};
|
|
3366
3373
|
if (self.params.callbacks?.onTick) {
|
|
3367
3374
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3378,6 +3385,7 @@ const RETURN_SCHEDULED_SIGNAL_ACTIVE_FN = async (self, scheduled, currentPrice)
|
|
|
3378
3385
|
symbol: self.params.execution.context.symbol,
|
|
3379
3386
|
percentTp: 0,
|
|
3380
3387
|
percentSl: 0,
|
|
3388
|
+
backtest: self.params.execution.context.backtest,
|
|
3381
3389
|
};
|
|
3382
3390
|
if (self.params.callbacks?.onTick) {
|
|
3383
3391
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3403,6 +3411,7 @@ const OPEN_NEW_SCHEDULED_SIGNAL_FN = async (self, signal) => {
|
|
|
3403
3411
|
exchangeName: self.params.method.context.exchangeName,
|
|
3404
3412
|
symbol: self.params.execution.context.symbol,
|
|
3405
3413
|
currentPrice: currentPrice,
|
|
3414
|
+
backtest: self.params.execution.context.backtest,
|
|
3406
3415
|
};
|
|
3407
3416
|
if (self.params.callbacks?.onTick) {
|
|
3408
3417
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3434,6 +3443,7 @@ const OPEN_NEW_PENDING_SIGNAL_FN = async (self, signal) => {
|
|
|
3434
3443
|
exchangeName: self.params.method.context.exchangeName,
|
|
3435
3444
|
symbol: self.params.execution.context.symbol,
|
|
3436
3445
|
currentPrice: signal.priceOpen,
|
|
3446
|
+
backtest: self.params.execution.context.backtest,
|
|
3437
3447
|
};
|
|
3438
3448
|
if (self.params.callbacks?.onTick) {
|
|
3439
3449
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3498,6 +3508,7 @@ const CLOSE_PENDING_SIGNAL_FN = async (self, signal, currentPrice, closeReason)
|
|
|
3498
3508
|
strategyName: self.params.method.context.strategyName,
|
|
3499
3509
|
exchangeName: self.params.method.context.exchangeName,
|
|
3500
3510
|
symbol: self.params.execution.context.symbol,
|
|
3511
|
+
backtest: self.params.execution.context.backtest,
|
|
3501
3512
|
};
|
|
3502
3513
|
if (self.params.callbacks?.onTick) {
|
|
3503
3514
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3567,6 +3578,7 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice) => {
|
|
|
3567
3578
|
symbol: self.params.execution.context.symbol,
|
|
3568
3579
|
percentTp,
|
|
3569
3580
|
percentSl,
|
|
3581
|
+
backtest: self.params.execution.context.backtest,
|
|
3570
3582
|
};
|
|
3571
3583
|
if (self.params.callbacks?.onTick) {
|
|
3572
3584
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3584,6 +3596,7 @@ const RETURN_IDLE_FN = async (self, currentPrice) => {
|
|
|
3584
3596
|
exchangeName: self.params.method.context.exchangeName,
|
|
3585
3597
|
symbol: self.params.execution.context.symbol,
|
|
3586
3598
|
currentPrice: currentPrice,
|
|
3599
|
+
backtest: self.params.execution.context.backtest,
|
|
3587
3600
|
};
|
|
3588
3601
|
if (self.params.callbacks?.onTick) {
|
|
3589
3602
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3610,6 +3623,7 @@ const CANCEL_SCHEDULED_SIGNAL_IN_BACKTEST_FN = async (self, scheduled, averagePr
|
|
|
3610
3623
|
strategyName: self.params.method.context.strategyName,
|
|
3611
3624
|
exchangeName: self.params.method.context.exchangeName,
|
|
3612
3625
|
symbol: self.params.execution.context.symbol,
|
|
3626
|
+
backtest: self.params.execution.context.backtest,
|
|
3613
3627
|
};
|
|
3614
3628
|
if (self.params.callbacks?.onTick) {
|
|
3615
3629
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3705,6 +3719,7 @@ const CLOSE_PENDING_SIGNAL_IN_BACKTEST_FN = async (self, signal, averagePrice, c
|
|
|
3705
3719
|
strategyName: self.params.method.context.strategyName,
|
|
3706
3720
|
exchangeName: self.params.method.context.exchangeName,
|
|
3707
3721
|
symbol: self.params.execution.context.symbol,
|
|
3722
|
+
backtest: self.params.execution.context.backtest,
|
|
3708
3723
|
};
|
|
3709
3724
|
if (self.params.callbacks?.onTick) {
|
|
3710
3725
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -4203,6 +4218,7 @@ class ClientStrategy {
|
|
|
4203
4218
|
strategyName: this.params.method.context.strategyName,
|
|
4204
4219
|
exchangeName: this.params.method.context.exchangeName,
|
|
4205
4220
|
symbol: this.params.execution.context.symbol,
|
|
4221
|
+
backtest: this.params.execution.context.backtest,
|
|
4206
4222
|
};
|
|
4207
4223
|
return result; // Cast to IStrategyBacktestResult (which includes Active)
|
|
4208
4224
|
}
|
|
@@ -4333,7 +4349,7 @@ class MergeRisk {
|
|
|
4333
4349
|
* @returns Promise resolving to true if all risks approve, false if any risk rejects
|
|
4334
4350
|
*/
|
|
4335
4351
|
async checkSignal(params) {
|
|
4336
|
-
|
|
4352
|
+
bt.loggerService.info("MergeRisk checkSignal", {
|
|
4337
4353
|
params,
|
|
4338
4354
|
});
|
|
4339
4355
|
const riskCheck = await Promise.all(this._riskList.map(async (risk) => await risk.checkSignal(params)));
|
|
@@ -4350,7 +4366,7 @@ class MergeRisk {
|
|
|
4350
4366
|
* @returns Promise that resolves when all risks have registered the signal
|
|
4351
4367
|
*/
|
|
4352
4368
|
async addSignal(symbol, context) {
|
|
4353
|
-
|
|
4369
|
+
bt.loggerService.info("MergeRisk addSignal", {
|
|
4354
4370
|
symbol,
|
|
4355
4371
|
context,
|
|
4356
4372
|
});
|
|
@@ -4367,7 +4383,7 @@ class MergeRisk {
|
|
|
4367
4383
|
* @returns Promise that resolves when all risks have removed the signal
|
|
4368
4384
|
*/
|
|
4369
4385
|
async removeSignal(symbol, context) {
|
|
4370
|
-
|
|
4386
|
+
bt.loggerService.info("MergeRisk removeSignal", {
|
|
4371
4387
|
symbol,
|
|
4372
4388
|
context,
|
|
4373
4389
|
});
|
|
@@ -4435,19 +4451,19 @@ class RiskUtils {
|
|
|
4435
4451
|
* }
|
|
4436
4452
|
* ```
|
|
4437
4453
|
*/
|
|
4438
|
-
this.getData = async (symbol, strategyName) => {
|
|
4439
|
-
|
|
4454
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
4455
|
+
bt.loggerService.info(RISK_METHOD_NAME_GET_DATA, {
|
|
4440
4456
|
symbol,
|
|
4441
4457
|
strategyName,
|
|
4442
4458
|
});
|
|
4443
|
-
|
|
4459
|
+
bt.strategyValidationService.validate(strategyName, RISK_METHOD_NAME_GET_DATA);
|
|
4444
4460
|
{
|
|
4445
|
-
const { riskName, riskList } =
|
|
4461
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
4446
4462
|
riskName &&
|
|
4447
|
-
|
|
4448
|
-
riskList && riskList.forEach((riskName) =>
|
|
4463
|
+
bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_DATA);
|
|
4464
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_DATA));
|
|
4449
4465
|
}
|
|
4450
|
-
return await
|
|
4466
|
+
return await bt.riskMarkdownService.getData(symbol, strategyName, backtest);
|
|
4451
4467
|
};
|
|
4452
4468
|
/**
|
|
4453
4469
|
* Generates markdown report with all risk rejection events for a symbol-strategy pair.
|
|
@@ -4490,19 +4506,19 @@ class RiskUtils {
|
|
|
4490
4506
|
* // - my-strategy: 1
|
|
4491
4507
|
* ```
|
|
4492
4508
|
*/
|
|
4493
|
-
this.getReport = async (symbol, strategyName, columns) => {
|
|
4494
|
-
|
|
4509
|
+
this.getReport = async (symbol, strategyName, backtest, columns) => {
|
|
4510
|
+
bt.loggerService.info(RISK_METHOD_NAME_GET_REPORT, {
|
|
4495
4511
|
symbol,
|
|
4496
4512
|
strategyName,
|
|
4497
4513
|
});
|
|
4498
|
-
|
|
4514
|
+
bt.strategyValidationService.validate(strategyName, RISK_METHOD_NAME_GET_REPORT);
|
|
4499
4515
|
{
|
|
4500
|
-
const { riskName, riskList } =
|
|
4516
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
4501
4517
|
riskName &&
|
|
4502
|
-
|
|
4503
|
-
riskList && riskList.forEach((riskName) =>
|
|
4518
|
+
bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_REPORT);
|
|
4519
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_REPORT));
|
|
4504
4520
|
}
|
|
4505
|
-
return await
|
|
4521
|
+
return await bt.riskMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
4506
4522
|
};
|
|
4507
4523
|
/**
|
|
4508
4524
|
* Generates and saves markdown report to file.
|
|
@@ -4536,20 +4552,20 @@ class RiskUtils {
|
|
|
4536
4552
|
* }
|
|
4537
4553
|
* ```
|
|
4538
4554
|
*/
|
|
4539
|
-
this.dump = async (symbol, strategyName, path, columns) => {
|
|
4540
|
-
|
|
4555
|
+
this.dump = async (symbol, strategyName, backtest, path, columns) => {
|
|
4556
|
+
bt.loggerService.info(RISK_METHOD_NAME_DUMP, {
|
|
4541
4557
|
symbol,
|
|
4542
4558
|
strategyName,
|
|
4543
4559
|
path,
|
|
4544
4560
|
});
|
|
4545
|
-
|
|
4561
|
+
bt.strategyValidationService.validate(strategyName, RISK_METHOD_NAME_DUMP);
|
|
4546
4562
|
{
|
|
4547
|
-
const { riskName, riskList } =
|
|
4563
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
4548
4564
|
riskName &&
|
|
4549
|
-
|
|
4550
|
-
riskList && riskList.forEach((riskName) =>
|
|
4565
|
+
bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_DUMP);
|
|
4566
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_DUMP));
|
|
4551
4567
|
}
|
|
4552
|
-
await
|
|
4568
|
+
await bt.riskMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
4553
4569
|
};
|
|
4554
4570
|
}
|
|
4555
4571
|
}
|
|
@@ -4574,25 +4590,25 @@ const NOOP_RISK = {
|
|
|
4574
4590
|
addSignal: () => Promise.resolve(),
|
|
4575
4591
|
removeSignal: () => Promise.resolve(),
|
|
4576
4592
|
};
|
|
4577
|
-
const GET_RISK_FN = (dto, self) => {
|
|
4593
|
+
const GET_RISK_FN = (dto, backtest, self) => {
|
|
4578
4594
|
const hasRiskName = !!dto.riskName;
|
|
4579
|
-
const hasRiskList = !!
|
|
4595
|
+
const hasRiskList = !!dto.riskList?.length;
|
|
4580
4596
|
// Нет ни riskName, ни riskList
|
|
4581
4597
|
if (!hasRiskName && !hasRiskList) {
|
|
4582
4598
|
return NOOP_RISK;
|
|
4583
4599
|
}
|
|
4584
4600
|
// Есть только riskName (без riskList)
|
|
4585
4601
|
if (hasRiskName && !hasRiskList) {
|
|
4586
|
-
return self.riskConnectionService.getRisk(dto.riskName);
|
|
4602
|
+
return self.riskConnectionService.getRisk(dto.riskName, backtest);
|
|
4587
4603
|
}
|
|
4588
4604
|
// Есть только riskList (без riskName)
|
|
4589
4605
|
if (!hasRiskName && hasRiskList) {
|
|
4590
|
-
return new MergeRisk(dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName)));
|
|
4606
|
+
return new MergeRisk(dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName, backtest)));
|
|
4591
4607
|
}
|
|
4592
4608
|
// Есть и riskName, и riskList - объединяем (riskName в начало)
|
|
4593
4609
|
return new MergeRisk([
|
|
4594
|
-
self.riskConnectionService.getRisk(dto.riskName),
|
|
4595
|
-
...dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName))
|
|
4610
|
+
self.riskConnectionService.getRisk(dto.riskName, backtest),
|
|
4611
|
+
...dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName, backtest)),
|
|
4596
4612
|
]);
|
|
4597
4613
|
};
|
|
4598
4614
|
/**
|
|
@@ -4634,7 +4650,7 @@ class StrategyConnectionService {
|
|
|
4634
4650
|
* @param strategyName - Name of registered strategy schema
|
|
4635
4651
|
* @returns Configured ClientStrategy instance
|
|
4636
4652
|
*/
|
|
4637
|
-
this.getStrategy = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, (symbol, strategyName) => {
|
|
4653
|
+
this.getStrategy = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, (symbol, strategyName, backtest) => {
|
|
4638
4654
|
const { riskName = "", riskList = [], getSignal, interval, callbacks, } = this.strategySchemaService.get(strategyName);
|
|
4639
4655
|
return new ClientStrategy({
|
|
4640
4656
|
symbol,
|
|
@@ -4647,7 +4663,7 @@ class StrategyConnectionService {
|
|
|
4647
4663
|
risk: GET_RISK_FN({
|
|
4648
4664
|
riskName,
|
|
4649
4665
|
riskList,
|
|
4650
|
-
}, this),
|
|
4666
|
+
}, backtest, this),
|
|
4651
4667
|
riskName,
|
|
4652
4668
|
strategyName,
|
|
4653
4669
|
getSignal,
|
|
@@ -4664,12 +4680,13 @@ class StrategyConnectionService {
|
|
|
4664
4680
|
*
|
|
4665
4681
|
* @returns Promise resolving to pending signal or null
|
|
4666
4682
|
*/
|
|
4667
|
-
this.getPendingSignal = async (symbol, strategyName) => {
|
|
4683
|
+
this.getPendingSignal = async (backtest, symbol, strategyName) => {
|
|
4668
4684
|
this.loggerService.log("strategyConnectionService getPendingSignal", {
|
|
4669
4685
|
symbol,
|
|
4670
4686
|
strategyName,
|
|
4687
|
+
backtest,
|
|
4671
4688
|
});
|
|
4672
|
-
const strategy = this.getStrategy(symbol, strategyName);
|
|
4689
|
+
const strategy = this.getStrategy(symbol, strategyName, backtest);
|
|
4673
4690
|
return await strategy.getPendingSignal(symbol, strategyName);
|
|
4674
4691
|
};
|
|
4675
4692
|
/**
|
|
@@ -4682,12 +4699,13 @@ class StrategyConnectionService {
|
|
|
4682
4699
|
* @param strategyName - Name of the strategy
|
|
4683
4700
|
* @returns Promise resolving to true if strategy is stopped, false otherwise
|
|
4684
4701
|
*/
|
|
4685
|
-
this.getStopped = async (symbol, strategyName) => {
|
|
4702
|
+
this.getStopped = async (backtest, symbol, strategyName) => {
|
|
4686
4703
|
this.loggerService.log("strategyConnectionService getStopped", {
|
|
4687
4704
|
symbol,
|
|
4688
4705
|
strategyName,
|
|
4706
|
+
backtest,
|
|
4689
4707
|
});
|
|
4690
|
-
const strategy = this.getStrategy(symbol, strategyName);
|
|
4708
|
+
const strategy = this.getStrategy(symbol, strategyName, backtest);
|
|
4691
4709
|
return await strategy.getStopped(symbol, strategyName);
|
|
4692
4710
|
};
|
|
4693
4711
|
/**
|
|
@@ -4705,7 +4723,8 @@ class StrategyConnectionService {
|
|
|
4705
4723
|
symbol,
|
|
4706
4724
|
strategyName,
|
|
4707
4725
|
});
|
|
4708
|
-
const
|
|
4726
|
+
const backtest = this.executionContextService.context.backtest;
|
|
4727
|
+
const strategy = this.getStrategy(symbol, strategyName, backtest);
|
|
4709
4728
|
await strategy.waitForInit();
|
|
4710
4729
|
const tick = await strategy.tick(symbol, strategyName);
|
|
4711
4730
|
{
|
|
@@ -4736,7 +4755,8 @@ class StrategyConnectionService {
|
|
|
4736
4755
|
strategyName,
|
|
4737
4756
|
candleCount: candles.length,
|
|
4738
4757
|
});
|
|
4739
|
-
const
|
|
4758
|
+
const backtest = this.executionContextService.context.backtest;
|
|
4759
|
+
const strategy = this.getStrategy(symbol, strategyName, backtest);
|
|
4740
4760
|
await strategy.waitForInit();
|
|
4741
4761
|
const tick = await strategy.backtest(symbol, strategyName, candles);
|
|
4742
4762
|
{
|
|
@@ -4757,11 +4777,11 @@ class StrategyConnectionService {
|
|
|
4757
4777
|
* @param strategyName - Name of strategy to stop
|
|
4758
4778
|
* @returns Promise that resolves when stop flag is set
|
|
4759
4779
|
*/
|
|
4760
|
-
this.stop = async (
|
|
4780
|
+
this.stop = async (backtest, ctx) => {
|
|
4761
4781
|
this.loggerService.log("strategyConnectionService stop", {
|
|
4762
4782
|
ctx,
|
|
4763
4783
|
});
|
|
4764
|
-
const strategy = this.getStrategy(ctx.symbol, ctx.strategyName);
|
|
4784
|
+
const strategy = this.getStrategy(ctx.symbol, ctx.strategyName, backtest);
|
|
4765
4785
|
await strategy.stop(ctx.symbol, ctx.strategyName, backtest);
|
|
4766
4786
|
};
|
|
4767
4787
|
/**
|
|
@@ -4772,12 +4792,12 @@ class StrategyConnectionService {
|
|
|
4772
4792
|
*
|
|
4773
4793
|
* @param ctx - Optional context with symbol and strategyName (clears all if not provided)
|
|
4774
4794
|
*/
|
|
4775
|
-
this.clear = async (ctx) => {
|
|
4795
|
+
this.clear = async (backtest, ctx) => {
|
|
4776
4796
|
this.loggerService.log("strategyConnectionService clear", {
|
|
4777
4797
|
ctx,
|
|
4778
4798
|
});
|
|
4779
4799
|
if (ctx) {
|
|
4780
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
4800
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
4781
4801
|
this.getStrategy.clear(key);
|
|
4782
4802
|
}
|
|
4783
4803
|
else {
|
|
@@ -5163,7 +5183,7 @@ const DO_VALIDATION_FN = functoolsKit.trycatch(async (validation, params) => {
|
|
|
5163
5183
|
error: functoolsKit.errorData(error),
|
|
5164
5184
|
message: functoolsKit.getErrorMessage(error),
|
|
5165
5185
|
};
|
|
5166
|
-
|
|
5186
|
+
bt.loggerService.warn(message, payload);
|
|
5167
5187
|
console.warn(message, payload);
|
|
5168
5188
|
validationSubject.next(error);
|
|
5169
5189
|
},
|
|
@@ -5172,9 +5192,15 @@ const DO_VALIDATION_FN = functoolsKit.trycatch(async (validation, params) => {
|
|
|
5172
5192
|
* Initializes active positions by reading from persistence.
|
|
5173
5193
|
* Uses singleshot pattern to ensure it only runs once.
|
|
5174
5194
|
* This function is exported for use in tests or other modules.
|
|
5195
|
+
*
|
|
5196
|
+
* In backtest mode, initializes with empty Map. In live mode, reads from persist storage.
|
|
5175
5197
|
*/
|
|
5176
5198
|
const WAIT_FOR_INIT_FN$1 = async (self) => {
|
|
5177
|
-
self.params.logger.debug("ClientRisk waitForInit");
|
|
5199
|
+
self.params.logger.debug("ClientRisk waitForInit", { backtest: self.params.backtest });
|
|
5200
|
+
if (self.params.backtest) {
|
|
5201
|
+
self._activePositions = new Map();
|
|
5202
|
+
return;
|
|
5203
|
+
}
|
|
5178
5204
|
const persistedPositions = await PersistRiskAdapter.readPositionData(self.params.riskName);
|
|
5179
5205
|
self._activePositions = new Map(persistedPositions);
|
|
5180
5206
|
};
|
|
@@ -5222,6 +5248,7 @@ class ClientRisk {
|
|
|
5222
5248
|
this.params.logger.debug("ClientRisk checkSignal", {
|
|
5223
5249
|
symbol: params.symbol,
|
|
5224
5250
|
strategyName: params.strategyName,
|
|
5251
|
+
backtest: this.params.backtest,
|
|
5225
5252
|
});
|
|
5226
5253
|
if (this._activePositions === POSITION_NEED_FETCH) {
|
|
5227
5254
|
await this.waitForInit();
|
|
@@ -5251,7 +5278,7 @@ class ClientRisk {
|
|
|
5251
5278
|
}
|
|
5252
5279
|
if (!isValid) {
|
|
5253
5280
|
// Call params.onRejected for riskSubject emission
|
|
5254
|
-
await this.params.onRejected(params.symbol, params, riskMap.size, rejectionNote, Date.now());
|
|
5281
|
+
await this.params.onRejected(params.symbol, params, riskMap.size, rejectionNote, Date.now(), this.params.backtest);
|
|
5255
5282
|
// Call schema callbacks.onRejected if defined
|
|
5256
5283
|
if (this.params.callbacks?.onRejected) {
|
|
5257
5284
|
this.params.callbacks.onRejected(params.symbol, params);
|
|
@@ -5267,8 +5294,12 @@ class ClientRisk {
|
|
|
5267
5294
|
}
|
|
5268
5295
|
/**
|
|
5269
5296
|
* Persists current active positions to disk.
|
|
5297
|
+
* Skips in backtest mode.
|
|
5270
5298
|
*/
|
|
5271
5299
|
async _updatePositions() {
|
|
5300
|
+
if (this.params.backtest) {
|
|
5301
|
+
return;
|
|
5302
|
+
}
|
|
5272
5303
|
if (this._activePositions === POSITION_NEED_FETCH) {
|
|
5273
5304
|
await this.waitForInit();
|
|
5274
5305
|
}
|
|
@@ -5282,6 +5313,7 @@ class ClientRisk {
|
|
|
5282
5313
|
this.params.logger.debug("ClientRisk addSignal", {
|
|
5283
5314
|
symbol,
|
|
5284
5315
|
context,
|
|
5316
|
+
backtest: this.params.backtest,
|
|
5285
5317
|
});
|
|
5286
5318
|
if (this._activePositions === POSITION_NEED_FETCH) {
|
|
5287
5319
|
await this.waitForInit();
|
|
@@ -5304,6 +5336,7 @@ class ClientRisk {
|
|
|
5304
5336
|
this.params.logger.debug("ClientRisk removeSignal", {
|
|
5305
5337
|
symbol,
|
|
5306
5338
|
context,
|
|
5339
|
+
backtest: this.params.backtest,
|
|
5307
5340
|
});
|
|
5308
5341
|
if (this._activePositions === POSITION_NEED_FETCH) {
|
|
5309
5342
|
await this.waitForInit();
|
|
@@ -5326,8 +5359,9 @@ class ClientRisk {
|
|
|
5326
5359
|
* @param activePositionCount - Number of active positions at rejection time
|
|
5327
5360
|
* @param comment - Rejection reason from validation note or "N/A"
|
|
5328
5361
|
* @param timestamp - Event timestamp in milliseconds
|
|
5362
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
5329
5363
|
*/
|
|
5330
|
-
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, comment, timestamp) => await riskSubject.next({
|
|
5364
|
+
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, comment, timestamp, backtest) => await riskSubject.next({
|
|
5331
5365
|
symbol,
|
|
5332
5366
|
pendingSignal: params.pendingSignal,
|
|
5333
5367
|
strategyName: params.strategyName,
|
|
@@ -5336,6 +5370,7 @@ const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, comment,
|
|
|
5336
5370
|
activePositionCount,
|
|
5337
5371
|
comment,
|
|
5338
5372
|
timestamp,
|
|
5373
|
+
backtest,
|
|
5339
5374
|
});
|
|
5340
5375
|
/**
|
|
5341
5376
|
* Connection service routing risk operations to correct ClientRisk instance.
|
|
@@ -5374,19 +5409,21 @@ class RiskConnectionService {
|
|
|
5374
5409
|
this.loggerService = inject(TYPES.loggerService);
|
|
5375
5410
|
this.riskSchemaService = inject(TYPES.riskSchemaService);
|
|
5376
5411
|
/**
|
|
5377
|
-
* Retrieves memoized ClientRisk instance for given risk name.
|
|
5412
|
+
* Retrieves memoized ClientRisk instance for given risk name and backtest mode.
|
|
5378
5413
|
*
|
|
5379
5414
|
* Creates ClientRisk on first call, returns cached instance on subsequent calls.
|
|
5380
|
-
* Cache key is riskName string.
|
|
5415
|
+
* Cache key is "riskName:backtest" string to separate live and backtest instances.
|
|
5381
5416
|
*
|
|
5382
5417
|
* @param riskName - Name of registered risk schema
|
|
5418
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
5383
5419
|
* @returns Configured ClientRisk instance
|
|
5384
5420
|
*/
|
|
5385
|
-
this.getRisk = functoolsKit.memoize(([riskName]) => `${riskName}`, (riskName) => {
|
|
5421
|
+
this.getRisk = functoolsKit.memoize(([riskName, backtest]) => `${riskName}:${backtest ? "backtest" : "live"}`, (riskName, backtest) => {
|
|
5386
5422
|
const schema = this.riskSchemaService.get(riskName);
|
|
5387
5423
|
return new ClientRisk({
|
|
5388
5424
|
...schema,
|
|
5389
5425
|
logger: this.loggerService,
|
|
5426
|
+
backtest,
|
|
5390
5427
|
onRejected: COMMIT_REJECTION_FN,
|
|
5391
5428
|
});
|
|
5392
5429
|
});
|
|
@@ -5398,7 +5435,7 @@ class RiskConnectionService {
|
|
|
5398
5435
|
* ClientRisk will emit riskSubject event via onRejected callback when signal is rejected.
|
|
5399
5436
|
*
|
|
5400
5437
|
* @param params - Risk check arguments (portfolio state, position details)
|
|
5401
|
-
* @param context - Execution context with risk name
|
|
5438
|
+
* @param context - Execution context with risk name and backtest mode
|
|
5402
5439
|
* @returns Promise resolving to risk check result
|
|
5403
5440
|
*/
|
|
5404
5441
|
this.checkSignal = async (params, context) => {
|
|
@@ -5406,46 +5443,48 @@ class RiskConnectionService {
|
|
|
5406
5443
|
symbol: params.symbol,
|
|
5407
5444
|
context,
|
|
5408
5445
|
});
|
|
5409
|
-
return await this.getRisk(context.riskName).checkSignal(params);
|
|
5446
|
+
return await this.getRisk(context.riskName, context.backtest).checkSignal(params);
|
|
5410
5447
|
};
|
|
5411
5448
|
/**
|
|
5412
5449
|
* Registers an opened signal with the risk management system.
|
|
5413
5450
|
* Routes to appropriate ClientRisk instance.
|
|
5414
5451
|
*
|
|
5415
5452
|
* @param symbol - Trading pair symbol
|
|
5416
|
-
* @param context - Context information (strategyName, riskName)
|
|
5453
|
+
* @param context - Context information (strategyName, riskName, backtest)
|
|
5417
5454
|
*/
|
|
5418
5455
|
this.addSignal = async (symbol, context) => {
|
|
5419
5456
|
this.loggerService.log("riskConnectionService addSignal", {
|
|
5420
5457
|
symbol,
|
|
5421
5458
|
context,
|
|
5422
5459
|
});
|
|
5423
|
-
await this.getRisk(context.riskName).addSignal(symbol, context);
|
|
5460
|
+
await this.getRisk(context.riskName, context.backtest).addSignal(symbol, context);
|
|
5424
5461
|
};
|
|
5425
5462
|
/**
|
|
5426
5463
|
* Removes a closed signal from the risk management system.
|
|
5427
5464
|
* Routes to appropriate ClientRisk instance.
|
|
5428
5465
|
*
|
|
5429
5466
|
* @param symbol - Trading pair symbol
|
|
5430
|
-
* @param context - Context information (strategyName, riskName)
|
|
5467
|
+
* @param context - Context information (strategyName, riskName, backtest)
|
|
5431
5468
|
*/
|
|
5432
5469
|
this.removeSignal = async (symbol, context) => {
|
|
5433
5470
|
this.loggerService.log("riskConnectionService removeSignal", {
|
|
5434
5471
|
symbol,
|
|
5435
5472
|
context,
|
|
5436
5473
|
});
|
|
5437
|
-
await this.getRisk(context.riskName).removeSignal(symbol, context);
|
|
5474
|
+
await this.getRisk(context.riskName, context.backtest).removeSignal(symbol, context);
|
|
5438
5475
|
};
|
|
5439
5476
|
/**
|
|
5440
5477
|
* Clears the cached ClientRisk instance for the given risk name.
|
|
5441
5478
|
*
|
|
5442
5479
|
* @param riskName - Name of the risk schema to clear from cache
|
|
5443
5480
|
*/
|
|
5444
|
-
this.clear = async (riskName) => {
|
|
5481
|
+
this.clear = async (backtest, riskName) => {
|
|
5445
5482
|
this.loggerService.log("riskConnectionService clear", {
|
|
5446
5483
|
riskName,
|
|
5484
|
+
backtest,
|
|
5447
5485
|
});
|
|
5448
|
-
|
|
5486
|
+
const key = `${riskName}:${backtest ? "backtest" : "live"}`;
|
|
5487
|
+
this.getRisk.clear(key);
|
|
5449
5488
|
};
|
|
5450
5489
|
}
|
|
5451
5490
|
}
|
|
@@ -5668,7 +5707,7 @@ class StrategyCoreService {
|
|
|
5668
5707
|
* @param strategyName - Name of the strategy
|
|
5669
5708
|
* @returns Promise resolving to pending signal or null
|
|
5670
5709
|
*/
|
|
5671
|
-
this.getPendingSignal = async (symbol, strategyName) => {
|
|
5710
|
+
this.getPendingSignal = async (backtest, symbol, strategyName) => {
|
|
5672
5711
|
this.loggerService.log("strategyCoreService getPendingSignal", {
|
|
5673
5712
|
symbol,
|
|
5674
5713
|
strategyName,
|
|
@@ -5677,7 +5716,7 @@ class StrategyCoreService {
|
|
|
5677
5716
|
throw new Error("strategyCoreService getPendingSignal requires a method context");
|
|
5678
5717
|
}
|
|
5679
5718
|
await this.validate(symbol, strategyName);
|
|
5680
|
-
return await this.strategyConnectionService.getPendingSignal(symbol, strategyName);
|
|
5719
|
+
return await this.strategyConnectionService.getPendingSignal(backtest, symbol, strategyName);
|
|
5681
5720
|
};
|
|
5682
5721
|
/**
|
|
5683
5722
|
* Checks if the strategy has been stopped.
|
|
@@ -5689,16 +5728,17 @@ class StrategyCoreService {
|
|
|
5689
5728
|
* @param strategyName - Name of the strategy
|
|
5690
5729
|
* @returns Promise resolving to true if strategy is stopped, false otherwise
|
|
5691
5730
|
*/
|
|
5692
|
-
this.getStopped = async (symbol, strategyName) => {
|
|
5731
|
+
this.getStopped = async (backtest, symbol, strategyName) => {
|
|
5693
5732
|
this.loggerService.log("strategyCoreService getStopped", {
|
|
5694
5733
|
symbol,
|
|
5695
5734
|
strategyName,
|
|
5735
|
+
backtest,
|
|
5696
5736
|
});
|
|
5697
5737
|
if (!MethodContextService.hasContext()) {
|
|
5698
5738
|
throw new Error("strategyCoreService getStopped requires a method context");
|
|
5699
5739
|
}
|
|
5700
5740
|
await this.validate(symbol, strategyName);
|
|
5701
|
-
return await this.strategyConnectionService.getStopped(symbol, strategyName);
|
|
5741
|
+
return await this.strategyConnectionService.getStopped(backtest, symbol, strategyName);
|
|
5702
5742
|
};
|
|
5703
5743
|
/**
|
|
5704
5744
|
* Checks signal status at a specific timestamp.
|
|
@@ -5772,13 +5812,13 @@ class StrategyCoreService {
|
|
|
5772
5812
|
* @param strategyName - Name of strategy to stop
|
|
5773
5813
|
* @returns Promise that resolves when stop flag is set
|
|
5774
5814
|
*/
|
|
5775
|
-
this.stop = async (
|
|
5815
|
+
this.stop = async (backtest, ctx) => {
|
|
5776
5816
|
this.loggerService.log("strategyCoreService stop", {
|
|
5777
5817
|
ctx,
|
|
5778
5818
|
backtest,
|
|
5779
5819
|
});
|
|
5780
5820
|
await this.validate(ctx.symbol, ctx.strategyName);
|
|
5781
|
-
return await this.strategyConnectionService.stop(
|
|
5821
|
+
return await this.strategyConnectionService.stop(backtest, ctx);
|
|
5782
5822
|
};
|
|
5783
5823
|
/**
|
|
5784
5824
|
* Clears the memoized ClientStrategy instance from cache.
|
|
@@ -5788,14 +5828,14 @@ class StrategyCoreService {
|
|
|
5788
5828
|
*
|
|
5789
5829
|
* @param ctx - Optional context with symbol and strategyName (clears all if not provided)
|
|
5790
5830
|
*/
|
|
5791
|
-
this.clear = async (ctx) => {
|
|
5831
|
+
this.clear = async (backtest, ctx) => {
|
|
5792
5832
|
this.loggerService.log("strategyCoreService clear", {
|
|
5793
5833
|
ctx,
|
|
5794
5834
|
});
|
|
5795
5835
|
if (ctx) {
|
|
5796
5836
|
await this.validate(ctx.symbol, ctx.strategyName);
|
|
5797
5837
|
}
|
|
5798
|
-
return await this.strategyConnectionService.clear(ctx);
|
|
5838
|
+
return await this.strategyConnectionService.clear(backtest, ctx);
|
|
5799
5839
|
};
|
|
5800
5840
|
}
|
|
5801
5841
|
}
|
|
@@ -5936,14 +5976,15 @@ class RiskGlobalService {
|
|
|
5936
5976
|
* If no riskName is provided, clears all risk data.
|
|
5937
5977
|
* @param riskName - Optional name of the risk instance to clear
|
|
5938
5978
|
*/
|
|
5939
|
-
this.clear = async (riskName) => {
|
|
5979
|
+
this.clear = async (backtest, riskName) => {
|
|
5940
5980
|
this.loggerService.log("riskGlobalService clear", {
|
|
5941
5981
|
riskName,
|
|
5982
|
+
backtest,
|
|
5942
5983
|
});
|
|
5943
5984
|
if (riskName) {
|
|
5944
5985
|
await this.validate(riskName);
|
|
5945
5986
|
}
|
|
5946
|
-
return await this.riskConnectionService.clear(riskName);
|
|
5987
|
+
return await this.riskConnectionService.clear(backtest, riskName);
|
|
5947
5988
|
};
|
|
5948
5989
|
}
|
|
5949
5990
|
}
|
|
@@ -6487,7 +6528,7 @@ class BacktestLogicPrivateService {
|
|
|
6487
6528
|
});
|
|
6488
6529
|
}
|
|
6489
6530
|
// Check if strategy should stop before processing next frame
|
|
6490
|
-
if (await this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName)) {
|
|
6531
|
+
if (await this.strategyCoreService.getStopped(true, symbol, this.methodContextService.context.strategyName)) {
|
|
6491
6532
|
this.loggerService.info("backtestLogicPrivateService stopped by user request (before tick)", {
|
|
6492
6533
|
symbol,
|
|
6493
6534
|
when: when.toISOString(),
|
|
@@ -6512,7 +6553,7 @@ class BacktestLogicPrivateService {
|
|
|
6512
6553
|
continue;
|
|
6513
6554
|
}
|
|
6514
6555
|
// Check if strategy should stop when idle (no active signal)
|
|
6515
|
-
if (await functoolsKit.and(Promise.resolve(result.action === "idle"), this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName))) {
|
|
6556
|
+
if (await functoolsKit.and(Promise.resolve(result.action === "idle"), this.strategyCoreService.getStopped(true, symbol, this.methodContextService.context.strategyName))) {
|
|
6516
6557
|
this.loggerService.info("backtestLogicPrivateService stopped by user request (idle state)", {
|
|
6517
6558
|
symbol,
|
|
6518
6559
|
when: when.toISOString(),
|
|
@@ -6614,7 +6655,7 @@ class BacktestLogicPrivateService {
|
|
|
6614
6655
|
}
|
|
6615
6656
|
yield backtestResult;
|
|
6616
6657
|
// Check if strategy should stop after signal is closed
|
|
6617
|
-
if (await this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName)) {
|
|
6658
|
+
if (await this.strategyCoreService.getStopped(true, symbol, this.methodContextService.context.strategyName)) {
|
|
6618
6659
|
this.loggerService.info("backtestLogicPrivateService stopped by user request (after scheduled signal closed)", {
|
|
6619
6660
|
symbol,
|
|
6620
6661
|
signalId: backtestResult.signal.id,
|
|
@@ -6707,7 +6748,7 @@ class BacktestLogicPrivateService {
|
|
|
6707
6748
|
}
|
|
6708
6749
|
yield backtestResult;
|
|
6709
6750
|
// Check if strategy should stop after signal is closed
|
|
6710
|
-
if (await this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName)) {
|
|
6751
|
+
if (await this.strategyCoreService.getStopped(true, symbol, this.methodContextService.context.strategyName)) {
|
|
6711
6752
|
this.loggerService.info("backtestLogicPrivateService stopped by user request (after signal closed)", {
|
|
6712
6753
|
symbol,
|
|
6713
6754
|
signalId: backtestResult.signal.id,
|
|
@@ -6850,7 +6891,7 @@ class LiveLogicPrivateService {
|
|
|
6850
6891
|
previousEventTimestamp = currentTimestamp;
|
|
6851
6892
|
// Check if strategy should stop when idle (no active signal)
|
|
6852
6893
|
if (result.action === "idle") {
|
|
6853
|
-
if (await functoolsKit.and(Promise.resolve(true), this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName))) {
|
|
6894
|
+
if (await functoolsKit.and(Promise.resolve(true), this.strategyCoreService.getStopped(false, symbol, this.methodContextService.context.strategyName))) {
|
|
6854
6895
|
this.loggerService.info("liveLogicPrivateService stopped by user request (idle state)", {
|
|
6855
6896
|
symbol,
|
|
6856
6897
|
when: when.toISOString(),
|
|
@@ -6872,7 +6913,7 @@ class LiveLogicPrivateService {
|
|
|
6872
6913
|
yield result;
|
|
6873
6914
|
// Check if strategy should stop after signal is closed
|
|
6874
6915
|
if (result.action === "closed") {
|
|
6875
|
-
if (await this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName)) {
|
|
6916
|
+
if (await this.strategyCoreService.getStopped(false, symbol, this.methodContextService.context.strategyName)) {
|
|
6876
6917
|
this.loggerService.info("liveLogicPrivateService stopped by user request (after signal closed)", {
|
|
6877
6918
|
symbol,
|
|
6878
6919
|
signalId: result.signal.id,
|
|
@@ -7004,7 +7045,7 @@ class WalkerLogicPrivateService {
|
|
|
7004
7045
|
symbol,
|
|
7005
7046
|
});
|
|
7006
7047
|
// Get statistics from BacktestMarkdownService
|
|
7007
|
-
const stats = await this.backtestMarkdownService.getData(symbol, strategyName);
|
|
7048
|
+
const stats = await this.backtestMarkdownService.getData(symbol, strategyName, true);
|
|
7008
7049
|
// Extract metric value
|
|
7009
7050
|
const value = stats[metric];
|
|
7010
7051
|
const metricValue = value !== null &&
|
|
@@ -7068,7 +7109,7 @@ class WalkerLogicPrivateService {
|
|
|
7068
7109
|
bestStrategy,
|
|
7069
7110
|
bestMetric,
|
|
7070
7111
|
bestStats: bestStrategy !== null
|
|
7071
|
-
? await this.backtestMarkdownService.getData(symbol, bestStrategy)
|
|
7112
|
+
? await this.backtestMarkdownService.getData(symbol, bestStrategy, true)
|
|
7072
7113
|
: null,
|
|
7073
7114
|
};
|
|
7074
7115
|
// Call onComplete callback if provided with final best results
|
|
@@ -7581,10 +7622,10 @@ class BacktestMarkdownService {
|
|
|
7581
7622
|
/** Logger service for debug output */
|
|
7582
7623
|
this.loggerService = inject(TYPES.loggerService);
|
|
7583
7624
|
/**
|
|
7584
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
7585
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
7625
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
7626
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
7586
7627
|
*/
|
|
7587
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$5());
|
|
7628
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$5());
|
|
7588
7629
|
/**
|
|
7589
7630
|
* Processes tick events and accumulates closed signals.
|
|
7590
7631
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -7611,7 +7652,7 @@ class BacktestMarkdownService {
|
|
|
7611
7652
|
if (data.action !== "closed") {
|
|
7612
7653
|
return;
|
|
7613
7654
|
}
|
|
7614
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
7655
|
+
const storage = this.getStorage(data.symbol, data.strategyName, true);
|
|
7615
7656
|
storage.addSignal(data);
|
|
7616
7657
|
};
|
|
7617
7658
|
/**
|
|
@@ -7620,21 +7661,23 @@ class BacktestMarkdownService {
|
|
|
7620
7661
|
*
|
|
7621
7662
|
* @param symbol - Trading pair symbol
|
|
7622
7663
|
* @param strategyName - Strategy name to get data for
|
|
7664
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
7623
7665
|
* @returns Statistical data object with all metrics
|
|
7624
7666
|
*
|
|
7625
7667
|
* @example
|
|
7626
7668
|
* ```typescript
|
|
7627
7669
|
* const service = new BacktestMarkdownService();
|
|
7628
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
7670
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", true);
|
|
7629
7671
|
* console.log(stats.sharpeRatio, stats.winRate);
|
|
7630
7672
|
* ```
|
|
7631
7673
|
*/
|
|
7632
|
-
this.getData = async (symbol, strategyName) => {
|
|
7674
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
7633
7675
|
this.loggerService.log("backtestMarkdownService getData", {
|
|
7634
7676
|
symbol,
|
|
7635
7677
|
strategyName,
|
|
7678
|
+
backtest,
|
|
7636
7679
|
});
|
|
7637
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
7680
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
7638
7681
|
return storage.getData();
|
|
7639
7682
|
};
|
|
7640
7683
|
/**
|
|
@@ -7643,22 +7686,24 @@ class BacktestMarkdownService {
|
|
|
7643
7686
|
*
|
|
7644
7687
|
* @param symbol - Trading pair symbol
|
|
7645
7688
|
* @param strategyName - Strategy name to generate report for
|
|
7689
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
7646
7690
|
* @param columns - Column configuration for formatting the table
|
|
7647
7691
|
* @returns Markdown formatted report string with table of all closed signals
|
|
7648
7692
|
*
|
|
7649
7693
|
* @example
|
|
7650
7694
|
* ```typescript
|
|
7651
7695
|
* const service = new BacktestMarkdownService();
|
|
7652
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
7696
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", true);
|
|
7653
7697
|
* console.log(markdown);
|
|
7654
7698
|
* ```
|
|
7655
7699
|
*/
|
|
7656
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7700
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7657
7701
|
this.loggerService.log("backtestMarkdownService getReport", {
|
|
7658
7702
|
symbol,
|
|
7659
7703
|
strategyName,
|
|
7704
|
+
backtest,
|
|
7660
7705
|
});
|
|
7661
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
7706
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
7662
7707
|
return storage.getReport(strategyName, columns);
|
|
7663
7708
|
};
|
|
7664
7709
|
/**
|
|
@@ -7668,6 +7713,7 @@ class BacktestMarkdownService {
|
|
|
7668
7713
|
*
|
|
7669
7714
|
* @param symbol - Trading pair symbol
|
|
7670
7715
|
* @param strategyName - Strategy name to save report for
|
|
7716
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
7671
7717
|
* @param path - Directory path to save report (default: "./dump/backtest")
|
|
7672
7718
|
* @param columns - Column configuration for formatting the table
|
|
7673
7719
|
*
|
|
@@ -7676,45 +7722,48 @@ class BacktestMarkdownService {
|
|
|
7676
7722
|
* const service = new BacktestMarkdownService();
|
|
7677
7723
|
*
|
|
7678
7724
|
* // Save to default path: ./dump/backtest/my-strategy.md
|
|
7679
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
7725
|
+
* await service.dump("BTCUSDT", "my-strategy", true);
|
|
7680
7726
|
*
|
|
7681
7727
|
* // Save to custom path: ./custom/path/my-strategy.md
|
|
7682
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
7728
|
+
* await service.dump("BTCUSDT", "my-strategy", true, "./custom/path");
|
|
7683
7729
|
* ```
|
|
7684
7730
|
*/
|
|
7685
|
-
this.dump = async (symbol, strategyName, path = "./dump/backtest", columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7731
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/backtest", columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7686
7732
|
this.loggerService.log("backtestMarkdownService dump", {
|
|
7687
7733
|
symbol,
|
|
7688
7734
|
strategyName,
|
|
7735
|
+
backtest,
|
|
7689
7736
|
path,
|
|
7690
7737
|
});
|
|
7691
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
7738
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
7692
7739
|
await storage.dump(strategyName, path, columns);
|
|
7693
7740
|
};
|
|
7694
7741
|
/**
|
|
7695
7742
|
* Clears accumulated signal data from storage.
|
|
7696
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
7743
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
7697
7744
|
* If nothing is provided, clears all data.
|
|
7698
7745
|
*
|
|
7746
|
+
* @param backtest - Backtest mode flag
|
|
7699
7747
|
* @param ctx - Optional context with symbol and strategyName
|
|
7700
7748
|
*
|
|
7701
7749
|
* @example
|
|
7702
7750
|
* ```typescript
|
|
7703
7751
|
* const service = new BacktestMarkdownService();
|
|
7704
7752
|
*
|
|
7705
|
-
* // Clear specific symbol-strategy
|
|
7706
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
7753
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
7754
|
+
* await service.clear(true, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
7707
7755
|
*
|
|
7708
7756
|
* // Clear all data
|
|
7709
7757
|
* await service.clear();
|
|
7710
7758
|
* ```
|
|
7711
7759
|
*/
|
|
7712
|
-
this.clear = async (ctx) => {
|
|
7760
|
+
this.clear = async (backtest, ctx) => {
|
|
7713
7761
|
this.loggerService.log("backtestMarkdownService clear", {
|
|
7762
|
+
backtest,
|
|
7714
7763
|
ctx,
|
|
7715
7764
|
});
|
|
7716
7765
|
if (ctx) {
|
|
7717
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
7766
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
7718
7767
|
this.getStorage.clear(key);
|
|
7719
7768
|
}
|
|
7720
7769
|
else {
|
|
@@ -8065,10 +8114,10 @@ class LiveMarkdownService {
|
|
|
8065
8114
|
/** Logger service for debug output */
|
|
8066
8115
|
this.loggerService = inject(TYPES.loggerService);
|
|
8067
8116
|
/**
|
|
8068
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
8069
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
8117
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
8118
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
8070
8119
|
*/
|
|
8071
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$4());
|
|
8120
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$4());
|
|
8072
8121
|
/**
|
|
8073
8122
|
* Processes tick events and accumulates all event types.
|
|
8074
8123
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -8094,7 +8143,7 @@ class LiveMarkdownService {
|
|
|
8094
8143
|
this.loggerService.log("liveMarkdownService tick", {
|
|
8095
8144
|
data,
|
|
8096
8145
|
});
|
|
8097
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
8146
|
+
const storage = this.getStorage(data.symbol, data.strategyName, false);
|
|
8098
8147
|
if (data.action === "idle") {
|
|
8099
8148
|
storage.addIdleEvent(data.currentPrice);
|
|
8100
8149
|
}
|
|
@@ -8114,21 +8163,23 @@ class LiveMarkdownService {
|
|
|
8114
8163
|
*
|
|
8115
8164
|
* @param symbol - Trading pair symbol
|
|
8116
8165
|
* @param strategyName - Strategy name to get data for
|
|
8166
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8117
8167
|
* @returns Statistical data object with all metrics
|
|
8118
8168
|
*
|
|
8119
8169
|
* @example
|
|
8120
8170
|
* ```typescript
|
|
8121
8171
|
* const service = new LiveMarkdownService();
|
|
8122
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
8172
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
8123
8173
|
* console.log(stats.sharpeRatio, stats.winRate);
|
|
8124
8174
|
* ```
|
|
8125
8175
|
*/
|
|
8126
|
-
this.getData = async (symbol, strategyName) => {
|
|
8176
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
8127
8177
|
this.loggerService.log("liveMarkdownService getData", {
|
|
8128
8178
|
symbol,
|
|
8129
8179
|
strategyName,
|
|
8180
|
+
backtest,
|
|
8130
8181
|
});
|
|
8131
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8182
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8132
8183
|
return storage.getData();
|
|
8133
8184
|
};
|
|
8134
8185
|
/**
|
|
@@ -8137,22 +8188,24 @@ class LiveMarkdownService {
|
|
|
8137
8188
|
*
|
|
8138
8189
|
* @param symbol - Trading pair symbol
|
|
8139
8190
|
* @param strategyName - Strategy name to generate report for
|
|
8191
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8140
8192
|
* @param columns - Column configuration for formatting the table
|
|
8141
8193
|
* @returns Markdown formatted report string with table of all events
|
|
8142
8194
|
*
|
|
8143
8195
|
* @example
|
|
8144
8196
|
* ```typescript
|
|
8145
8197
|
* const service = new LiveMarkdownService();
|
|
8146
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
8198
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
8147
8199
|
* console.log(markdown);
|
|
8148
8200
|
* ```
|
|
8149
8201
|
*/
|
|
8150
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.live_columns) => {
|
|
8202
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.live_columns) => {
|
|
8151
8203
|
this.loggerService.log("liveMarkdownService getReport", {
|
|
8152
8204
|
symbol,
|
|
8153
8205
|
strategyName,
|
|
8206
|
+
backtest,
|
|
8154
8207
|
});
|
|
8155
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8208
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8156
8209
|
return storage.getReport(strategyName, columns);
|
|
8157
8210
|
};
|
|
8158
8211
|
/**
|
|
@@ -8162,6 +8215,7 @@ class LiveMarkdownService {
|
|
|
8162
8215
|
*
|
|
8163
8216
|
* @param symbol - Trading pair symbol
|
|
8164
8217
|
* @param strategyName - Strategy name to save report for
|
|
8218
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8165
8219
|
* @param path - Directory path to save report (default: "./dump/live")
|
|
8166
8220
|
* @param columns - Column configuration for formatting the table
|
|
8167
8221
|
*
|
|
@@ -8170,45 +8224,48 @@ class LiveMarkdownService {
|
|
|
8170
8224
|
* const service = new LiveMarkdownService();
|
|
8171
8225
|
*
|
|
8172
8226
|
* // Save to default path: ./dump/live/my-strategy.md
|
|
8173
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
8227
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
8174
8228
|
*
|
|
8175
8229
|
* // Save to custom path: ./custom/path/my-strategy.md
|
|
8176
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
8230
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
8177
8231
|
* ```
|
|
8178
8232
|
*/
|
|
8179
|
-
this.dump = async (symbol, strategyName, path = "./dump/live", columns = COLUMN_CONFIG.live_columns) => {
|
|
8233
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/live", columns = COLUMN_CONFIG.live_columns) => {
|
|
8180
8234
|
this.loggerService.log("liveMarkdownService dump", {
|
|
8181
8235
|
symbol,
|
|
8182
8236
|
strategyName,
|
|
8237
|
+
backtest,
|
|
8183
8238
|
path,
|
|
8184
8239
|
});
|
|
8185
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8240
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8186
8241
|
await storage.dump(strategyName, path, columns);
|
|
8187
8242
|
};
|
|
8188
8243
|
/**
|
|
8189
8244
|
* Clears accumulated event data from storage.
|
|
8190
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
8245
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
8191
8246
|
* If nothing is provided, clears all data.
|
|
8192
8247
|
*
|
|
8248
|
+
* @param backtest - Backtest mode flag
|
|
8193
8249
|
* @param ctx - Optional context with symbol and strategyName
|
|
8194
8250
|
*
|
|
8195
8251
|
* @example
|
|
8196
8252
|
* ```typescript
|
|
8197
8253
|
* const service = new LiveMarkdownService();
|
|
8198
8254
|
*
|
|
8199
|
-
* // Clear specific symbol-strategy
|
|
8200
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8255
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
8256
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8201
8257
|
*
|
|
8202
8258
|
* // Clear all data
|
|
8203
8259
|
* await service.clear();
|
|
8204
8260
|
* ```
|
|
8205
8261
|
*/
|
|
8206
|
-
this.clear = async (ctx) => {
|
|
8262
|
+
this.clear = async (backtest, ctx) => {
|
|
8207
8263
|
this.loggerService.log("liveMarkdownService clear", {
|
|
8264
|
+
backtest,
|
|
8208
8265
|
ctx,
|
|
8209
8266
|
});
|
|
8210
8267
|
if (ctx) {
|
|
8211
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
8268
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
8212
8269
|
this.getStorage.clear(key);
|
|
8213
8270
|
}
|
|
8214
8271
|
else {
|
|
@@ -8463,10 +8520,10 @@ class ScheduleMarkdownService {
|
|
|
8463
8520
|
/** Logger service for debug output */
|
|
8464
8521
|
this.loggerService = inject(TYPES.loggerService);
|
|
8465
8522
|
/**
|
|
8466
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
8467
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
8523
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
8524
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
8468
8525
|
*/
|
|
8469
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$3());
|
|
8526
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$3());
|
|
8470
8527
|
/**
|
|
8471
8528
|
* Processes tick events and accumulates scheduled/opened/cancelled events.
|
|
8472
8529
|
* Should be called from signalEmitter subscription.
|
|
@@ -8485,7 +8542,7 @@ class ScheduleMarkdownService {
|
|
|
8485
8542
|
this.loggerService.log("scheduleMarkdownService tick", {
|
|
8486
8543
|
data,
|
|
8487
8544
|
});
|
|
8488
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
8545
|
+
const storage = this.getStorage(data.symbol, data.strategyName, data.backtest);
|
|
8489
8546
|
if (data.action === "scheduled") {
|
|
8490
8547
|
storage.addScheduledEvent(data);
|
|
8491
8548
|
}
|
|
@@ -8506,21 +8563,23 @@ class ScheduleMarkdownService {
|
|
|
8506
8563
|
*
|
|
8507
8564
|
* @param symbol - Trading pair symbol
|
|
8508
8565
|
* @param strategyName - Strategy name to get data for
|
|
8566
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8509
8567
|
* @returns Statistical data object with all metrics
|
|
8510
8568
|
*
|
|
8511
8569
|
* @example
|
|
8512
8570
|
* ```typescript
|
|
8513
8571
|
* const service = new ScheduleMarkdownService();
|
|
8514
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
8572
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
8515
8573
|
* console.log(stats.cancellationRate, stats.avgWaitTime);
|
|
8516
8574
|
* ```
|
|
8517
8575
|
*/
|
|
8518
|
-
this.getData = async (symbol, strategyName) => {
|
|
8576
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
8519
8577
|
this.loggerService.log("scheduleMarkdownService getData", {
|
|
8520
8578
|
symbol,
|
|
8521
8579
|
strategyName,
|
|
8580
|
+
backtest,
|
|
8522
8581
|
});
|
|
8523
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8582
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8524
8583
|
return storage.getData();
|
|
8525
8584
|
};
|
|
8526
8585
|
/**
|
|
@@ -8529,22 +8588,24 @@ class ScheduleMarkdownService {
|
|
|
8529
8588
|
*
|
|
8530
8589
|
* @param symbol - Trading pair symbol
|
|
8531
8590
|
* @param strategyName - Strategy name to generate report for
|
|
8591
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8532
8592
|
* @param columns - Column configuration for formatting the table
|
|
8533
8593
|
* @returns Markdown formatted report string with table of all events
|
|
8534
8594
|
*
|
|
8535
8595
|
* @example
|
|
8536
8596
|
* ```typescript
|
|
8537
8597
|
* const service = new ScheduleMarkdownService();
|
|
8538
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
8598
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
8539
8599
|
* console.log(markdown);
|
|
8540
8600
|
* ```
|
|
8541
8601
|
*/
|
|
8542
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8602
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8543
8603
|
this.loggerService.log("scheduleMarkdownService getReport", {
|
|
8544
8604
|
symbol,
|
|
8545
8605
|
strategyName,
|
|
8606
|
+
backtest,
|
|
8546
8607
|
});
|
|
8547
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8608
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8548
8609
|
return storage.getReport(strategyName, columns);
|
|
8549
8610
|
};
|
|
8550
8611
|
/**
|
|
@@ -8554,6 +8615,7 @@ class ScheduleMarkdownService {
|
|
|
8554
8615
|
*
|
|
8555
8616
|
* @param symbol - Trading pair symbol
|
|
8556
8617
|
* @param strategyName - Strategy name to save report for
|
|
8618
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8557
8619
|
* @param path - Directory path to save report (default: "./dump/schedule")
|
|
8558
8620
|
* @param columns - Column configuration for formatting the table
|
|
8559
8621
|
*
|
|
@@ -8562,45 +8624,48 @@ class ScheduleMarkdownService {
|
|
|
8562
8624
|
* const service = new ScheduleMarkdownService();
|
|
8563
8625
|
*
|
|
8564
8626
|
* // Save to default path: ./dump/schedule/my-strategy.md
|
|
8565
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
8627
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
8566
8628
|
*
|
|
8567
8629
|
* // Save to custom path: ./custom/path/my-strategy.md
|
|
8568
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
8630
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
8569
8631
|
* ```
|
|
8570
8632
|
*/
|
|
8571
|
-
this.dump = async (symbol, strategyName, path = "./dump/schedule", columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8633
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/schedule", columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8572
8634
|
this.loggerService.log("scheduleMarkdownService dump", {
|
|
8573
8635
|
symbol,
|
|
8574
8636
|
strategyName,
|
|
8637
|
+
backtest,
|
|
8575
8638
|
path,
|
|
8576
8639
|
});
|
|
8577
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8640
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8578
8641
|
await storage.dump(strategyName, path, columns);
|
|
8579
8642
|
};
|
|
8580
8643
|
/**
|
|
8581
8644
|
* Clears accumulated event data from storage.
|
|
8582
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
8645
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
8583
8646
|
* If nothing is provided, clears all data.
|
|
8584
8647
|
*
|
|
8648
|
+
* @param backtest - Backtest mode flag
|
|
8585
8649
|
* @param ctx - Optional context with symbol and strategyName
|
|
8586
8650
|
*
|
|
8587
8651
|
* @example
|
|
8588
8652
|
* ```typescript
|
|
8589
8653
|
* const service = new ScheduleMarkdownService();
|
|
8590
8654
|
*
|
|
8591
|
-
* // Clear specific symbol-strategy
|
|
8592
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8655
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
8656
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8593
8657
|
*
|
|
8594
8658
|
* // Clear all data
|
|
8595
8659
|
* await service.clear();
|
|
8596
8660
|
* ```
|
|
8597
8661
|
*/
|
|
8598
|
-
this.clear = async (ctx) => {
|
|
8662
|
+
this.clear = async (backtest, ctx) => {
|
|
8599
8663
|
this.loggerService.log("scheduleMarkdownService clear", {
|
|
8664
|
+
backtest,
|
|
8600
8665
|
ctx,
|
|
8601
8666
|
});
|
|
8602
8667
|
if (ctx) {
|
|
8603
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
8668
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
8604
8669
|
this.getStorage.clear(key);
|
|
8605
8670
|
}
|
|
8606
8671
|
else {
|
|
@@ -8839,10 +8904,10 @@ class PerformanceMarkdownService {
|
|
|
8839
8904
|
/** Logger service for debug output */
|
|
8840
8905
|
this.loggerService = inject(TYPES.loggerService);
|
|
8841
8906
|
/**
|
|
8842
|
-
* Memoized function to get or create PerformanceStorage for a symbol-strategy
|
|
8843
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
8907
|
+
* Memoized function to get or create PerformanceStorage for a symbol-strategy-backtest triple.
|
|
8908
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
8844
8909
|
*/
|
|
8845
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new PerformanceStorage());
|
|
8910
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new PerformanceStorage());
|
|
8846
8911
|
/**
|
|
8847
8912
|
* Processes performance events and accumulates metrics.
|
|
8848
8913
|
* Should be called from performance tracking code.
|
|
@@ -8855,7 +8920,7 @@ class PerformanceMarkdownService {
|
|
|
8855
8920
|
});
|
|
8856
8921
|
const symbol = event.symbol || "global";
|
|
8857
8922
|
const strategyName = event.strategyName || "global";
|
|
8858
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8923
|
+
const storage = this.getStorage(symbol, strategyName, event.backtest);
|
|
8859
8924
|
storage.addEvent(event);
|
|
8860
8925
|
};
|
|
8861
8926
|
/**
|
|
@@ -8863,22 +8928,24 @@ class PerformanceMarkdownService {
|
|
|
8863
8928
|
*
|
|
8864
8929
|
* @param symbol - Trading pair symbol
|
|
8865
8930
|
* @param strategyName - Strategy name to get data for
|
|
8931
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8866
8932
|
* @returns Performance statistics with aggregated metrics
|
|
8867
8933
|
*
|
|
8868
8934
|
* @example
|
|
8869
8935
|
* ```typescript
|
|
8870
|
-
* const stats = await performanceService.getData("BTCUSDT", "my-strategy");
|
|
8936
|
+
* const stats = await performanceService.getData("BTCUSDT", "my-strategy", false);
|
|
8871
8937
|
* console.log("Total time:", stats.totalDuration);
|
|
8872
8938
|
* console.log("Slowest operation:", Object.values(stats.metricStats)
|
|
8873
8939
|
* .sort((a, b) => b.avgDuration - a.avgDuration)[0]);
|
|
8874
8940
|
* ```
|
|
8875
8941
|
*/
|
|
8876
|
-
this.getData = async (symbol, strategyName) => {
|
|
8942
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
8877
8943
|
this.loggerService.log("performanceMarkdownService getData", {
|
|
8878
8944
|
symbol,
|
|
8879
8945
|
strategyName,
|
|
8946
|
+
backtest,
|
|
8880
8947
|
});
|
|
8881
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8948
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8882
8949
|
return storage.getData(strategyName);
|
|
8883
8950
|
};
|
|
8884
8951
|
/**
|
|
@@ -8886,21 +8953,23 @@ class PerformanceMarkdownService {
|
|
|
8886
8953
|
*
|
|
8887
8954
|
* @param symbol - Trading pair symbol
|
|
8888
8955
|
* @param strategyName - Strategy name to generate report for
|
|
8956
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8889
8957
|
* @param columns - Column configuration for formatting the table
|
|
8890
8958
|
* @returns Markdown formatted report string
|
|
8891
8959
|
*
|
|
8892
8960
|
* @example
|
|
8893
8961
|
* ```typescript
|
|
8894
|
-
* const markdown = await performanceService.getReport("BTCUSDT", "my-strategy");
|
|
8962
|
+
* const markdown = await performanceService.getReport("BTCUSDT", "my-strategy", false);
|
|
8895
8963
|
* console.log(markdown);
|
|
8896
8964
|
* ```
|
|
8897
8965
|
*/
|
|
8898
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.performance_columns) => {
|
|
8966
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.performance_columns) => {
|
|
8899
8967
|
this.loggerService.log("performanceMarkdownService getReport", {
|
|
8900
8968
|
symbol,
|
|
8901
8969
|
strategyName,
|
|
8970
|
+
backtest,
|
|
8902
8971
|
});
|
|
8903
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8972
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8904
8973
|
return storage.getReport(strategyName, columns);
|
|
8905
8974
|
};
|
|
8906
8975
|
/**
|
|
@@ -8908,42 +8977,45 @@ class PerformanceMarkdownService {
|
|
|
8908
8977
|
*
|
|
8909
8978
|
* @param symbol - Trading pair symbol
|
|
8910
8979
|
* @param strategyName - Strategy name to save report for
|
|
8980
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8911
8981
|
* @param path - Directory path to save report
|
|
8912
8982
|
* @param columns - Column configuration for formatting the table
|
|
8913
8983
|
*
|
|
8914
8984
|
* @example
|
|
8915
8985
|
* ```typescript
|
|
8916
8986
|
* // Save to default path: ./dump/performance/my-strategy.md
|
|
8917
|
-
* await performanceService.dump("BTCUSDT", "my-strategy");
|
|
8987
|
+
* await performanceService.dump("BTCUSDT", "my-strategy", false);
|
|
8918
8988
|
*
|
|
8919
8989
|
* // Save to custom path
|
|
8920
|
-
* await performanceService.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
8990
|
+
* await performanceService.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
8921
8991
|
* ```
|
|
8922
8992
|
*/
|
|
8923
|
-
this.dump = async (symbol, strategyName, path = "./dump/performance", columns = COLUMN_CONFIG.performance_columns) => {
|
|
8993
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/performance", columns = COLUMN_CONFIG.performance_columns) => {
|
|
8924
8994
|
this.loggerService.log("performanceMarkdownService dump", {
|
|
8925
8995
|
symbol,
|
|
8926
8996
|
strategyName,
|
|
8997
|
+
backtest,
|
|
8927
8998
|
path,
|
|
8928
8999
|
});
|
|
8929
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
9000
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8930
9001
|
await storage.dump(strategyName, path, columns);
|
|
8931
9002
|
};
|
|
8932
9003
|
/**
|
|
8933
9004
|
* Clears accumulated performance data from storage.
|
|
8934
9005
|
*
|
|
8935
|
-
* @param
|
|
8936
|
-
* @param
|
|
9006
|
+
* @param backtest - Backtest mode flag
|
|
9007
|
+
* @param ctx - Optional context with symbol and strategyName
|
|
8937
9008
|
*/
|
|
8938
|
-
this.clear = async (ctx) => {
|
|
9009
|
+
this.clear = async (backtest, ctx) => {
|
|
8939
9010
|
this.loggerService.log("performanceMarkdownService clear", {
|
|
9011
|
+
backtest,
|
|
8940
9012
|
ctx,
|
|
8941
9013
|
});
|
|
8942
9014
|
if (ctx) {
|
|
8943
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
9015
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
8944
9016
|
this.getStorage.clear(key);
|
|
8945
9017
|
}
|
|
8946
|
-
{
|
|
9018
|
+
else {
|
|
8947
9019
|
this.getStorage.clear();
|
|
8948
9020
|
}
|
|
8949
9021
|
};
|
|
@@ -9707,10 +9779,10 @@ class HeatMarkdownService {
|
|
|
9707
9779
|
/** Logger service for debug output */
|
|
9708
9780
|
this.loggerService = inject(TYPES.loggerService);
|
|
9709
9781
|
/**
|
|
9710
|
-
* Memoized function to get or create HeatmapStorage for a strategy.
|
|
9711
|
-
* Each strategy gets its own isolated heatmap storage instance.
|
|
9782
|
+
* Memoized function to get or create HeatmapStorage for a strategy and backtest mode.
|
|
9783
|
+
* Each strategy + backtest mode combination gets its own isolated heatmap storage instance.
|
|
9712
9784
|
*/
|
|
9713
|
-
this.getStorage = functoolsKit.memoize(([strategyName]) => `${strategyName}`, () => new HeatmapStorage());
|
|
9785
|
+
this.getStorage = functoolsKit.memoize(([strategyName, backtest]) => `${strategyName}:${backtest ? "backtest" : "live"}`, () => new HeatmapStorage());
|
|
9714
9786
|
/**
|
|
9715
9787
|
* Processes tick events and accumulates closed signals.
|
|
9716
9788
|
* Should be called from signal emitter subscription.
|
|
@@ -9726,19 +9798,20 @@ class HeatMarkdownService {
|
|
|
9726
9798
|
if (data.action !== "closed") {
|
|
9727
9799
|
return;
|
|
9728
9800
|
}
|
|
9729
|
-
const storage = this.getStorage(data.strategyName);
|
|
9801
|
+
const storage = this.getStorage(data.strategyName, data.backtest);
|
|
9730
9802
|
storage.addSignal(data);
|
|
9731
9803
|
};
|
|
9732
9804
|
/**
|
|
9733
9805
|
* Gets aggregated portfolio heatmap statistics for a strategy.
|
|
9734
9806
|
*
|
|
9735
9807
|
* @param strategyName - Strategy name to get heatmap data for
|
|
9808
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
9736
9809
|
* @returns Promise resolving to heatmap statistics with per-symbol and portfolio-wide metrics
|
|
9737
9810
|
*
|
|
9738
9811
|
* @example
|
|
9739
9812
|
* ```typescript
|
|
9740
9813
|
* const service = new HeatMarkdownService();
|
|
9741
|
-
* const stats = await service.getData("my-strategy");
|
|
9814
|
+
* const stats = await service.getData("my-strategy", true);
|
|
9742
9815
|
*
|
|
9743
9816
|
* console.log(`Total symbols: ${stats.totalSymbols}`);
|
|
9744
9817
|
* console.log(`Portfolio PNL: ${stats.portfolioTotalPnl}%`);
|
|
@@ -9748,24 +9821,26 @@ class HeatMarkdownService {
|
|
|
9748
9821
|
* });
|
|
9749
9822
|
* ```
|
|
9750
9823
|
*/
|
|
9751
|
-
this.getData = async (strategyName) => {
|
|
9824
|
+
this.getData = async (strategyName, backtest) => {
|
|
9752
9825
|
this.loggerService.log(HEATMAP_METHOD_NAME_GET_DATA, {
|
|
9753
9826
|
strategyName,
|
|
9827
|
+
backtest,
|
|
9754
9828
|
});
|
|
9755
|
-
const storage = this.getStorage(strategyName);
|
|
9829
|
+
const storage = this.getStorage(strategyName, backtest);
|
|
9756
9830
|
return storage.getData();
|
|
9757
9831
|
};
|
|
9758
9832
|
/**
|
|
9759
9833
|
* Generates markdown report with portfolio heatmap table for a strategy.
|
|
9760
9834
|
*
|
|
9761
9835
|
* @param strategyName - Strategy name to generate heatmap report for
|
|
9836
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
9762
9837
|
* @param columns - Column configuration for formatting the table
|
|
9763
9838
|
* @returns Promise resolving to markdown formatted report string
|
|
9764
9839
|
*
|
|
9765
9840
|
* @example
|
|
9766
9841
|
* ```typescript
|
|
9767
9842
|
* const service = new HeatMarkdownService();
|
|
9768
|
-
* const markdown = await service.getReport("my-strategy");
|
|
9843
|
+
* const markdown = await service.getReport("my-strategy", true);
|
|
9769
9844
|
* console.log(markdown);
|
|
9770
9845
|
* // Output:
|
|
9771
9846
|
* // # Portfolio Heatmap: my-strategy
|
|
@@ -9779,11 +9854,12 @@ class HeatMarkdownService {
|
|
|
9779
9854
|
* // ...
|
|
9780
9855
|
* ```
|
|
9781
9856
|
*/
|
|
9782
|
-
this.getReport = async (strategyName, columns = COLUMN_CONFIG.heat_columns) => {
|
|
9857
|
+
this.getReport = async (strategyName, backtest, columns = COLUMN_CONFIG.heat_columns) => {
|
|
9783
9858
|
this.loggerService.log(HEATMAP_METHOD_NAME_GET_REPORT, {
|
|
9784
9859
|
strategyName,
|
|
9860
|
+
backtest,
|
|
9785
9861
|
});
|
|
9786
|
-
const storage = this.getStorage(strategyName);
|
|
9862
|
+
const storage = this.getStorage(strategyName, backtest);
|
|
9787
9863
|
return storage.getReport(strategyName, columns);
|
|
9788
9864
|
};
|
|
9789
9865
|
/**
|
|
@@ -9793,6 +9869,7 @@ class HeatMarkdownService {
|
|
|
9793
9869
|
* Default filename: {strategyName}.md
|
|
9794
9870
|
*
|
|
9795
9871
|
* @param strategyName - Strategy name to save heatmap report for
|
|
9872
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
9796
9873
|
* @param path - Optional directory path to save report (default: "./dump/heatmap")
|
|
9797
9874
|
* @param columns - Column configuration for formatting the table
|
|
9798
9875
|
*
|
|
@@ -9801,43 +9878,52 @@ class HeatMarkdownService {
|
|
|
9801
9878
|
* const service = new HeatMarkdownService();
|
|
9802
9879
|
*
|
|
9803
9880
|
* // Save to default path: ./dump/heatmap/my-strategy.md
|
|
9804
|
-
* await service.dump("my-strategy");
|
|
9881
|
+
* await service.dump("my-strategy", true);
|
|
9805
9882
|
*
|
|
9806
9883
|
* // Save to custom path: ./reports/my-strategy.md
|
|
9807
|
-
* await service.dump("my-strategy", "./reports");
|
|
9884
|
+
* await service.dump("my-strategy", true, "./reports");
|
|
9808
9885
|
* ```
|
|
9809
9886
|
*/
|
|
9810
|
-
this.dump = async (strategyName, path = "./dump/heatmap", columns = COLUMN_CONFIG.heat_columns) => {
|
|
9887
|
+
this.dump = async (strategyName, backtest, path = "./dump/heatmap", columns = COLUMN_CONFIG.heat_columns) => {
|
|
9811
9888
|
this.loggerService.log(HEATMAP_METHOD_NAME_DUMP, {
|
|
9812
9889
|
strategyName,
|
|
9890
|
+
backtest,
|
|
9813
9891
|
path,
|
|
9814
9892
|
});
|
|
9815
|
-
const storage = this.getStorage(strategyName);
|
|
9893
|
+
const storage = this.getStorage(strategyName, backtest);
|
|
9816
9894
|
await storage.dump(strategyName, path, columns);
|
|
9817
9895
|
};
|
|
9818
9896
|
/**
|
|
9819
9897
|
* Clears accumulated heatmap data from storage.
|
|
9820
|
-
* If
|
|
9821
|
-
* If
|
|
9898
|
+
* If ctx is provided, clears only that strategy+backtest combination's data.
|
|
9899
|
+
* If ctx is omitted, clears all data.
|
|
9822
9900
|
*
|
|
9823
|
-
* @param
|
|
9901
|
+
* @param backtest - Backtest mode flag
|
|
9902
|
+
* @param ctx - Optional context with strategyName to clear specific data
|
|
9824
9903
|
*
|
|
9825
9904
|
* @example
|
|
9826
9905
|
* ```typescript
|
|
9827
9906
|
* const service = new HeatMarkdownService();
|
|
9828
9907
|
*
|
|
9829
|
-
* // Clear specific strategy data
|
|
9830
|
-
* await service.clear("my-strategy");
|
|
9908
|
+
* // Clear specific strategy+backtest data
|
|
9909
|
+
* await service.clear(true, { strategyName: "my-strategy" });
|
|
9831
9910
|
*
|
|
9832
|
-
* // Clear all
|
|
9911
|
+
* // Clear all data
|
|
9833
9912
|
* await service.clear();
|
|
9834
9913
|
* ```
|
|
9835
9914
|
*/
|
|
9836
|
-
this.clear = async (
|
|
9915
|
+
this.clear = async (backtest, ctx) => {
|
|
9837
9916
|
this.loggerService.log(HEATMAP_METHOD_NAME_CLEAR, {
|
|
9838
|
-
|
|
9917
|
+
backtest,
|
|
9918
|
+
ctx,
|
|
9839
9919
|
});
|
|
9840
|
-
|
|
9920
|
+
if (ctx) {
|
|
9921
|
+
const key = `${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
9922
|
+
this.getStorage.clear(key);
|
|
9923
|
+
}
|
|
9924
|
+
else {
|
|
9925
|
+
this.getStorage.clear();
|
|
9926
|
+
}
|
|
9841
9927
|
};
|
|
9842
9928
|
/**
|
|
9843
9929
|
* Initializes the service by subscribing to signal events.
|
|
@@ -11667,6 +11753,9 @@ const HANDLE_PROFIT_FN = async (symbol, data, currentPrice, revenuePercent, back
|
|
|
11667
11753
|
if (self._states === NEED_FETCH) {
|
|
11668
11754
|
throw new Error("ClientPartial not initialized. Call waitForInit() before using.");
|
|
11669
11755
|
}
|
|
11756
|
+
if (data.id !== self.params.signalId) {
|
|
11757
|
+
throw new Error(`Signal ID mismatch: expected ${self.params.signalId}, got ${data.id}`);
|
|
11758
|
+
}
|
|
11670
11759
|
let state = self._states.get(data.id);
|
|
11671
11760
|
if (!state) {
|
|
11672
11761
|
state = {
|
|
@@ -11691,7 +11780,7 @@ const HANDLE_PROFIT_FN = async (symbol, data, currentPrice, revenuePercent, back
|
|
|
11691
11780
|
}
|
|
11692
11781
|
}
|
|
11693
11782
|
if (shouldPersist) {
|
|
11694
|
-
await self._persistState(symbol,
|
|
11783
|
+
await self._persistState(symbol, data.strategyName);
|
|
11695
11784
|
}
|
|
11696
11785
|
};
|
|
11697
11786
|
/**
|
|
@@ -11713,6 +11802,9 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
|
|
|
11713
11802
|
if (self._states === NEED_FETCH) {
|
|
11714
11803
|
throw new Error("ClientPartial not initialized. Call waitForInit() before using.");
|
|
11715
11804
|
}
|
|
11805
|
+
if (data.id !== self.params.signalId) {
|
|
11806
|
+
throw new Error(`Signal ID mismatch: expected ${self.params.signalId}, got ${data.id}`);
|
|
11807
|
+
}
|
|
11716
11808
|
let state = self._states.get(data.id);
|
|
11717
11809
|
if (!state) {
|
|
11718
11810
|
state = {
|
|
@@ -11738,7 +11830,7 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
|
|
|
11738
11830
|
}
|
|
11739
11831
|
}
|
|
11740
11832
|
if (shouldPersist) {
|
|
11741
|
-
await self._persistState(symbol,
|
|
11833
|
+
await self._persistState(symbol, data.strategyName);
|
|
11742
11834
|
}
|
|
11743
11835
|
};
|
|
11744
11836
|
/**
|
|
@@ -11747,15 +11839,29 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
|
|
|
11747
11839
|
* Loads persisted partial state from disk and restores in-memory Maps.
|
|
11748
11840
|
* Converts serialized arrays back to Sets for O(1) lookups.
|
|
11749
11841
|
*
|
|
11842
|
+
* ONLY runs in LIVE mode (backtest=false). In backtest mode, state is not persisted.
|
|
11843
|
+
*
|
|
11750
11844
|
* @param symbol - Trading pair symbol
|
|
11845
|
+
* @param strategyName - Strategy identifier
|
|
11846
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
11751
11847
|
* @param self - ClientPartial instance reference
|
|
11752
11848
|
*/
|
|
11753
|
-
const WAIT_FOR_INIT_FN = async (symbol, self) => {
|
|
11754
|
-
self.params.logger.debug("ClientPartial waitForInit", {
|
|
11755
|
-
|
|
11756
|
-
|
|
11849
|
+
const WAIT_FOR_INIT_FN = async (symbol, strategyName, self) => {
|
|
11850
|
+
self.params.logger.debug("ClientPartial waitForInit", {
|
|
11851
|
+
symbol,
|
|
11852
|
+
strategyName,
|
|
11853
|
+
backtest: self.params.backtest
|
|
11854
|
+
});
|
|
11855
|
+
if (self._states !== NEED_FETCH) {
|
|
11856
|
+
throw new Error("ClientPartial WAIT_FOR_INIT_FN should be called once!");
|
|
11757
11857
|
}
|
|
11758
|
-
|
|
11858
|
+
self._states = new Map();
|
|
11859
|
+
// Skip persistence in backtest mode
|
|
11860
|
+
if (self.params.backtest) {
|
|
11861
|
+
self.params.logger.debug("ClientPartial waitForInit: skipping persist read in backtest mode");
|
|
11862
|
+
return;
|
|
11863
|
+
}
|
|
11864
|
+
const partialData = await PersistPartialAdapter.readPartialData(symbol, strategyName);
|
|
11759
11865
|
for (const [signalId, data] of Object.entries(partialData)) {
|
|
11760
11866
|
const state = {
|
|
11761
11867
|
profitLevels: new Set(data.profitLevels),
|
|
@@ -11765,6 +11871,7 @@ const WAIT_FOR_INIT_FN = async (symbol, self) => {
|
|
|
11765
11871
|
}
|
|
11766
11872
|
self.params.logger.info("ClientPartial restored state", {
|
|
11767
11873
|
symbol,
|
|
11874
|
+
strategyName,
|
|
11768
11875
|
signalCount: Object.keys(partialData).length,
|
|
11769
11876
|
});
|
|
11770
11877
|
};
|
|
@@ -11843,23 +11950,24 @@ class ClientPartial {
|
|
|
11843
11950
|
/**
|
|
11844
11951
|
* Initializes partial state by loading from disk.
|
|
11845
11952
|
*
|
|
11846
|
-
* Uses singleshot pattern to ensure initialization happens exactly once per symbol.
|
|
11953
|
+
* Uses singleshot pattern to ensure initialization happens exactly once per symbol:strategyName.
|
|
11847
11954
|
* Reads persisted state from PersistPartialAdapter and restores to _states Map.
|
|
11848
11955
|
*
|
|
11849
11956
|
* Must be called before profit()/loss()/clear() methods.
|
|
11850
11957
|
*
|
|
11851
11958
|
* @param symbol - Trading pair symbol
|
|
11959
|
+
* @param strategyName - Strategy identifier
|
|
11960
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
11852
11961
|
* @returns Promise that resolves when initialization is complete
|
|
11853
11962
|
*
|
|
11854
11963
|
* @example
|
|
11855
11964
|
* ```typescript
|
|
11856
11965
|
* const partial = new ClientPartial(params);
|
|
11857
|
-
* await partial.waitForInit("BTCUSDT"); // Load persisted state
|
|
11966
|
+
* await partial.waitForInit("BTCUSDT", "my-strategy", false); // Load persisted state (live mode)
|
|
11858
11967
|
* // Now profit()/loss() can be called
|
|
11859
11968
|
* ```
|
|
11860
11969
|
*/
|
|
11861
|
-
this.waitForInit = functoolsKit.singleshot(async (symbol) => await WAIT_FOR_INIT_FN(symbol, this));
|
|
11862
|
-
this._states = new Map();
|
|
11970
|
+
this.waitForInit = functoolsKit.singleshot(async (symbol, strategyName) => await WAIT_FOR_INIT_FN(symbol, strategyName, this));
|
|
11863
11971
|
}
|
|
11864
11972
|
/**
|
|
11865
11973
|
* Persists current partial state to disk.
|
|
@@ -11872,13 +11980,15 @@ class ClientPartial {
|
|
|
11872
11980
|
* Uses atomic file writes via PersistPartialAdapter.
|
|
11873
11981
|
*
|
|
11874
11982
|
* @param symbol - Trading pair symbol
|
|
11983
|
+
* @param strategyName - Strategy identifier
|
|
11984
|
+
* @param backtest - True if backtest mode
|
|
11875
11985
|
* @returns Promise that resolves when persistence is complete
|
|
11876
11986
|
*/
|
|
11877
|
-
async _persistState(symbol,
|
|
11878
|
-
if (backtest) {
|
|
11987
|
+
async _persistState(symbol, strategyName) {
|
|
11988
|
+
if (this.params.backtest) {
|
|
11879
11989
|
return;
|
|
11880
11990
|
}
|
|
11881
|
-
this.params.logger.debug("ClientPartial persistState", { symbol });
|
|
11991
|
+
this.params.logger.debug("ClientPartial persistState", { symbol, strategyName });
|
|
11882
11992
|
if (this._states === NEED_FETCH) {
|
|
11883
11993
|
throw new Error("ClientPartial not initialized. Call waitForInit() before using.");
|
|
11884
11994
|
}
|
|
@@ -11889,7 +11999,7 @@ class ClientPartial {
|
|
|
11889
11999
|
lossLevels: Array.from(state.lossLevels),
|
|
11890
12000
|
};
|
|
11891
12001
|
}
|
|
11892
|
-
await PersistPartialAdapter.writePartialData(partialData, symbol);
|
|
12002
|
+
await PersistPartialAdapter.writePartialData(partialData, symbol, strategyName);
|
|
11893
12003
|
}
|
|
11894
12004
|
/**
|
|
11895
12005
|
* Processes profit state and emits events for newly reached profit levels.
|
|
@@ -12010,8 +12120,11 @@ class ClientPartial {
|
|
|
12010
12120
|
if (this._states === NEED_FETCH) {
|
|
12011
12121
|
throw new Error("ClientPartial not initialized. Call waitForInit() before using.");
|
|
12012
12122
|
}
|
|
12123
|
+
if (data.id !== this.params.signalId) {
|
|
12124
|
+
throw new Error(`Signal ID mismatch: expected ${this.params.signalId}, got ${data.id}`);
|
|
12125
|
+
}
|
|
12013
12126
|
this._states.delete(data.id);
|
|
12014
|
-
await this._persistState(symbol,
|
|
12127
|
+
await this._persistState(symbol, data.strategyName);
|
|
12015
12128
|
}
|
|
12016
12129
|
}
|
|
12017
12130
|
|
|
@@ -12106,15 +12219,17 @@ class PartialConnectionService {
|
|
|
12106
12219
|
/**
|
|
12107
12220
|
* Memoized factory function for ClientPartial instances.
|
|
12108
12221
|
*
|
|
12109
|
-
* Creates one ClientPartial per signal ID with configured callbacks.
|
|
12222
|
+
* Creates one ClientPartial per signal ID and backtest mode with configured callbacks.
|
|
12110
12223
|
* Instances are cached until clear() is called.
|
|
12111
12224
|
*
|
|
12112
|
-
* Key format: signalId
|
|
12225
|
+
* Key format: "signalId:backtest" or "signalId:live"
|
|
12113
12226
|
* Value: ClientPartial instance with logger and event emitters
|
|
12114
12227
|
*/
|
|
12115
|
-
this.getPartial = functoolsKit.memoize(([signalId]) => `${signalId}`, () => {
|
|
12228
|
+
this.getPartial = functoolsKit.memoize(([signalId, backtest]) => `${signalId}:${backtest ? "backtest" : "live"}`, (signalId, backtest) => {
|
|
12116
12229
|
return new ClientPartial({
|
|
12230
|
+
signalId,
|
|
12117
12231
|
logger: this.loggerService,
|
|
12232
|
+
backtest,
|
|
12118
12233
|
onProfit: COMMIT_PROFIT_FN,
|
|
12119
12234
|
onLoss: COMMIT_LOSS_FN,
|
|
12120
12235
|
});
|
|
@@ -12142,8 +12257,8 @@ class PartialConnectionService {
|
|
|
12142
12257
|
backtest,
|
|
12143
12258
|
when,
|
|
12144
12259
|
});
|
|
12145
|
-
const partial = this.getPartial(data.id);
|
|
12146
|
-
await partial.waitForInit(symbol);
|
|
12260
|
+
const partial = this.getPartial(data.id, backtest);
|
|
12261
|
+
await partial.waitForInit(symbol, data.strategyName);
|
|
12147
12262
|
return await partial.profit(symbol, data, currentPrice, revenuePercent, backtest, when);
|
|
12148
12263
|
};
|
|
12149
12264
|
/**
|
|
@@ -12169,8 +12284,8 @@ class PartialConnectionService {
|
|
|
12169
12284
|
backtest,
|
|
12170
12285
|
when,
|
|
12171
12286
|
});
|
|
12172
|
-
const partial = this.getPartial(data.id);
|
|
12173
|
-
await partial.waitForInit(symbol);
|
|
12287
|
+
const partial = this.getPartial(data.id, backtest);
|
|
12288
|
+
await partial.waitForInit(symbol, data.strategyName);
|
|
12174
12289
|
return await partial.loss(symbol, data, currentPrice, lossPercent, backtest, when);
|
|
12175
12290
|
};
|
|
12176
12291
|
/**
|
|
@@ -12191,15 +12306,17 @@ class PartialConnectionService {
|
|
|
12191
12306
|
* @returns Promise that resolves when clear is complete
|
|
12192
12307
|
*/
|
|
12193
12308
|
this.clear = async (symbol, data, priceClose, backtest) => {
|
|
12194
|
-
this.loggerService.log("partialConnectionService
|
|
12309
|
+
this.loggerService.log("partialConnectionService clear", {
|
|
12195
12310
|
symbol,
|
|
12196
12311
|
data,
|
|
12197
12312
|
priceClose,
|
|
12313
|
+
backtest,
|
|
12198
12314
|
});
|
|
12199
|
-
const partial = this.getPartial(data.id);
|
|
12200
|
-
await partial.waitForInit(symbol);
|
|
12315
|
+
const partial = this.getPartial(data.id, backtest);
|
|
12316
|
+
await partial.waitForInit(symbol, data.strategyName);
|
|
12201
12317
|
await partial.clear(symbol, data, priceClose, backtest);
|
|
12202
|
-
|
|
12318
|
+
const key = `${data.id}:${backtest ? "backtest" : "live"}`;
|
|
12319
|
+
this.getPartial.clear(key);
|
|
12203
12320
|
};
|
|
12204
12321
|
}
|
|
12205
12322
|
}
|
|
@@ -12375,10 +12492,10 @@ class PartialMarkdownService {
|
|
|
12375
12492
|
/** Logger service for debug output */
|
|
12376
12493
|
this.loggerService = inject(TYPES.loggerService);
|
|
12377
12494
|
/**
|
|
12378
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
12379
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
12495
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
12496
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
12380
12497
|
*/
|
|
12381
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$1());
|
|
12498
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$1());
|
|
12382
12499
|
/**
|
|
12383
12500
|
* Processes profit events and accumulates them.
|
|
12384
12501
|
* Should be called from partialProfitSubject subscription.
|
|
@@ -12395,7 +12512,7 @@ class PartialMarkdownService {
|
|
|
12395
12512
|
this.loggerService.log("partialMarkdownService tickProfit", {
|
|
12396
12513
|
data,
|
|
12397
12514
|
});
|
|
12398
|
-
const storage = this.getStorage(data.symbol, data.data.strategyName);
|
|
12515
|
+
const storage = this.getStorage(data.symbol, data.data.strategyName, data.backtest);
|
|
12399
12516
|
storage.addProfitEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
|
|
12400
12517
|
};
|
|
12401
12518
|
/**
|
|
@@ -12414,7 +12531,7 @@ class PartialMarkdownService {
|
|
|
12414
12531
|
this.loggerService.log("partialMarkdownService tickLoss", {
|
|
12415
12532
|
data,
|
|
12416
12533
|
});
|
|
12417
|
-
const storage = this.getStorage(data.symbol, data.data.strategyName);
|
|
12534
|
+
const storage = this.getStorage(data.symbol, data.data.strategyName, data.backtest);
|
|
12418
12535
|
storage.addLossEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
|
|
12419
12536
|
};
|
|
12420
12537
|
/**
|
|
@@ -12423,21 +12540,23 @@ class PartialMarkdownService {
|
|
|
12423
12540
|
*
|
|
12424
12541
|
* @param symbol - Trading pair symbol to get data for
|
|
12425
12542
|
* @param strategyName - Strategy name to get data for
|
|
12543
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
12426
12544
|
* @returns Statistical data object with all metrics
|
|
12427
12545
|
*
|
|
12428
12546
|
* @example
|
|
12429
12547
|
* ```typescript
|
|
12430
12548
|
* const service = new PartialMarkdownService();
|
|
12431
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
12549
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
12432
12550
|
* console.log(stats.totalProfit, stats.totalLoss);
|
|
12433
12551
|
* ```
|
|
12434
12552
|
*/
|
|
12435
|
-
this.getData = async (symbol, strategyName) => {
|
|
12553
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
12436
12554
|
this.loggerService.log("partialMarkdownService getData", {
|
|
12437
12555
|
symbol,
|
|
12438
12556
|
strategyName,
|
|
12557
|
+
backtest,
|
|
12439
12558
|
});
|
|
12440
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
12559
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
12441
12560
|
return storage.getData();
|
|
12442
12561
|
};
|
|
12443
12562
|
/**
|
|
@@ -12446,22 +12565,24 @@ class PartialMarkdownService {
|
|
|
12446
12565
|
*
|
|
12447
12566
|
* @param symbol - Trading pair symbol to generate report for
|
|
12448
12567
|
* @param strategyName - Strategy name to generate report for
|
|
12568
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
12449
12569
|
* @param columns - Column configuration for formatting the table
|
|
12450
12570
|
* @returns Markdown formatted report string with table of all events
|
|
12451
12571
|
*
|
|
12452
12572
|
* @example
|
|
12453
12573
|
* ```typescript
|
|
12454
12574
|
* const service = new PartialMarkdownService();
|
|
12455
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
12575
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
12456
12576
|
* console.log(markdown);
|
|
12457
12577
|
* ```
|
|
12458
12578
|
*/
|
|
12459
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.partial_columns) => {
|
|
12579
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.partial_columns) => {
|
|
12460
12580
|
this.loggerService.log("partialMarkdownService getReport", {
|
|
12461
12581
|
symbol,
|
|
12462
12582
|
strategyName,
|
|
12583
|
+
backtest,
|
|
12463
12584
|
});
|
|
12464
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
12585
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
12465
12586
|
return storage.getReport(symbol, strategyName, columns);
|
|
12466
12587
|
};
|
|
12467
12588
|
/**
|
|
@@ -12471,6 +12592,7 @@ class PartialMarkdownService {
|
|
|
12471
12592
|
*
|
|
12472
12593
|
* @param symbol - Trading pair symbol to save report for
|
|
12473
12594
|
* @param strategyName - Strategy name to save report for
|
|
12595
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
12474
12596
|
* @param path - Directory path to save report (default: "./dump/partial")
|
|
12475
12597
|
* @param columns - Column configuration for formatting the table
|
|
12476
12598
|
*
|
|
@@ -12479,45 +12601,48 @@ class PartialMarkdownService {
|
|
|
12479
12601
|
* const service = new PartialMarkdownService();
|
|
12480
12602
|
*
|
|
12481
12603
|
* // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
|
|
12482
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
12604
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
12483
12605
|
*
|
|
12484
12606
|
* // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
|
|
12485
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
12607
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
12486
12608
|
* ```
|
|
12487
12609
|
*/
|
|
12488
|
-
this.dump = async (symbol, strategyName, path = "./dump/partial", columns = COLUMN_CONFIG.partial_columns) => {
|
|
12610
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/partial", columns = COLUMN_CONFIG.partial_columns) => {
|
|
12489
12611
|
this.loggerService.log("partialMarkdownService dump", {
|
|
12490
12612
|
symbol,
|
|
12491
12613
|
strategyName,
|
|
12614
|
+
backtest,
|
|
12492
12615
|
path,
|
|
12493
12616
|
});
|
|
12494
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
12617
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
12495
12618
|
await storage.dump(symbol, strategyName, path, columns);
|
|
12496
12619
|
};
|
|
12497
12620
|
/**
|
|
12498
12621
|
* Clears accumulated event data from storage.
|
|
12499
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
12622
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
12500
12623
|
* If nothing is provided, clears all data.
|
|
12501
12624
|
*
|
|
12625
|
+
* @param backtest - Backtest mode flag
|
|
12502
12626
|
* @param ctx - Optional context with symbol and strategyName
|
|
12503
12627
|
*
|
|
12504
12628
|
* @example
|
|
12505
12629
|
* ```typescript
|
|
12506
12630
|
* const service = new PartialMarkdownService();
|
|
12507
12631
|
*
|
|
12508
|
-
* // Clear specific symbol-strategy
|
|
12509
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
12632
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
12633
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
12510
12634
|
*
|
|
12511
12635
|
* // Clear all data
|
|
12512
12636
|
* await service.clear();
|
|
12513
12637
|
* ```
|
|
12514
12638
|
*/
|
|
12515
|
-
this.clear = async (ctx) => {
|
|
12639
|
+
this.clear = async (backtest, ctx) => {
|
|
12516
12640
|
this.loggerService.log("partialMarkdownService clear", {
|
|
12641
|
+
backtest,
|
|
12517
12642
|
ctx,
|
|
12518
12643
|
});
|
|
12519
12644
|
if (ctx) {
|
|
12520
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
12645
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
12521
12646
|
this.getStorage.clear(key);
|
|
12522
12647
|
}
|
|
12523
12648
|
else {
|
|
@@ -13093,10 +13218,10 @@ class RiskMarkdownService {
|
|
|
13093
13218
|
/** Logger service for debug output */
|
|
13094
13219
|
this.loggerService = inject(TYPES.loggerService);
|
|
13095
13220
|
/**
|
|
13096
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
13097
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
13221
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
13222
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
13098
13223
|
*/
|
|
13099
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage());
|
|
13224
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage());
|
|
13100
13225
|
/**
|
|
13101
13226
|
* Processes risk rejection events and accumulates them.
|
|
13102
13227
|
* Should be called from riskSubject subscription.
|
|
@@ -13113,7 +13238,7 @@ class RiskMarkdownService {
|
|
|
13113
13238
|
this.loggerService.log("riskMarkdownService tickRejection", {
|
|
13114
13239
|
data,
|
|
13115
13240
|
});
|
|
13116
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
13241
|
+
const storage = this.getStorage(data.symbol, data.strategyName, data.backtest);
|
|
13117
13242
|
storage.addRejectionEvent(data);
|
|
13118
13243
|
};
|
|
13119
13244
|
/**
|
|
@@ -13122,21 +13247,23 @@ class RiskMarkdownService {
|
|
|
13122
13247
|
*
|
|
13123
13248
|
* @param symbol - Trading pair symbol to get data for
|
|
13124
13249
|
* @param strategyName - Strategy name to get data for
|
|
13250
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
13125
13251
|
* @returns Statistical data object with all metrics
|
|
13126
13252
|
*
|
|
13127
13253
|
* @example
|
|
13128
13254
|
* ```typescript
|
|
13129
13255
|
* const service = new RiskMarkdownService();
|
|
13130
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
13256
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
13131
13257
|
* console.log(stats.totalRejections, stats.bySymbol);
|
|
13132
13258
|
* ```
|
|
13133
13259
|
*/
|
|
13134
|
-
this.getData = async (symbol, strategyName) => {
|
|
13260
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
13135
13261
|
this.loggerService.log("riskMarkdownService getData", {
|
|
13136
13262
|
symbol,
|
|
13137
13263
|
strategyName,
|
|
13264
|
+
backtest,
|
|
13138
13265
|
});
|
|
13139
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
13266
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
13140
13267
|
return storage.getData();
|
|
13141
13268
|
};
|
|
13142
13269
|
/**
|
|
@@ -13145,22 +13272,24 @@ class RiskMarkdownService {
|
|
|
13145
13272
|
*
|
|
13146
13273
|
* @param symbol - Trading pair symbol to generate report for
|
|
13147
13274
|
* @param strategyName - Strategy name to generate report for
|
|
13275
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
13148
13276
|
* @param columns - Column configuration for formatting the table
|
|
13149
13277
|
* @returns Markdown formatted report string with table of all events
|
|
13150
13278
|
*
|
|
13151
13279
|
* @example
|
|
13152
13280
|
* ```typescript
|
|
13153
13281
|
* const service = new RiskMarkdownService();
|
|
13154
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
13282
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
13155
13283
|
* console.log(markdown);
|
|
13156
13284
|
* ```
|
|
13157
13285
|
*/
|
|
13158
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.risk_columns) => {
|
|
13286
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.risk_columns) => {
|
|
13159
13287
|
this.loggerService.log("riskMarkdownService getReport", {
|
|
13160
13288
|
symbol,
|
|
13161
13289
|
strategyName,
|
|
13290
|
+
backtest,
|
|
13162
13291
|
});
|
|
13163
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
13292
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
13164
13293
|
return storage.getReport(symbol, strategyName, columns);
|
|
13165
13294
|
};
|
|
13166
13295
|
/**
|
|
@@ -13170,6 +13299,7 @@ class RiskMarkdownService {
|
|
|
13170
13299
|
*
|
|
13171
13300
|
* @param symbol - Trading pair symbol to save report for
|
|
13172
13301
|
* @param strategyName - Strategy name to save report for
|
|
13302
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
13173
13303
|
* @param path - Directory path to save report (default: "./dump/risk")
|
|
13174
13304
|
* @param columns - Column configuration for formatting the table
|
|
13175
13305
|
*
|
|
@@ -13178,45 +13308,48 @@ class RiskMarkdownService {
|
|
|
13178
13308
|
* const service = new RiskMarkdownService();
|
|
13179
13309
|
*
|
|
13180
13310
|
* // Save to default path: ./dump/risk/BTCUSDT_my-strategy.md
|
|
13181
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
13311
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
13182
13312
|
*
|
|
13183
13313
|
* // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
|
|
13184
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
13314
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
13185
13315
|
* ```
|
|
13186
13316
|
*/
|
|
13187
|
-
this.dump = async (symbol, strategyName, path = "./dump/risk", columns = COLUMN_CONFIG.risk_columns) => {
|
|
13317
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/risk", columns = COLUMN_CONFIG.risk_columns) => {
|
|
13188
13318
|
this.loggerService.log("riskMarkdownService dump", {
|
|
13189
13319
|
symbol,
|
|
13190
13320
|
strategyName,
|
|
13321
|
+
backtest,
|
|
13191
13322
|
path,
|
|
13192
13323
|
});
|
|
13193
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
13324
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
13194
13325
|
await storage.dump(symbol, strategyName, path, columns);
|
|
13195
13326
|
};
|
|
13196
13327
|
/**
|
|
13197
13328
|
* Clears accumulated event data from storage.
|
|
13198
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
13329
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
13199
13330
|
* If nothing is provided, clears all data.
|
|
13200
13331
|
*
|
|
13332
|
+
* @param backtest - Backtest mode flag
|
|
13201
13333
|
* @param ctx - Optional context with symbol and strategyName
|
|
13202
13334
|
*
|
|
13203
13335
|
* @example
|
|
13204
13336
|
* ```typescript
|
|
13205
13337
|
* const service = new RiskMarkdownService();
|
|
13206
13338
|
*
|
|
13207
|
-
* // Clear specific symbol-strategy
|
|
13208
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
13339
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
13340
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
13209
13341
|
*
|
|
13210
13342
|
* // Clear all data
|
|
13211
13343
|
* await service.clear();
|
|
13212
13344
|
* ```
|
|
13213
13345
|
*/
|
|
13214
|
-
this.clear = async (ctx) => {
|
|
13346
|
+
this.clear = async (backtest, ctx) => {
|
|
13215
13347
|
this.loggerService.log("riskMarkdownService clear", {
|
|
13348
|
+
backtest,
|
|
13216
13349
|
ctx,
|
|
13217
13350
|
});
|
|
13218
13351
|
if (ctx) {
|
|
13219
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
13352
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
13220
13353
|
this.getStorage.clear(key);
|
|
13221
13354
|
}
|
|
13222
13355
|
else {
|
|
@@ -13521,7 +13654,7 @@ const backtest = {
|
|
|
13521
13654
|
...templateServices,
|
|
13522
13655
|
};
|
|
13523
13656
|
init();
|
|
13524
|
-
var
|
|
13657
|
+
var bt = backtest;
|
|
13525
13658
|
|
|
13526
13659
|
/**
|
|
13527
13660
|
* Sets custom logger implementation for the framework.
|
|
@@ -13541,7 +13674,7 @@ var backtest$1 = backtest;
|
|
|
13541
13674
|
* ```
|
|
13542
13675
|
*/
|
|
13543
13676
|
function setLogger(logger) {
|
|
13544
|
-
|
|
13677
|
+
bt.loggerService.setLogger(logger);
|
|
13545
13678
|
}
|
|
13546
13679
|
/**
|
|
13547
13680
|
* Sets global configuration parameters for the framework.
|
|
@@ -13559,7 +13692,7 @@ function setConfig(config, _unsafe) {
|
|
|
13559
13692
|
const prevConfig = Object.assign({}, GLOBAL_CONFIG);
|
|
13560
13693
|
try {
|
|
13561
13694
|
Object.assign(GLOBAL_CONFIG, config);
|
|
13562
|
-
!_unsafe &&
|
|
13695
|
+
!_unsafe && bt.configValidationService.validate();
|
|
13563
13696
|
}
|
|
13564
13697
|
catch (error) {
|
|
13565
13698
|
console.warn(`backtest-kit setConfig failed: ${functoolsKit.getErrorMessage(error)}`, config);
|
|
@@ -13630,7 +13763,7 @@ function setColumns(columns, _unsafe) {
|
|
|
13630
13763
|
const prevConfig = Object.assign({}, COLUMN_CONFIG);
|
|
13631
13764
|
try {
|
|
13632
13765
|
Object.assign(COLUMN_CONFIG, columns);
|
|
13633
|
-
!_unsafe &&
|
|
13766
|
+
!_unsafe && bt.columnValidationService.validate();
|
|
13634
13767
|
}
|
|
13635
13768
|
catch (error) {
|
|
13636
13769
|
console.warn(`backtest-kit setColumns failed: ${functoolsKit.getErrorMessage(error)}`, columns);
|
|
@@ -13715,11 +13848,11 @@ const ADD_OPTIMIZER_METHOD_NAME = "add.addOptimizer";
|
|
|
13715
13848
|
* ```
|
|
13716
13849
|
*/
|
|
13717
13850
|
function addStrategy(strategySchema) {
|
|
13718
|
-
|
|
13851
|
+
bt.loggerService.info(ADD_STRATEGY_METHOD_NAME, {
|
|
13719
13852
|
strategySchema,
|
|
13720
13853
|
});
|
|
13721
|
-
|
|
13722
|
-
|
|
13854
|
+
bt.strategyValidationService.addStrategy(strategySchema.strategyName, strategySchema);
|
|
13855
|
+
bt.strategySchemaService.register(strategySchema.strategyName, strategySchema);
|
|
13723
13856
|
}
|
|
13724
13857
|
/**
|
|
13725
13858
|
* Registers an exchange data source in the framework.
|
|
@@ -13757,11 +13890,11 @@ function addStrategy(strategySchema) {
|
|
|
13757
13890
|
* ```
|
|
13758
13891
|
*/
|
|
13759
13892
|
function addExchange(exchangeSchema) {
|
|
13760
|
-
|
|
13893
|
+
bt.loggerService.info(ADD_EXCHANGE_METHOD_NAME, {
|
|
13761
13894
|
exchangeSchema,
|
|
13762
13895
|
});
|
|
13763
|
-
|
|
13764
|
-
|
|
13896
|
+
bt.exchangeValidationService.addExchange(exchangeSchema.exchangeName, exchangeSchema);
|
|
13897
|
+
bt.exchangeSchemaService.register(exchangeSchema.exchangeName, exchangeSchema);
|
|
13765
13898
|
}
|
|
13766
13899
|
/**
|
|
13767
13900
|
* Registers a timeframe generator for backtesting.
|
|
@@ -13794,11 +13927,11 @@ function addExchange(exchangeSchema) {
|
|
|
13794
13927
|
* ```
|
|
13795
13928
|
*/
|
|
13796
13929
|
function addFrame(frameSchema) {
|
|
13797
|
-
|
|
13930
|
+
bt.loggerService.info(ADD_FRAME_METHOD_NAME, {
|
|
13798
13931
|
frameSchema,
|
|
13799
13932
|
});
|
|
13800
|
-
|
|
13801
|
-
|
|
13933
|
+
bt.frameValidationService.addFrame(frameSchema.frameName, frameSchema);
|
|
13934
|
+
bt.frameSchemaService.register(frameSchema.frameName, frameSchema);
|
|
13802
13935
|
}
|
|
13803
13936
|
/**
|
|
13804
13937
|
* Registers a walker for strategy comparison.
|
|
@@ -13838,11 +13971,11 @@ function addFrame(frameSchema) {
|
|
|
13838
13971
|
* ```
|
|
13839
13972
|
*/
|
|
13840
13973
|
function addWalker(walkerSchema) {
|
|
13841
|
-
|
|
13974
|
+
bt.loggerService.info(ADD_WALKER_METHOD_NAME, {
|
|
13842
13975
|
walkerSchema,
|
|
13843
13976
|
});
|
|
13844
|
-
|
|
13845
|
-
|
|
13977
|
+
bt.walkerValidationService.addWalker(walkerSchema.walkerName, walkerSchema);
|
|
13978
|
+
bt.walkerSchemaService.register(walkerSchema.walkerName, walkerSchema);
|
|
13846
13979
|
}
|
|
13847
13980
|
/**
|
|
13848
13981
|
* Registers a position sizing configuration in the framework.
|
|
@@ -13897,11 +14030,11 @@ function addWalker(walkerSchema) {
|
|
|
13897
14030
|
* ```
|
|
13898
14031
|
*/
|
|
13899
14032
|
function addSizing(sizingSchema) {
|
|
13900
|
-
|
|
14033
|
+
bt.loggerService.info(ADD_SIZING_METHOD_NAME, {
|
|
13901
14034
|
sizingSchema,
|
|
13902
14035
|
});
|
|
13903
|
-
|
|
13904
|
-
|
|
14036
|
+
bt.sizingValidationService.addSizing(sizingSchema.sizingName, sizingSchema);
|
|
14037
|
+
bt.sizingSchemaService.register(sizingSchema.sizingName, sizingSchema);
|
|
13905
14038
|
}
|
|
13906
14039
|
/**
|
|
13907
14040
|
* Registers a risk management configuration in the framework.
|
|
@@ -13965,11 +14098,11 @@ function addSizing(sizingSchema) {
|
|
|
13965
14098
|
* ```
|
|
13966
14099
|
*/
|
|
13967
14100
|
function addRisk(riskSchema) {
|
|
13968
|
-
|
|
14101
|
+
bt.loggerService.info(ADD_RISK_METHOD_NAME, {
|
|
13969
14102
|
riskSchema,
|
|
13970
14103
|
});
|
|
13971
|
-
|
|
13972
|
-
|
|
14104
|
+
bt.riskValidationService.addRisk(riskSchema.riskName, riskSchema);
|
|
14105
|
+
bt.riskSchemaService.register(riskSchema.riskName, riskSchema);
|
|
13973
14106
|
}
|
|
13974
14107
|
/**
|
|
13975
14108
|
* Registers an optimizer configuration in the framework.
|
|
@@ -14059,11 +14192,11 @@ function addRisk(riskSchema) {
|
|
|
14059
14192
|
* ```
|
|
14060
14193
|
*/
|
|
14061
14194
|
function addOptimizer(optimizerSchema) {
|
|
14062
|
-
|
|
14195
|
+
bt.loggerService.info(ADD_OPTIMIZER_METHOD_NAME, {
|
|
14063
14196
|
optimizerSchema,
|
|
14064
14197
|
});
|
|
14065
|
-
|
|
14066
|
-
|
|
14198
|
+
bt.optimizerValidationService.addOptimizer(optimizerSchema.optimizerName, optimizerSchema);
|
|
14199
|
+
bt.optimizerSchemaService.register(optimizerSchema.optimizerName, optimizerSchema);
|
|
14067
14200
|
}
|
|
14068
14201
|
|
|
14069
14202
|
const LIST_EXCHANGES_METHOD_NAME = "list.listExchanges";
|
|
@@ -14099,8 +14232,8 @@ const LIST_OPTIMIZERS_METHOD_NAME = "list.listOptimizers";
|
|
|
14099
14232
|
* ```
|
|
14100
14233
|
*/
|
|
14101
14234
|
async function listExchanges() {
|
|
14102
|
-
|
|
14103
|
-
return await
|
|
14235
|
+
bt.loggerService.log(LIST_EXCHANGES_METHOD_NAME);
|
|
14236
|
+
return await bt.exchangeValidationService.list();
|
|
14104
14237
|
}
|
|
14105
14238
|
/**
|
|
14106
14239
|
* Returns a list of all registered strategy schemas.
|
|
@@ -14133,8 +14266,8 @@ async function listExchanges() {
|
|
|
14133
14266
|
* ```
|
|
14134
14267
|
*/
|
|
14135
14268
|
async function listStrategies() {
|
|
14136
|
-
|
|
14137
|
-
return await
|
|
14269
|
+
bt.loggerService.log(LIST_STRATEGIES_METHOD_NAME);
|
|
14270
|
+
return await bt.strategyValidationService.list();
|
|
14138
14271
|
}
|
|
14139
14272
|
/**
|
|
14140
14273
|
* Returns a list of all registered frame schemas.
|
|
@@ -14162,8 +14295,8 @@ async function listStrategies() {
|
|
|
14162
14295
|
* ```
|
|
14163
14296
|
*/
|
|
14164
14297
|
async function listFrames() {
|
|
14165
|
-
|
|
14166
|
-
return await
|
|
14298
|
+
bt.loggerService.log(LIST_FRAMES_METHOD_NAME);
|
|
14299
|
+
return await bt.frameValidationService.list();
|
|
14167
14300
|
}
|
|
14168
14301
|
/**
|
|
14169
14302
|
* Returns a list of all registered walker schemas.
|
|
@@ -14192,8 +14325,8 @@ async function listFrames() {
|
|
|
14192
14325
|
* ```
|
|
14193
14326
|
*/
|
|
14194
14327
|
async function listWalkers() {
|
|
14195
|
-
|
|
14196
|
-
return await
|
|
14328
|
+
bt.loggerService.log(LIST_WALKERS_METHOD_NAME);
|
|
14329
|
+
return await bt.walkerValidationService.list();
|
|
14197
14330
|
}
|
|
14198
14331
|
/**
|
|
14199
14332
|
* Returns a list of all registered sizing schemas.
|
|
@@ -14231,8 +14364,8 @@ async function listWalkers() {
|
|
|
14231
14364
|
* ```
|
|
14232
14365
|
*/
|
|
14233
14366
|
async function listSizings() {
|
|
14234
|
-
|
|
14235
|
-
return await
|
|
14367
|
+
bt.loggerService.log(LIST_SIZINGS_METHOD_NAME);
|
|
14368
|
+
return await bt.sizingValidationService.list();
|
|
14236
14369
|
}
|
|
14237
14370
|
/**
|
|
14238
14371
|
* Returns a list of all registered risk schemas.
|
|
@@ -14267,8 +14400,8 @@ async function listSizings() {
|
|
|
14267
14400
|
* ```
|
|
14268
14401
|
*/
|
|
14269
14402
|
async function listRisks() {
|
|
14270
|
-
|
|
14271
|
-
return await
|
|
14403
|
+
bt.loggerService.log(LIST_RISKS_METHOD_NAME);
|
|
14404
|
+
return await bt.riskValidationService.list();
|
|
14272
14405
|
}
|
|
14273
14406
|
/**
|
|
14274
14407
|
* Returns a list of all registered optimizer schemas.
|
|
@@ -14307,8 +14440,8 @@ async function listRisks() {
|
|
|
14307
14440
|
* ```
|
|
14308
14441
|
*/
|
|
14309
14442
|
async function listOptimizers() {
|
|
14310
|
-
|
|
14311
|
-
return await
|
|
14443
|
+
bt.loggerService.log(LIST_OPTIMIZERS_METHOD_NAME);
|
|
14444
|
+
return await bt.optimizerValidationService.list();
|
|
14312
14445
|
}
|
|
14313
14446
|
|
|
14314
14447
|
const LISTEN_SIGNAL_METHOD_NAME = "event.listenSignal";
|
|
@@ -14365,7 +14498,7 @@ const LISTEN_RISK_ONCE_METHOD_NAME = "event.listenRiskOnce";
|
|
|
14365
14498
|
* ```
|
|
14366
14499
|
*/
|
|
14367
14500
|
function listenSignal(fn) {
|
|
14368
|
-
|
|
14501
|
+
bt.loggerService.log(LISTEN_SIGNAL_METHOD_NAME);
|
|
14369
14502
|
return signalEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14370
14503
|
}
|
|
14371
14504
|
/**
|
|
@@ -14401,7 +14534,7 @@ function listenSignal(fn) {
|
|
|
14401
14534
|
* ```
|
|
14402
14535
|
*/
|
|
14403
14536
|
function listenSignalOnce(filterFn, fn) {
|
|
14404
|
-
|
|
14537
|
+
bt.loggerService.log(LISTEN_SIGNAL_ONCE_METHOD_NAME);
|
|
14405
14538
|
return signalEmitter.filter(filterFn).once(fn);
|
|
14406
14539
|
}
|
|
14407
14540
|
/**
|
|
@@ -14425,7 +14558,7 @@ function listenSignalOnce(filterFn, fn) {
|
|
|
14425
14558
|
* ```
|
|
14426
14559
|
*/
|
|
14427
14560
|
function listenSignalLive(fn) {
|
|
14428
|
-
|
|
14561
|
+
bt.loggerService.log(LISTEN_SIGNAL_LIVE_METHOD_NAME);
|
|
14429
14562
|
return signalLiveEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14430
14563
|
}
|
|
14431
14564
|
/**
|
|
@@ -14450,7 +14583,7 @@ function listenSignalLive(fn) {
|
|
|
14450
14583
|
* ```
|
|
14451
14584
|
*/
|
|
14452
14585
|
function listenSignalLiveOnce(filterFn, fn) {
|
|
14453
|
-
|
|
14586
|
+
bt.loggerService.log(LISTEN_SIGNAL_LIVE_ONCE_METHOD_NAME);
|
|
14454
14587
|
return signalLiveEmitter.filter(filterFn).once(fn);
|
|
14455
14588
|
}
|
|
14456
14589
|
/**
|
|
@@ -14474,7 +14607,7 @@ function listenSignalLiveOnce(filterFn, fn) {
|
|
|
14474
14607
|
* ```
|
|
14475
14608
|
*/
|
|
14476
14609
|
function listenSignalBacktest(fn) {
|
|
14477
|
-
|
|
14610
|
+
bt.loggerService.log(LISTEN_SIGNAL_BACKTEST_METHOD_NAME);
|
|
14478
14611
|
return signalBacktestEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14479
14612
|
}
|
|
14480
14613
|
/**
|
|
@@ -14499,7 +14632,7 @@ function listenSignalBacktest(fn) {
|
|
|
14499
14632
|
* ```
|
|
14500
14633
|
*/
|
|
14501
14634
|
function listenSignalBacktestOnce(filterFn, fn) {
|
|
14502
|
-
|
|
14635
|
+
bt.loggerService.log(LISTEN_SIGNAL_BACKTEST_ONCE_METHOD_NAME);
|
|
14503
14636
|
return signalBacktestEmitter.filter(filterFn).once(fn);
|
|
14504
14637
|
}
|
|
14505
14638
|
/**
|
|
@@ -14527,7 +14660,7 @@ function listenSignalBacktestOnce(filterFn, fn) {
|
|
|
14527
14660
|
* ```
|
|
14528
14661
|
*/
|
|
14529
14662
|
function listenError(fn) {
|
|
14530
|
-
|
|
14663
|
+
bt.loggerService.log(LISTEN_ERROR_METHOD_NAME);
|
|
14531
14664
|
return errorEmitter.subscribe(functoolsKit.queued(async (error) => fn(error)));
|
|
14532
14665
|
}
|
|
14533
14666
|
/**
|
|
@@ -14555,7 +14688,7 @@ function listenError(fn) {
|
|
|
14555
14688
|
* ```
|
|
14556
14689
|
*/
|
|
14557
14690
|
function listenExit(fn) {
|
|
14558
|
-
|
|
14691
|
+
bt.loggerService.log(LISTEN_EXIT_METHOD_NAME);
|
|
14559
14692
|
return exitEmitter.subscribe(functoolsKit.queued(async (error) => fn(error)));
|
|
14560
14693
|
}
|
|
14561
14694
|
/**
|
|
@@ -14586,7 +14719,7 @@ function listenExit(fn) {
|
|
|
14586
14719
|
* ```
|
|
14587
14720
|
*/
|
|
14588
14721
|
function listenDoneLive(fn) {
|
|
14589
|
-
|
|
14722
|
+
bt.loggerService.log(LISTEN_DONE_LIVE_METHOD_NAME);
|
|
14590
14723
|
return doneLiveSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14591
14724
|
}
|
|
14592
14725
|
/**
|
|
@@ -14616,7 +14749,7 @@ function listenDoneLive(fn) {
|
|
|
14616
14749
|
* ```
|
|
14617
14750
|
*/
|
|
14618
14751
|
function listenDoneLiveOnce(filterFn, fn) {
|
|
14619
|
-
|
|
14752
|
+
bt.loggerService.log(LISTEN_DONE_LIVE_ONCE_METHOD_NAME);
|
|
14620
14753
|
return doneLiveSubject.filter(filterFn).once(fn);
|
|
14621
14754
|
}
|
|
14622
14755
|
/**
|
|
@@ -14648,7 +14781,7 @@ function listenDoneLiveOnce(filterFn, fn) {
|
|
|
14648
14781
|
* ```
|
|
14649
14782
|
*/
|
|
14650
14783
|
function listenDoneBacktest(fn) {
|
|
14651
|
-
|
|
14784
|
+
bt.loggerService.log(LISTEN_DONE_BACKTEST_METHOD_NAME);
|
|
14652
14785
|
return doneBacktestSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14653
14786
|
}
|
|
14654
14787
|
/**
|
|
@@ -14679,7 +14812,7 @@ function listenDoneBacktest(fn) {
|
|
|
14679
14812
|
* ```
|
|
14680
14813
|
*/
|
|
14681
14814
|
function listenDoneBacktestOnce(filterFn, fn) {
|
|
14682
|
-
|
|
14815
|
+
bt.loggerService.log(LISTEN_DONE_BACKTEST_ONCE_METHOD_NAME);
|
|
14683
14816
|
return doneBacktestSubject.filter(filterFn).once(fn);
|
|
14684
14817
|
}
|
|
14685
14818
|
/**
|
|
@@ -14709,7 +14842,7 @@ function listenDoneBacktestOnce(filterFn, fn) {
|
|
|
14709
14842
|
* ```
|
|
14710
14843
|
*/
|
|
14711
14844
|
function listenDoneWalker(fn) {
|
|
14712
|
-
|
|
14845
|
+
bt.loggerService.log(LISTEN_DONE_WALKER_METHOD_NAME);
|
|
14713
14846
|
return doneWalkerSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14714
14847
|
}
|
|
14715
14848
|
/**
|
|
@@ -14738,7 +14871,7 @@ function listenDoneWalker(fn) {
|
|
|
14738
14871
|
* ```
|
|
14739
14872
|
*/
|
|
14740
14873
|
function listenDoneWalkerOnce(filterFn, fn) {
|
|
14741
|
-
|
|
14874
|
+
bt.loggerService.log(LISTEN_DONE_WALKER_ONCE_METHOD_NAME);
|
|
14742
14875
|
return doneWalkerSubject.filter(filterFn).once(fn);
|
|
14743
14876
|
}
|
|
14744
14877
|
/**
|
|
@@ -14772,7 +14905,7 @@ function listenDoneWalkerOnce(filterFn, fn) {
|
|
|
14772
14905
|
* ```
|
|
14773
14906
|
*/
|
|
14774
14907
|
function listenBacktestProgress(fn) {
|
|
14775
|
-
|
|
14908
|
+
bt.loggerService.log(LISTEN_PROGRESS_METHOD_NAME);
|
|
14776
14909
|
return progressBacktestEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14777
14910
|
}
|
|
14778
14911
|
/**
|
|
@@ -14806,7 +14939,7 @@ function listenBacktestProgress(fn) {
|
|
|
14806
14939
|
* ```
|
|
14807
14940
|
*/
|
|
14808
14941
|
function listenWalkerProgress(fn) {
|
|
14809
|
-
|
|
14942
|
+
bt.loggerService.log(LISTEN_PROGRESS_WALKER_METHOD_NAME);
|
|
14810
14943
|
return progressWalkerEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14811
14944
|
}
|
|
14812
14945
|
/**
|
|
@@ -14834,7 +14967,7 @@ function listenWalkerProgress(fn) {
|
|
|
14834
14967
|
* ```
|
|
14835
14968
|
*/
|
|
14836
14969
|
function listenOptimizerProgress(fn) {
|
|
14837
|
-
|
|
14970
|
+
bt.loggerService.log(LISTEN_PROGRESS_OPTIMIZER_METHOD_NAME);
|
|
14838
14971
|
return progressOptimizerEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14839
14972
|
}
|
|
14840
14973
|
/**
|
|
@@ -14870,7 +15003,7 @@ function listenOptimizerProgress(fn) {
|
|
|
14870
15003
|
* ```
|
|
14871
15004
|
*/
|
|
14872
15005
|
function listenPerformance(fn) {
|
|
14873
|
-
|
|
15006
|
+
bt.loggerService.log(LISTEN_PERFORMANCE_METHOD_NAME);
|
|
14874
15007
|
return performanceEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14875
15008
|
}
|
|
14876
15009
|
/**
|
|
@@ -14904,7 +15037,7 @@ function listenPerformance(fn) {
|
|
|
14904
15037
|
* ```
|
|
14905
15038
|
*/
|
|
14906
15039
|
function listenWalker(fn) {
|
|
14907
|
-
|
|
15040
|
+
bt.loggerService.log(LISTEN_WALKER_METHOD_NAME);
|
|
14908
15041
|
return walkerEmitter.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14909
15042
|
}
|
|
14910
15043
|
/**
|
|
@@ -14947,7 +15080,7 @@ function listenWalker(fn) {
|
|
|
14947
15080
|
* ```
|
|
14948
15081
|
*/
|
|
14949
15082
|
function listenWalkerOnce(filterFn, fn) {
|
|
14950
|
-
|
|
15083
|
+
bt.loggerService.log(LISTEN_WALKER_ONCE_METHOD_NAME);
|
|
14951
15084
|
return walkerEmitter.filter(filterFn).once(fn);
|
|
14952
15085
|
}
|
|
14953
15086
|
/**
|
|
@@ -14982,7 +15115,7 @@ function listenWalkerOnce(filterFn, fn) {
|
|
|
14982
15115
|
* ```
|
|
14983
15116
|
*/
|
|
14984
15117
|
function listenWalkerComplete(fn) {
|
|
14985
|
-
|
|
15118
|
+
bt.loggerService.log(LISTEN_WALKER_COMPLETE_METHOD_NAME);
|
|
14986
15119
|
return walkerCompleteSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
14987
15120
|
}
|
|
14988
15121
|
/**
|
|
@@ -15010,7 +15143,7 @@ function listenWalkerComplete(fn) {
|
|
|
15010
15143
|
* ```
|
|
15011
15144
|
*/
|
|
15012
15145
|
function listenValidation(fn) {
|
|
15013
|
-
|
|
15146
|
+
bt.loggerService.log(LISTEN_VALIDATION_METHOD_NAME);
|
|
15014
15147
|
return validationSubject.subscribe(functoolsKit.queued(async (error) => fn(error)));
|
|
15015
15148
|
}
|
|
15016
15149
|
/**
|
|
@@ -15038,7 +15171,7 @@ function listenValidation(fn) {
|
|
|
15038
15171
|
* ```
|
|
15039
15172
|
*/
|
|
15040
15173
|
function listenPartialProfit(fn) {
|
|
15041
|
-
|
|
15174
|
+
bt.loggerService.log(LISTEN_PARTIAL_PROFIT_METHOD_NAME);
|
|
15042
15175
|
return partialProfitSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
15043
15176
|
}
|
|
15044
15177
|
/**
|
|
@@ -15072,7 +15205,7 @@ function listenPartialProfit(fn) {
|
|
|
15072
15205
|
* ```
|
|
15073
15206
|
*/
|
|
15074
15207
|
function listenPartialProfitOnce(filterFn, fn) {
|
|
15075
|
-
|
|
15208
|
+
bt.loggerService.log(LISTEN_PARTIAL_PROFIT_ONCE_METHOD_NAME);
|
|
15076
15209
|
return partialProfitSubject.filter(filterFn).once(fn);
|
|
15077
15210
|
}
|
|
15078
15211
|
/**
|
|
@@ -15100,7 +15233,7 @@ function listenPartialProfitOnce(filterFn, fn) {
|
|
|
15100
15233
|
* ```
|
|
15101
15234
|
*/
|
|
15102
15235
|
function listenPartialLoss(fn) {
|
|
15103
|
-
|
|
15236
|
+
bt.loggerService.log(LISTEN_PARTIAL_LOSS_METHOD_NAME);
|
|
15104
15237
|
return partialLossSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
15105
15238
|
}
|
|
15106
15239
|
/**
|
|
@@ -15134,7 +15267,7 @@ function listenPartialLoss(fn) {
|
|
|
15134
15267
|
* ```
|
|
15135
15268
|
*/
|
|
15136
15269
|
function listenPartialLossOnce(filterFn, fn) {
|
|
15137
|
-
|
|
15270
|
+
bt.loggerService.log(LISTEN_PARTIAL_LOSS_ONCE_METHOD_NAME);
|
|
15138
15271
|
return partialLossSubject.filter(filterFn).once(fn);
|
|
15139
15272
|
}
|
|
15140
15273
|
/**
|
|
@@ -15166,7 +15299,7 @@ function listenPartialLossOnce(filterFn, fn) {
|
|
|
15166
15299
|
* ```
|
|
15167
15300
|
*/
|
|
15168
15301
|
function listenRisk(fn) {
|
|
15169
|
-
|
|
15302
|
+
bt.loggerService.log(LISTEN_RISK_METHOD_NAME);
|
|
15170
15303
|
return riskSubject.subscribe(functoolsKit.queued(async (event) => fn(event)));
|
|
15171
15304
|
}
|
|
15172
15305
|
/**
|
|
@@ -15203,7 +15336,7 @@ function listenRisk(fn) {
|
|
|
15203
15336
|
* ```
|
|
15204
15337
|
*/
|
|
15205
15338
|
function listenRiskOnce(filterFn, fn) {
|
|
15206
|
-
|
|
15339
|
+
bt.loggerService.log(LISTEN_RISK_ONCE_METHOD_NAME);
|
|
15207
15340
|
return riskSubject.filter(filterFn).once(fn);
|
|
15208
15341
|
}
|
|
15209
15342
|
|
|
@@ -15231,12 +15364,12 @@ const GET_MODE_METHOD_NAME = "exchange.getMode";
|
|
|
15231
15364
|
* ```
|
|
15232
15365
|
*/
|
|
15233
15366
|
async function getCandles(symbol, interval, limit) {
|
|
15234
|
-
|
|
15367
|
+
bt.loggerService.info(GET_CANDLES_METHOD_NAME, {
|
|
15235
15368
|
symbol,
|
|
15236
15369
|
interval,
|
|
15237
15370
|
limit,
|
|
15238
15371
|
});
|
|
15239
|
-
return await
|
|
15372
|
+
return await bt.exchangeConnectionService.getCandles(symbol, interval, limit);
|
|
15240
15373
|
}
|
|
15241
15374
|
/**
|
|
15242
15375
|
* Calculates VWAP (Volume Weighted Average Price) for a symbol.
|
|
@@ -15257,10 +15390,10 @@ async function getCandles(symbol, interval, limit) {
|
|
|
15257
15390
|
* ```
|
|
15258
15391
|
*/
|
|
15259
15392
|
async function getAveragePrice(symbol) {
|
|
15260
|
-
|
|
15393
|
+
bt.loggerService.info(GET_AVERAGE_PRICE_METHOD_NAME, {
|
|
15261
15394
|
symbol,
|
|
15262
15395
|
});
|
|
15263
|
-
return await
|
|
15396
|
+
return await bt.exchangeConnectionService.getAveragePrice(symbol);
|
|
15264
15397
|
}
|
|
15265
15398
|
/**
|
|
15266
15399
|
* Formats a price value according to exchange rules.
|
|
@@ -15278,11 +15411,11 @@ async function getAveragePrice(symbol) {
|
|
|
15278
15411
|
* ```
|
|
15279
15412
|
*/
|
|
15280
15413
|
async function formatPrice(symbol, price) {
|
|
15281
|
-
|
|
15414
|
+
bt.loggerService.info(FORMAT_PRICE_METHOD_NAME, {
|
|
15282
15415
|
symbol,
|
|
15283
15416
|
price,
|
|
15284
15417
|
});
|
|
15285
|
-
return await
|
|
15418
|
+
return await bt.exchangeConnectionService.formatPrice(symbol, price);
|
|
15286
15419
|
}
|
|
15287
15420
|
/**
|
|
15288
15421
|
* Formats a quantity value according to exchange rules.
|
|
@@ -15300,11 +15433,11 @@ async function formatPrice(symbol, price) {
|
|
|
15300
15433
|
* ```
|
|
15301
15434
|
*/
|
|
15302
15435
|
async function formatQuantity(symbol, quantity) {
|
|
15303
|
-
|
|
15436
|
+
bt.loggerService.info(FORMAT_QUANTITY_METHOD_NAME, {
|
|
15304
15437
|
symbol,
|
|
15305
15438
|
quantity,
|
|
15306
15439
|
});
|
|
15307
|
-
return await
|
|
15440
|
+
return await bt.exchangeConnectionService.formatQuantity(symbol, quantity);
|
|
15308
15441
|
}
|
|
15309
15442
|
/**
|
|
15310
15443
|
* Gets the current date from execution context.
|
|
@@ -15321,8 +15454,8 @@ async function formatQuantity(symbol, quantity) {
|
|
|
15321
15454
|
* ```
|
|
15322
15455
|
*/
|
|
15323
15456
|
async function getDate() {
|
|
15324
|
-
|
|
15325
|
-
const { when } =
|
|
15457
|
+
bt.loggerService.info(GET_DATE_METHOD_NAME);
|
|
15458
|
+
const { when } = bt.executionContextService.context;
|
|
15326
15459
|
return new Date(when.getTime());
|
|
15327
15460
|
}
|
|
15328
15461
|
/**
|
|
@@ -15341,9 +15474,9 @@ async function getDate() {
|
|
|
15341
15474
|
* ```
|
|
15342
15475
|
*/
|
|
15343
15476
|
async function getMode() {
|
|
15344
|
-
|
|
15345
|
-
const { backtest: bt } =
|
|
15346
|
-
return bt ? "backtest" : "live";
|
|
15477
|
+
bt.loggerService.info(GET_MODE_METHOD_NAME);
|
|
15478
|
+
const { backtest: bt$1 } = bt.executionContextService.context;
|
|
15479
|
+
return bt$1 ? "backtest" : "live";
|
|
15347
15480
|
}
|
|
15348
15481
|
|
|
15349
15482
|
const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
|
|
@@ -15414,13 +15547,13 @@ const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
|
|
|
15414
15547
|
* ```
|
|
15415
15548
|
*/
|
|
15416
15549
|
async function dumpSignal(signalId, history, signal, outputDir = "./dump/strategy") {
|
|
15417
|
-
|
|
15550
|
+
bt.loggerService.info(DUMP_SIGNAL_METHOD_NAME, {
|
|
15418
15551
|
signalId,
|
|
15419
15552
|
history,
|
|
15420
15553
|
signal,
|
|
15421
15554
|
outputDir,
|
|
15422
15555
|
});
|
|
15423
|
-
return await
|
|
15556
|
+
return await bt.outlineMarkdownService.dumpSignal(signalId, history, signal, outputDir);
|
|
15424
15557
|
}
|
|
15425
15558
|
|
|
15426
15559
|
const BACKTEST_METHOD_NAME_RUN = "BacktestUtils.run";
|
|
@@ -15507,7 +15640,7 @@ class BacktestInstance {
|
|
|
15507
15640
|
* @internal
|
|
15508
15641
|
*/
|
|
15509
15642
|
this.task = functoolsKit.singlerun(async (symbol, context) => {
|
|
15510
|
-
|
|
15643
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_TASK, {
|
|
15511
15644
|
symbol,
|
|
15512
15645
|
context,
|
|
15513
15646
|
});
|
|
@@ -15526,7 +15659,7 @@ class BacktestInstance {
|
|
|
15526
15659
|
* ```
|
|
15527
15660
|
*/
|
|
15528
15661
|
this.getStatus = async () => {
|
|
15529
|
-
|
|
15662
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_GET_STATUS);
|
|
15530
15663
|
return {
|
|
15531
15664
|
id: this.id,
|
|
15532
15665
|
symbol: this.symbol,
|
|
@@ -15542,23 +15675,27 @@ class BacktestInstance {
|
|
|
15542
15675
|
* @returns Async generator yielding closed signals with PNL
|
|
15543
15676
|
*/
|
|
15544
15677
|
this.run = (symbol, context) => {
|
|
15545
|
-
|
|
15678
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_RUN, {
|
|
15546
15679
|
symbol,
|
|
15547
15680
|
context,
|
|
15548
15681
|
});
|
|
15549
15682
|
{
|
|
15550
|
-
|
|
15551
|
-
|
|
15683
|
+
bt.backtestMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15684
|
+
bt.liveMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15685
|
+
bt.scheduleMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15686
|
+
bt.performanceMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15687
|
+
bt.partialMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15688
|
+
bt.riskMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15552
15689
|
}
|
|
15553
15690
|
{
|
|
15554
|
-
|
|
15691
|
+
bt.strategyCoreService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15555
15692
|
}
|
|
15556
15693
|
{
|
|
15557
|
-
const { riskName, riskList } =
|
|
15558
|
-
riskName &&
|
|
15559
|
-
riskList && riskList.forEach((riskName) =>
|
|
15694
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
15695
|
+
riskName && bt.riskGlobalService.clear(true, riskName);
|
|
15696
|
+
riskList && riskList.forEach((riskName) => bt.riskGlobalService.clear(true, riskName));
|
|
15560
15697
|
}
|
|
15561
|
-
return
|
|
15698
|
+
return bt.backtestCommandService.run(symbol, context);
|
|
15562
15699
|
};
|
|
15563
15700
|
/**
|
|
15564
15701
|
* Runs backtest in background without yielding results.
|
|
@@ -15581,15 +15718,24 @@ class BacktestInstance {
|
|
|
15581
15718
|
* ```
|
|
15582
15719
|
*/
|
|
15583
15720
|
this.background = (symbol, context) => {
|
|
15584
|
-
|
|
15721
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_BACKGROUND, {
|
|
15585
15722
|
symbol,
|
|
15586
15723
|
context,
|
|
15587
15724
|
});
|
|
15725
|
+
{
|
|
15726
|
+
const currentStatus = this.task.getStatus();
|
|
15727
|
+
if (currentStatus === "pending") {
|
|
15728
|
+
throw new Error(`Backtest.background is already running for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName} frameName=${context.frameName}`);
|
|
15729
|
+
}
|
|
15730
|
+
if (currentStatus === "rejected") {
|
|
15731
|
+
throw new Error(`Backtest.background has failed for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName} frameName=${context.frameName}`);
|
|
15732
|
+
}
|
|
15733
|
+
}
|
|
15588
15734
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
|
|
15589
15735
|
return () => {
|
|
15590
|
-
|
|
15591
|
-
|
|
15592
|
-
.getPendingSignal(symbol, context.strategyName)
|
|
15736
|
+
bt.strategyCoreService.stop(true, { symbol, strategyName: context.strategyName });
|
|
15737
|
+
bt.strategyCoreService
|
|
15738
|
+
.getPendingSignal(true, symbol, context.strategyName)
|
|
15593
15739
|
.then(async (pendingSignal) => {
|
|
15594
15740
|
if (pendingSignal) {
|
|
15595
15741
|
return;
|
|
@@ -15625,11 +15771,11 @@ class BacktestInstance {
|
|
|
15625
15771
|
* ```
|
|
15626
15772
|
*/
|
|
15627
15773
|
this.stop = async (symbol, strategyName) => {
|
|
15628
|
-
|
|
15774
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_STOP, {
|
|
15629
15775
|
symbol,
|
|
15630
15776
|
strategyName,
|
|
15631
15777
|
});
|
|
15632
|
-
await
|
|
15778
|
+
await bt.strategyCoreService.stop(true, { symbol, strategyName });
|
|
15633
15779
|
};
|
|
15634
15780
|
/**
|
|
15635
15781
|
* Gets statistical data from all closed signals for a symbol-strategy pair.
|
|
@@ -15646,11 +15792,11 @@ class BacktestInstance {
|
|
|
15646
15792
|
* ```
|
|
15647
15793
|
*/
|
|
15648
15794
|
this.getData = async (symbol, strategyName) => {
|
|
15649
|
-
|
|
15795
|
+
bt.loggerService.info("BacktestUtils.getData", {
|
|
15650
15796
|
symbol,
|
|
15651
15797
|
strategyName,
|
|
15652
15798
|
});
|
|
15653
|
-
return await
|
|
15799
|
+
return await bt.backtestMarkdownService.getData(symbol, strategyName, true);
|
|
15654
15800
|
};
|
|
15655
15801
|
/**
|
|
15656
15802
|
* Generates markdown report with all closed signals for a symbol-strategy pair.
|
|
@@ -15668,11 +15814,11 @@ class BacktestInstance {
|
|
|
15668
15814
|
* ```
|
|
15669
15815
|
*/
|
|
15670
15816
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
15671
|
-
|
|
15817
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_GET_REPORT, {
|
|
15672
15818
|
symbol,
|
|
15673
15819
|
strategyName,
|
|
15674
15820
|
});
|
|
15675
|
-
return await
|
|
15821
|
+
return await bt.backtestMarkdownService.getReport(symbol, strategyName, true, columns);
|
|
15676
15822
|
};
|
|
15677
15823
|
/**
|
|
15678
15824
|
* Saves strategy report to disk.
|
|
@@ -15693,12 +15839,12 @@ class BacktestInstance {
|
|
|
15693
15839
|
* ```
|
|
15694
15840
|
*/
|
|
15695
15841
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
15696
|
-
|
|
15842
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_DUMP, {
|
|
15697
15843
|
symbol,
|
|
15698
15844
|
strategyName,
|
|
15699
15845
|
path,
|
|
15700
15846
|
});
|
|
15701
|
-
await
|
|
15847
|
+
await bt.backtestMarkdownService.dump(symbol, strategyName, true, path, columns);
|
|
15702
15848
|
};
|
|
15703
15849
|
}
|
|
15704
15850
|
}
|
|
@@ -15737,14 +15883,14 @@ class BacktestUtils {
|
|
|
15737
15883
|
*/
|
|
15738
15884
|
this.run = (symbol, context) => {
|
|
15739
15885
|
{
|
|
15740
|
-
|
|
15741
|
-
|
|
15742
|
-
|
|
15886
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_RUN);
|
|
15887
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_RUN);
|
|
15888
|
+
bt.frameValidationService.validate(context.frameName, BACKTEST_METHOD_NAME_RUN);
|
|
15743
15889
|
}
|
|
15744
15890
|
{
|
|
15745
|
-
const { riskName, riskList } =
|
|
15746
|
-
riskName &&
|
|
15747
|
-
riskList && riskList.forEach((riskName) =>
|
|
15891
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
15892
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_RUN);
|
|
15893
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_RUN));
|
|
15748
15894
|
}
|
|
15749
15895
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
15750
15896
|
return instance.run(symbol, context);
|
|
@@ -15771,13 +15917,13 @@ class BacktestUtils {
|
|
|
15771
15917
|
* ```
|
|
15772
15918
|
*/
|
|
15773
15919
|
this.background = (symbol, context) => {
|
|
15774
|
-
|
|
15775
|
-
|
|
15776
|
-
|
|
15920
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15921
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15922
|
+
bt.frameValidationService.validate(context.frameName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15777
15923
|
{
|
|
15778
|
-
const { riskName, riskList } =
|
|
15779
|
-
riskName &&
|
|
15780
|
-
riskList && riskList.forEach((riskName) =>
|
|
15924
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
15925
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15926
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BACKGROUND));
|
|
15781
15927
|
}
|
|
15782
15928
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
15783
15929
|
return instance.background(symbol, context);
|
|
@@ -15800,11 +15946,11 @@ class BacktestUtils {
|
|
|
15800
15946
|
* ```
|
|
15801
15947
|
*/
|
|
15802
15948
|
this.stop = async (symbol, strategyName) => {
|
|
15803
|
-
|
|
15949
|
+
bt.strategyValidationService.validate(strategyName, BACKTEST_METHOD_NAME_STOP);
|
|
15804
15950
|
{
|
|
15805
|
-
const { riskName, riskList } =
|
|
15806
|
-
riskName &&
|
|
15807
|
-
riskList && riskList.forEach((riskName) =>
|
|
15951
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
15952
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_STOP);
|
|
15953
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_STOP));
|
|
15808
15954
|
}
|
|
15809
15955
|
const instance = this._getInstance(symbol, strategyName);
|
|
15810
15956
|
return await instance.stop(symbol, strategyName);
|
|
@@ -15823,11 +15969,11 @@ class BacktestUtils {
|
|
|
15823
15969
|
* ```
|
|
15824
15970
|
*/
|
|
15825
15971
|
this.getData = async (symbol, strategyName) => {
|
|
15826
|
-
|
|
15972
|
+
bt.strategyValidationService.validate(strategyName, "BacktestUtils.getData");
|
|
15827
15973
|
{
|
|
15828
|
-
const { riskName, riskList } =
|
|
15829
|
-
riskName &&
|
|
15830
|
-
riskList && riskList.forEach((riskName) =>
|
|
15974
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
15975
|
+
riskName && bt.riskValidationService.validate(riskName, "BacktestUtils.getData");
|
|
15976
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, "BacktestUtils.getData"));
|
|
15831
15977
|
}
|
|
15832
15978
|
const instance = this._getInstance(symbol, strategyName);
|
|
15833
15979
|
return await instance.getData(symbol, strategyName);
|
|
@@ -15847,11 +15993,11 @@ class BacktestUtils {
|
|
|
15847
15993
|
* ```
|
|
15848
15994
|
*/
|
|
15849
15995
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
15850
|
-
|
|
15996
|
+
bt.strategyValidationService.validate(strategyName, BACKTEST_METHOD_NAME_GET_REPORT);
|
|
15851
15997
|
{
|
|
15852
|
-
const { riskName, riskList } =
|
|
15853
|
-
riskName &&
|
|
15854
|
-
riskList && riskList.forEach((riskName) =>
|
|
15998
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
15999
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_REPORT);
|
|
16000
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_REPORT));
|
|
15855
16001
|
}
|
|
15856
16002
|
const instance = this._getInstance(symbol, strategyName);
|
|
15857
16003
|
return await instance.getReport(symbol, strategyName, columns);
|
|
@@ -15874,11 +16020,11 @@ class BacktestUtils {
|
|
|
15874
16020
|
* ```
|
|
15875
16021
|
*/
|
|
15876
16022
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
15877
|
-
|
|
16023
|
+
bt.strategyValidationService.validate(strategyName, BACKTEST_METHOD_NAME_DUMP);
|
|
15878
16024
|
{
|
|
15879
|
-
const { riskName, riskList } =
|
|
15880
|
-
riskName &&
|
|
15881
|
-
riskList && riskList.forEach((riskName) =>
|
|
16025
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16026
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_DUMP);
|
|
16027
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_DUMP));
|
|
15882
16028
|
}
|
|
15883
16029
|
const instance = this._getInstance(symbol, strategyName);
|
|
15884
16030
|
return await instance.dump(symbol, strategyName, path, columns);
|
|
@@ -16008,7 +16154,7 @@ class LiveInstance {
|
|
|
16008
16154
|
* @internal
|
|
16009
16155
|
*/
|
|
16010
16156
|
this.task = functoolsKit.singlerun(async (symbol, context) => {
|
|
16011
|
-
|
|
16157
|
+
bt.loggerService.info(LIVE_METHOD_NAME_TASK, {
|
|
16012
16158
|
symbol,
|
|
16013
16159
|
context,
|
|
16014
16160
|
});
|
|
@@ -16027,7 +16173,7 @@ class LiveInstance {
|
|
|
16027
16173
|
* ```
|
|
16028
16174
|
*/
|
|
16029
16175
|
this.getStatus = async () => {
|
|
16030
|
-
|
|
16176
|
+
bt.loggerService.info(LIVE_METHOD_NAME_GET_STATUS);
|
|
16031
16177
|
return {
|
|
16032
16178
|
id: this.id,
|
|
16033
16179
|
symbol: this.symbol,
|
|
@@ -16046,23 +16192,27 @@ class LiveInstance {
|
|
|
16046
16192
|
* @returns Infinite async generator yielding opened and closed signals
|
|
16047
16193
|
*/
|
|
16048
16194
|
this.run = (symbol, context) => {
|
|
16049
|
-
|
|
16195
|
+
bt.loggerService.info(LIVE_METHOD_NAME_RUN, {
|
|
16050
16196
|
symbol,
|
|
16051
16197
|
context,
|
|
16052
16198
|
});
|
|
16053
16199
|
{
|
|
16054
|
-
|
|
16055
|
-
|
|
16200
|
+
bt.backtestMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16201
|
+
bt.liveMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16202
|
+
bt.scheduleMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16203
|
+
bt.performanceMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16204
|
+
bt.partialMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16205
|
+
bt.riskMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16056
16206
|
}
|
|
16057
16207
|
{
|
|
16058
|
-
|
|
16208
|
+
bt.strategyCoreService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16059
16209
|
}
|
|
16060
16210
|
{
|
|
16061
|
-
const { riskName, riskList } =
|
|
16062
|
-
riskName &&
|
|
16063
|
-
riskList && riskList.forEach((riskName) =>
|
|
16211
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
16212
|
+
riskName && bt.riskGlobalService.clear(false, riskName);
|
|
16213
|
+
riskList && riskList.forEach((riskName) => bt.riskGlobalService.clear(false, riskName));
|
|
16064
16214
|
}
|
|
16065
|
-
return
|
|
16215
|
+
return bt.liveCommandService.run(symbol, context);
|
|
16066
16216
|
};
|
|
16067
16217
|
/**
|
|
16068
16218
|
* Runs live trading in background without yielding results.
|
|
@@ -16085,15 +16235,24 @@ class LiveInstance {
|
|
|
16085
16235
|
* ```
|
|
16086
16236
|
*/
|
|
16087
16237
|
this.background = (symbol, context) => {
|
|
16088
|
-
|
|
16238
|
+
bt.loggerService.info(LIVE_METHOD_NAME_BACKGROUND, {
|
|
16089
16239
|
symbol,
|
|
16090
16240
|
context,
|
|
16091
16241
|
});
|
|
16242
|
+
const currentStatus = this.task.getStatus();
|
|
16243
|
+
{
|
|
16244
|
+
if (currentStatus === "pending") {
|
|
16245
|
+
throw new Error(`Live.background is already running for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName}`);
|
|
16246
|
+
}
|
|
16247
|
+
if (currentStatus === "rejected") {
|
|
16248
|
+
throw new Error(`Live.background has failed for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName}`);
|
|
16249
|
+
}
|
|
16250
|
+
}
|
|
16092
16251
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
|
|
16093
16252
|
return () => {
|
|
16094
|
-
|
|
16095
|
-
|
|
16096
|
-
.getPendingSignal(symbol, context.strategyName)
|
|
16253
|
+
bt.strategyCoreService.stop(false, { symbol, strategyName: context.strategyName });
|
|
16254
|
+
bt.strategyCoreService
|
|
16255
|
+
.getPendingSignal(false, symbol, context.strategyName)
|
|
16097
16256
|
.then(async (pendingSignal) => {
|
|
16098
16257
|
if (pendingSignal) {
|
|
16099
16258
|
return;
|
|
@@ -16129,11 +16288,11 @@ class LiveInstance {
|
|
|
16129
16288
|
* ```
|
|
16130
16289
|
*/
|
|
16131
16290
|
this.stop = async (symbol, strategyName) => {
|
|
16132
|
-
|
|
16291
|
+
bt.loggerService.info(LIVE_METHOD_NAME_STOP, {
|
|
16133
16292
|
symbol,
|
|
16134
16293
|
strategyName,
|
|
16135
16294
|
});
|
|
16136
|
-
await
|
|
16295
|
+
await bt.strategyCoreService.stop(false, { symbol, strategyName });
|
|
16137
16296
|
};
|
|
16138
16297
|
/**
|
|
16139
16298
|
* Gets statistical data from all live trading events for a symbol-strategy pair.
|
|
@@ -16150,11 +16309,11 @@ class LiveInstance {
|
|
|
16150
16309
|
* ```
|
|
16151
16310
|
*/
|
|
16152
16311
|
this.getData = async (symbol, strategyName) => {
|
|
16153
|
-
|
|
16312
|
+
bt.loggerService.info("LiveUtils.getData", {
|
|
16154
16313
|
symbol,
|
|
16155
16314
|
strategyName,
|
|
16156
16315
|
});
|
|
16157
|
-
return await
|
|
16316
|
+
return await bt.liveMarkdownService.getData(symbol, strategyName, false);
|
|
16158
16317
|
};
|
|
16159
16318
|
/**
|
|
16160
16319
|
* Generates markdown report with all events for a symbol-strategy pair.
|
|
@@ -16172,11 +16331,11 @@ class LiveInstance {
|
|
|
16172
16331
|
* ```
|
|
16173
16332
|
*/
|
|
16174
16333
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
16175
|
-
|
|
16334
|
+
bt.loggerService.info(LIVE_METHOD_NAME_GET_REPORT, {
|
|
16176
16335
|
symbol,
|
|
16177
16336
|
strategyName,
|
|
16178
16337
|
});
|
|
16179
|
-
return await
|
|
16338
|
+
return await bt.liveMarkdownService.getReport(symbol, strategyName, false, columns);
|
|
16180
16339
|
};
|
|
16181
16340
|
/**
|
|
16182
16341
|
* Saves strategy report to disk.
|
|
@@ -16197,12 +16356,12 @@ class LiveInstance {
|
|
|
16197
16356
|
* ```
|
|
16198
16357
|
*/
|
|
16199
16358
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
16200
|
-
|
|
16359
|
+
bt.loggerService.info(LIVE_METHOD_NAME_DUMP, {
|
|
16201
16360
|
symbol,
|
|
16202
16361
|
strategyName,
|
|
16203
16362
|
path,
|
|
16204
16363
|
});
|
|
16205
|
-
await
|
|
16364
|
+
await bt.liveMarkdownService.dump(symbol, strategyName, false, path, columns);
|
|
16206
16365
|
};
|
|
16207
16366
|
}
|
|
16208
16367
|
}
|
|
@@ -16254,13 +16413,13 @@ class LiveUtils {
|
|
|
16254
16413
|
*/
|
|
16255
16414
|
this.run = (symbol, context) => {
|
|
16256
16415
|
{
|
|
16257
|
-
|
|
16258
|
-
|
|
16416
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_RUN);
|
|
16417
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_RUN);
|
|
16259
16418
|
}
|
|
16260
16419
|
{
|
|
16261
|
-
const { riskName, riskList } =
|
|
16262
|
-
riskName &&
|
|
16263
|
-
riskList && riskList.forEach((riskName) =>
|
|
16420
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
16421
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_RUN);
|
|
16422
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_RUN));
|
|
16264
16423
|
}
|
|
16265
16424
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
16266
16425
|
return instance.run(symbol, context);
|
|
@@ -16287,12 +16446,12 @@ class LiveUtils {
|
|
|
16287
16446
|
* ```
|
|
16288
16447
|
*/
|
|
16289
16448
|
this.background = (symbol, context) => {
|
|
16290
|
-
|
|
16291
|
-
|
|
16449
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_BACKGROUND);
|
|
16450
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_BACKGROUND);
|
|
16292
16451
|
{
|
|
16293
|
-
const { riskName, riskList } =
|
|
16294
|
-
riskName &&
|
|
16295
|
-
riskList && riskList.forEach((riskName) =>
|
|
16452
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
16453
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_BACKGROUND);
|
|
16454
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_BACKGROUND));
|
|
16296
16455
|
}
|
|
16297
16456
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
16298
16457
|
return instance.background(symbol, context);
|
|
@@ -16315,11 +16474,11 @@ class LiveUtils {
|
|
|
16315
16474
|
* ```
|
|
16316
16475
|
*/
|
|
16317
16476
|
this.stop = async (symbol, strategyName) => {
|
|
16318
|
-
|
|
16477
|
+
bt.strategyValidationService.validate(strategyName, LIVE_METHOD_NAME_STOP);
|
|
16319
16478
|
{
|
|
16320
|
-
const { riskName, riskList } =
|
|
16321
|
-
riskName &&
|
|
16322
|
-
riskList && riskList.forEach((riskName) =>
|
|
16479
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16480
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_STOP);
|
|
16481
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_STOP));
|
|
16323
16482
|
}
|
|
16324
16483
|
const instance = this._getInstance(symbol, strategyName);
|
|
16325
16484
|
return await instance.stop(symbol, strategyName);
|
|
@@ -16338,11 +16497,11 @@ class LiveUtils {
|
|
|
16338
16497
|
* ```
|
|
16339
16498
|
*/
|
|
16340
16499
|
this.getData = async (symbol, strategyName) => {
|
|
16341
|
-
|
|
16500
|
+
bt.strategyValidationService.validate(strategyName, "LiveUtils.getData");
|
|
16342
16501
|
{
|
|
16343
|
-
const { riskName, riskList } =
|
|
16344
|
-
riskName &&
|
|
16345
|
-
riskList && riskList.forEach((riskName) =>
|
|
16502
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16503
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_DATA);
|
|
16504
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_DATA));
|
|
16346
16505
|
}
|
|
16347
16506
|
const instance = this._getInstance(symbol, strategyName);
|
|
16348
16507
|
return await instance.getData(symbol, strategyName);
|
|
@@ -16362,11 +16521,11 @@ class LiveUtils {
|
|
|
16362
16521
|
* ```
|
|
16363
16522
|
*/
|
|
16364
16523
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
16365
|
-
|
|
16524
|
+
bt.strategyValidationService.validate(strategyName, LIVE_METHOD_NAME_GET_REPORT);
|
|
16366
16525
|
{
|
|
16367
|
-
const { riskName, riskList } =
|
|
16368
|
-
riskName &&
|
|
16369
|
-
riskList && riskList.forEach((riskName) =>
|
|
16526
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16527
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_REPORT);
|
|
16528
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_REPORT));
|
|
16370
16529
|
}
|
|
16371
16530
|
const instance = this._getInstance(symbol, strategyName);
|
|
16372
16531
|
return await instance.getReport(symbol, strategyName, columns);
|
|
@@ -16389,11 +16548,11 @@ class LiveUtils {
|
|
|
16389
16548
|
* ```
|
|
16390
16549
|
*/
|
|
16391
16550
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
16392
|
-
|
|
16551
|
+
bt.strategyValidationService.validate(strategyName, LIVE_METHOD_NAME_DUMP);
|
|
16393
16552
|
{
|
|
16394
|
-
const { riskName, riskList } =
|
|
16395
|
-
riskName &&
|
|
16396
|
-
riskList && riskList.forEach((riskName) =>
|
|
16553
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16554
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_DUMP);
|
|
16555
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_DUMP));
|
|
16397
16556
|
}
|
|
16398
16557
|
const instance = this._getInstance(symbol, strategyName);
|
|
16399
16558
|
return await instance.dump(symbol, strategyName, path, columns);
|
|
@@ -16477,18 +16636,19 @@ class ScheduleUtils {
|
|
|
16477
16636
|
* console.log(stats.cancellationRate, stats.avgWaitTime);
|
|
16478
16637
|
* ```
|
|
16479
16638
|
*/
|
|
16480
|
-
this.getData = async (symbol, strategyName) => {
|
|
16481
|
-
|
|
16639
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
16640
|
+
bt.loggerService.info(SCHEDULE_METHOD_NAME_GET_DATA, {
|
|
16482
16641
|
symbol,
|
|
16483
16642
|
strategyName,
|
|
16643
|
+
backtest,
|
|
16484
16644
|
});
|
|
16485
|
-
|
|
16645
|
+
bt.strategyValidationService.validate(strategyName, SCHEDULE_METHOD_NAME_GET_DATA);
|
|
16486
16646
|
{
|
|
16487
|
-
const { riskName, riskList } =
|
|
16488
|
-
riskName &&
|
|
16489
|
-
riskList && riskList.forEach((riskName) =>
|
|
16647
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16648
|
+
riskName && bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_DATA);
|
|
16649
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_DATA));
|
|
16490
16650
|
}
|
|
16491
|
-
return await
|
|
16651
|
+
return await bt.scheduleMarkdownService.getData(symbol, strategyName, backtest);
|
|
16492
16652
|
};
|
|
16493
16653
|
/**
|
|
16494
16654
|
* Generates markdown report with all scheduled events for a symbol-strategy pair.
|
|
@@ -16504,18 +16664,19 @@ class ScheduleUtils {
|
|
|
16504
16664
|
* console.log(markdown);
|
|
16505
16665
|
* ```
|
|
16506
16666
|
*/
|
|
16507
|
-
this.getReport = async (symbol, strategyName, columns) => {
|
|
16508
|
-
|
|
16667
|
+
this.getReport = async (symbol, strategyName, backtest, columns) => {
|
|
16668
|
+
bt.loggerService.info(SCHEDULE_METHOD_NAME_GET_REPORT, {
|
|
16509
16669
|
symbol,
|
|
16510
16670
|
strategyName,
|
|
16671
|
+
backtest,
|
|
16511
16672
|
});
|
|
16512
|
-
|
|
16673
|
+
bt.strategyValidationService.validate(strategyName, SCHEDULE_METHOD_NAME_GET_REPORT);
|
|
16513
16674
|
{
|
|
16514
|
-
const { riskName, riskList } =
|
|
16515
|
-
riskName &&
|
|
16516
|
-
riskList && riskList.forEach((riskName) =>
|
|
16675
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16676
|
+
riskName && bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_REPORT);
|
|
16677
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_REPORT));
|
|
16517
16678
|
}
|
|
16518
|
-
return await
|
|
16679
|
+
return await bt.scheduleMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
16519
16680
|
};
|
|
16520
16681
|
/**
|
|
16521
16682
|
* Saves strategy report to disk.
|
|
@@ -16534,19 +16695,20 @@ class ScheduleUtils {
|
|
|
16534
16695
|
* await Schedule.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
16535
16696
|
* ```
|
|
16536
16697
|
*/
|
|
16537
|
-
this.dump = async (symbol, strategyName, path, columns) => {
|
|
16538
|
-
|
|
16698
|
+
this.dump = async (symbol, strategyName, backtest, path, columns) => {
|
|
16699
|
+
bt.loggerService.info(SCHEDULE_METHOD_NAME_DUMP, {
|
|
16539
16700
|
symbol,
|
|
16540
16701
|
strategyName,
|
|
16702
|
+
backtest,
|
|
16541
16703
|
path,
|
|
16542
16704
|
});
|
|
16543
|
-
|
|
16705
|
+
bt.strategyValidationService.validate(strategyName, SCHEDULE_METHOD_NAME_DUMP);
|
|
16544
16706
|
{
|
|
16545
|
-
const { riskName, riskList } =
|
|
16546
|
-
riskName &&
|
|
16547
|
-
riskList && riskList.forEach((riskName) =>
|
|
16707
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16708
|
+
riskName && bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_DUMP);
|
|
16709
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_DUMP));
|
|
16548
16710
|
}
|
|
16549
|
-
await
|
|
16711
|
+
await bt.scheduleMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
16550
16712
|
};
|
|
16551
16713
|
}
|
|
16552
16714
|
}
|
|
@@ -16584,7 +16746,7 @@ const PERFORMANCE_METHOD_NAME_DUMP = "Performance.dump";
|
|
|
16584
16746
|
* console.log(`${event.metricType}: ${event.duration.toFixed(2)}ms`);
|
|
16585
16747
|
* });
|
|
16586
16748
|
*
|
|
16587
|
-
* // Run
|
|
16749
|
+
* // Run bt...
|
|
16588
16750
|
*
|
|
16589
16751
|
* // Get aggregated statistics
|
|
16590
16752
|
* const stats = await Performance.getData("my-strategy");
|
|
@@ -16627,14 +16789,14 @@ class Performance {
|
|
|
16627
16789
|
* }
|
|
16628
16790
|
* ```
|
|
16629
16791
|
*/
|
|
16630
|
-
static async getData(symbol, strategyName) {
|
|
16631
|
-
|
|
16792
|
+
static async getData(symbol, strategyName, backtest) {
|
|
16793
|
+
bt.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_DATA);
|
|
16632
16794
|
{
|
|
16633
|
-
const { riskName, riskList } =
|
|
16634
|
-
riskName &&
|
|
16635
|
-
riskList && riskList.forEach((riskName) =>
|
|
16795
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16796
|
+
riskName && bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_DATA);
|
|
16797
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_DATA));
|
|
16636
16798
|
}
|
|
16637
|
-
return
|
|
16799
|
+
return bt.performanceMarkdownService.getData(symbol, strategyName, backtest);
|
|
16638
16800
|
}
|
|
16639
16801
|
/**
|
|
16640
16802
|
* Generates markdown report with performance analysis.
|
|
@@ -16659,14 +16821,14 @@ class Performance {
|
|
|
16659
16821
|
* await fs.writeFile("performance-report.md", markdown);
|
|
16660
16822
|
* ```
|
|
16661
16823
|
*/
|
|
16662
|
-
static async getReport(symbol, strategyName, columns) {
|
|
16663
|
-
|
|
16824
|
+
static async getReport(symbol, strategyName, backtest, columns) {
|
|
16825
|
+
bt.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_REPORT);
|
|
16664
16826
|
{
|
|
16665
|
-
const { riskName, riskList } =
|
|
16666
|
-
riskName &&
|
|
16667
|
-
riskList && riskList.forEach((riskName) =>
|
|
16827
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16828
|
+
riskName && bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_REPORT);
|
|
16829
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_REPORT));
|
|
16668
16830
|
}
|
|
16669
|
-
return
|
|
16831
|
+
return bt.performanceMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
16670
16832
|
}
|
|
16671
16833
|
/**
|
|
16672
16834
|
* Saves performance report to disk.
|
|
@@ -16688,14 +16850,14 @@ class Performance {
|
|
|
16688
16850
|
* await Performance.dump("BTCUSDT", "my-strategy", "./reports/perf");
|
|
16689
16851
|
* ```
|
|
16690
16852
|
*/
|
|
16691
|
-
static async dump(symbol, strategyName, path = "./dump/performance", columns) {
|
|
16692
|
-
|
|
16853
|
+
static async dump(symbol, strategyName, backtest, path = "./dump/performance", columns) {
|
|
16854
|
+
bt.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_DUMP);
|
|
16693
16855
|
{
|
|
16694
|
-
const { riskName, riskList } =
|
|
16695
|
-
riskName &&
|
|
16696
|
-
riskList && riskList.forEach((riskName) =>
|
|
16856
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16857
|
+
riskName && bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_DUMP);
|
|
16858
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_DUMP));
|
|
16697
16859
|
}
|
|
16698
|
-
return
|
|
16860
|
+
return bt.performanceMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
16699
16861
|
}
|
|
16700
16862
|
}
|
|
16701
16863
|
|
|
@@ -16729,7 +16891,7 @@ const INSTANCE_TASK_FN = async (symbol, context, self) => {
|
|
|
16729
16891
|
}
|
|
16730
16892
|
}
|
|
16731
16893
|
if (!self._isDone) {
|
|
16732
|
-
const walkerSchema =
|
|
16894
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
16733
16895
|
await doneWalkerSubject.next({
|
|
16734
16896
|
exchangeName: walkerSchema.exchangeName,
|
|
16735
16897
|
strategyName: context.walkerName,
|
|
@@ -16783,7 +16945,7 @@ class WalkerInstance {
|
|
|
16783
16945
|
* @internal
|
|
16784
16946
|
*/
|
|
16785
16947
|
this.task = functoolsKit.singlerun(async (symbol, context) => {
|
|
16786
|
-
|
|
16948
|
+
bt.loggerService.info(WALKER_METHOD_NAME_TASK, {
|
|
16787
16949
|
symbol,
|
|
16788
16950
|
context,
|
|
16789
16951
|
});
|
|
@@ -16802,7 +16964,7 @@ class WalkerInstance {
|
|
|
16802
16964
|
* ```
|
|
16803
16965
|
*/
|
|
16804
16966
|
this.getStatus = async () => {
|
|
16805
|
-
|
|
16967
|
+
bt.loggerService.info(WALKER_METHOD_NAME_GET_STATUS);
|
|
16806
16968
|
return {
|
|
16807
16969
|
id: this.id,
|
|
16808
16970
|
symbol: this.symbol,
|
|
@@ -16818,34 +16980,39 @@ class WalkerInstance {
|
|
|
16818
16980
|
* @returns Async generator yielding progress updates after each strategy
|
|
16819
16981
|
*/
|
|
16820
16982
|
this.run = (symbol, context) => {
|
|
16821
|
-
|
|
16983
|
+
bt.loggerService.info(WALKER_METHOD_NAME_RUN, {
|
|
16822
16984
|
symbol,
|
|
16823
16985
|
context,
|
|
16824
16986
|
});
|
|
16825
|
-
|
|
16826
|
-
const walkerSchema =
|
|
16827
|
-
|
|
16828
|
-
|
|
16987
|
+
bt.walkerValidationService.validate(context.walkerName, WALKER_METHOD_NAME_RUN);
|
|
16988
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
16989
|
+
bt.exchangeValidationService.validate(walkerSchema.exchangeName, WALKER_METHOD_NAME_RUN);
|
|
16990
|
+
bt.frameValidationService.validate(walkerSchema.frameName, WALKER_METHOD_NAME_RUN);
|
|
16829
16991
|
for (const strategyName of walkerSchema.strategies) {
|
|
16830
|
-
|
|
16992
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_RUN);
|
|
16831
16993
|
}
|
|
16832
|
-
|
|
16994
|
+
bt.walkerMarkdownService.clear(context.walkerName);
|
|
16833
16995
|
// Clear backtest data for all strategies
|
|
16834
16996
|
for (const strategyName of walkerSchema.strategies) {
|
|
16835
16997
|
{
|
|
16836
|
-
|
|
16837
|
-
|
|
16998
|
+
bt.backtestMarkdownService.clear(true, { symbol, strategyName });
|
|
16999
|
+
bt.liveMarkdownService.clear(true, { symbol, strategyName });
|
|
17000
|
+
bt.scheduleMarkdownService.clear(true, { symbol, strategyName });
|
|
17001
|
+
bt.performanceMarkdownService.clear(true, { symbol, strategyName });
|
|
17002
|
+
bt.partialMarkdownService.clear(true, { symbol, strategyName });
|
|
17003
|
+
bt.riskMarkdownService.clear(true, { symbol, strategyName });
|
|
16838
17004
|
}
|
|
16839
17005
|
{
|
|
16840
|
-
|
|
17006
|
+
bt.strategyCoreService.clear(true, { symbol, strategyName });
|
|
16841
17007
|
}
|
|
16842
17008
|
{
|
|
16843
|
-
const { riskName, riskList } =
|
|
16844
|
-
riskName &&
|
|
16845
|
-
riskList &&
|
|
17009
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17010
|
+
riskName && bt.riskGlobalService.clear(true, riskName);
|
|
17011
|
+
riskList &&
|
|
17012
|
+
riskList.forEach((riskName) => bt.riskGlobalService.clear(true, riskName));
|
|
16846
17013
|
}
|
|
16847
17014
|
}
|
|
16848
|
-
return
|
|
17015
|
+
return bt.walkerCommandService.run(symbol, {
|
|
16849
17016
|
walkerName: context.walkerName,
|
|
16850
17017
|
exchangeName: walkerSchema.exchangeName,
|
|
16851
17018
|
frameName: walkerSchema.frameName,
|
|
@@ -16870,16 +17037,29 @@ class WalkerInstance {
|
|
|
16870
17037
|
* ```
|
|
16871
17038
|
*/
|
|
16872
17039
|
this.background = (symbol, context) => {
|
|
16873
|
-
|
|
17040
|
+
bt.loggerService.info(WALKER_METHOD_NAME_BACKGROUND, {
|
|
16874
17041
|
symbol,
|
|
16875
17042
|
context,
|
|
16876
17043
|
});
|
|
16877
|
-
const walkerSchema =
|
|
17044
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
17045
|
+
{
|
|
17046
|
+
const currentStatus = this.task.getStatus();
|
|
17047
|
+
if (currentStatus === "pending") {
|
|
17048
|
+
throw new Error(`Walker.background is already running for symbol=${symbol} walkerName=${context.walkerName}`);
|
|
17049
|
+
}
|
|
17050
|
+
if (currentStatus === "rejected") {
|
|
17051
|
+
throw new Error(`Walker.background has failed for symbol=${symbol} walkerName=${context.walkerName}`);
|
|
17052
|
+
}
|
|
17053
|
+
}
|
|
16878
17054
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
|
|
16879
17055
|
return () => {
|
|
16880
17056
|
for (const strategyName of walkerSchema.strategies) {
|
|
16881
|
-
|
|
16882
|
-
walkerStopSubject.next({
|
|
17057
|
+
bt.strategyCoreService.stop(true, { symbol, strategyName });
|
|
17058
|
+
walkerStopSubject.next({
|
|
17059
|
+
symbol,
|
|
17060
|
+
strategyName,
|
|
17061
|
+
walkerName: context.walkerName,
|
|
17062
|
+
});
|
|
16883
17063
|
}
|
|
16884
17064
|
if (!this._isDone) {
|
|
16885
17065
|
doneWalkerSubject.next({
|
|
@@ -16917,14 +17097,14 @@ class WalkerInstance {
|
|
|
16917
17097
|
* ```
|
|
16918
17098
|
*/
|
|
16919
17099
|
this.stop = async (symbol, walkerName) => {
|
|
16920
|
-
|
|
17100
|
+
bt.loggerService.info(WALKER_METHOD_NAME_STOP, {
|
|
16921
17101
|
symbol,
|
|
16922
17102
|
walkerName,
|
|
16923
17103
|
});
|
|
16924
|
-
const walkerSchema =
|
|
17104
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
16925
17105
|
for (const strategyName of walkerSchema.strategies) {
|
|
16926
17106
|
await walkerStopSubject.next({ symbol, strategyName, walkerName });
|
|
16927
|
-
await
|
|
17107
|
+
await bt.strategyCoreService.stop(true, { symbol, strategyName });
|
|
16928
17108
|
}
|
|
16929
17109
|
};
|
|
16930
17110
|
/**
|
|
@@ -16942,12 +17122,12 @@ class WalkerInstance {
|
|
|
16942
17122
|
* ```
|
|
16943
17123
|
*/
|
|
16944
17124
|
this.getData = async (symbol, walkerName) => {
|
|
16945
|
-
|
|
17125
|
+
bt.loggerService.info(WALKER_METHOD_NAME_GET_DATA, {
|
|
16946
17126
|
symbol,
|
|
16947
17127
|
walkerName,
|
|
16948
17128
|
});
|
|
16949
|
-
const walkerSchema =
|
|
16950
|
-
return await
|
|
17129
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17130
|
+
return await bt.walkerMarkdownService.getData(walkerName, symbol, walkerSchema.metric || "sharpeRatio", {
|
|
16951
17131
|
exchangeName: walkerSchema.exchangeName,
|
|
16952
17132
|
frameName: walkerSchema.frameName,
|
|
16953
17133
|
});
|
|
@@ -16969,12 +17149,12 @@ class WalkerInstance {
|
|
|
16969
17149
|
* ```
|
|
16970
17150
|
*/
|
|
16971
17151
|
this.getReport = async (symbol, walkerName, strategyColumns, pnlColumns) => {
|
|
16972
|
-
|
|
17152
|
+
bt.loggerService.info(WALKER_METHOD_NAME_GET_REPORT, {
|
|
16973
17153
|
symbol,
|
|
16974
17154
|
walkerName,
|
|
16975
17155
|
});
|
|
16976
|
-
const walkerSchema =
|
|
16977
|
-
return await
|
|
17156
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17157
|
+
return await bt.walkerMarkdownService.getReport(walkerName, symbol, walkerSchema.metric || "sharpeRatio", {
|
|
16978
17158
|
exchangeName: walkerSchema.exchangeName,
|
|
16979
17159
|
frameName: walkerSchema.frameName,
|
|
16980
17160
|
}, strategyColumns, pnlColumns);
|
|
@@ -16999,13 +17179,13 @@ class WalkerInstance {
|
|
|
16999
17179
|
* ```
|
|
17000
17180
|
*/
|
|
17001
17181
|
this.dump = async (symbol, walkerName, path, strategyColumns, pnlColumns) => {
|
|
17002
|
-
|
|
17182
|
+
bt.loggerService.info(WALKER_METHOD_NAME_DUMP, {
|
|
17003
17183
|
symbol,
|
|
17004
17184
|
walkerName,
|
|
17005
17185
|
path,
|
|
17006
17186
|
});
|
|
17007
|
-
const walkerSchema =
|
|
17008
|
-
await
|
|
17187
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17188
|
+
await bt.walkerMarkdownService.dump(walkerName, symbol, walkerSchema.metric || "sharpeRatio", {
|
|
17009
17189
|
exchangeName: walkerSchema.exchangeName,
|
|
17010
17190
|
frameName: walkerSchema.frameName,
|
|
17011
17191
|
}, path, strategyColumns, pnlColumns);
|
|
@@ -17046,15 +17226,17 @@ class WalkerUtils {
|
|
|
17046
17226
|
* @returns Async generator yielding progress updates after each strategy
|
|
17047
17227
|
*/
|
|
17048
17228
|
this.run = (symbol, context) => {
|
|
17049
|
-
|
|
17050
|
-
const walkerSchema =
|
|
17051
|
-
|
|
17052
|
-
|
|
17229
|
+
bt.walkerValidationService.validate(context.walkerName, WALKER_METHOD_NAME_RUN);
|
|
17230
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
17231
|
+
bt.exchangeValidationService.validate(walkerSchema.exchangeName, WALKER_METHOD_NAME_RUN);
|
|
17232
|
+
bt.frameValidationService.validate(walkerSchema.frameName, WALKER_METHOD_NAME_RUN);
|
|
17053
17233
|
for (const strategyName of walkerSchema.strategies) {
|
|
17054
|
-
|
|
17055
|
-
const { riskName, riskList } =
|
|
17056
|
-
riskName &&
|
|
17057
|
-
|
|
17234
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_RUN);
|
|
17235
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17236
|
+
riskName &&
|
|
17237
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_RUN);
|
|
17238
|
+
riskList &&
|
|
17239
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_RUN));
|
|
17058
17240
|
}
|
|
17059
17241
|
const instance = this._getInstance(symbol, context.walkerName);
|
|
17060
17242
|
return instance.run(symbol, context);
|
|
@@ -17079,15 +17261,17 @@ class WalkerUtils {
|
|
|
17079
17261
|
* ```
|
|
17080
17262
|
*/
|
|
17081
17263
|
this.background = (symbol, context) => {
|
|
17082
|
-
|
|
17083
|
-
const walkerSchema =
|
|
17084
|
-
|
|
17085
|
-
|
|
17264
|
+
bt.walkerValidationService.validate(context.walkerName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17265
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
17266
|
+
bt.exchangeValidationService.validate(walkerSchema.exchangeName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17267
|
+
bt.frameValidationService.validate(walkerSchema.frameName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17086
17268
|
for (const strategyName of walkerSchema.strategies) {
|
|
17087
|
-
|
|
17088
|
-
const { riskName, riskList } =
|
|
17089
|
-
riskName &&
|
|
17090
|
-
|
|
17269
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17270
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17271
|
+
riskName &&
|
|
17272
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17273
|
+
riskList &&
|
|
17274
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_BACKGROUND));
|
|
17091
17275
|
}
|
|
17092
17276
|
const instance = this._getInstance(symbol, context.walkerName);
|
|
17093
17277
|
return instance.background(symbol, context);
|
|
@@ -17116,13 +17300,15 @@ class WalkerUtils {
|
|
|
17116
17300
|
* ```
|
|
17117
17301
|
*/
|
|
17118
17302
|
this.stop = async (symbol, walkerName) => {
|
|
17119
|
-
|
|
17120
|
-
const walkerSchema =
|
|
17303
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_STOP);
|
|
17304
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17121
17305
|
for (const strategyName of walkerSchema.strategies) {
|
|
17122
|
-
|
|
17123
|
-
const { riskName, riskList } =
|
|
17124
|
-
riskName &&
|
|
17125
|
-
|
|
17306
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_STOP);
|
|
17307
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17308
|
+
riskName &&
|
|
17309
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_STOP);
|
|
17310
|
+
riskList &&
|
|
17311
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_STOP));
|
|
17126
17312
|
}
|
|
17127
17313
|
const instance = this._getInstance(symbol, walkerName);
|
|
17128
17314
|
return await instance.stop(symbol, walkerName);
|
|
@@ -17141,13 +17327,15 @@ class WalkerUtils {
|
|
|
17141
17327
|
* ```
|
|
17142
17328
|
*/
|
|
17143
17329
|
this.getData = async (symbol, walkerName) => {
|
|
17144
|
-
|
|
17145
|
-
const walkerSchema =
|
|
17330
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_GET_DATA);
|
|
17331
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17146
17332
|
for (const strategyName of walkerSchema.strategies) {
|
|
17147
|
-
|
|
17148
|
-
const { riskName, riskList } =
|
|
17149
|
-
riskName &&
|
|
17150
|
-
|
|
17333
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_GET_DATA);
|
|
17334
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17335
|
+
riskName &&
|
|
17336
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_DATA);
|
|
17337
|
+
riskList &&
|
|
17338
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_DATA));
|
|
17151
17339
|
}
|
|
17152
17340
|
const instance = this._getInstance(symbol, walkerName);
|
|
17153
17341
|
return await instance.getData(symbol, walkerName);
|
|
@@ -17168,13 +17356,15 @@ class WalkerUtils {
|
|
|
17168
17356
|
* ```
|
|
17169
17357
|
*/
|
|
17170
17358
|
this.getReport = async (symbol, walkerName, strategyColumns, pnlColumns) => {
|
|
17171
|
-
|
|
17172
|
-
const walkerSchema =
|
|
17359
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_GET_REPORT);
|
|
17360
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17173
17361
|
for (const strategyName of walkerSchema.strategies) {
|
|
17174
|
-
|
|
17175
|
-
const { riskName, riskList } =
|
|
17176
|
-
riskName &&
|
|
17177
|
-
|
|
17362
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_GET_REPORT);
|
|
17363
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17364
|
+
riskName &&
|
|
17365
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_REPORT);
|
|
17366
|
+
riskList &&
|
|
17367
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_REPORT));
|
|
17178
17368
|
}
|
|
17179
17369
|
const instance = this._getInstance(symbol, walkerName);
|
|
17180
17370
|
return await instance.getReport(symbol, walkerName, strategyColumns, pnlColumns);
|
|
@@ -17198,13 +17388,15 @@ class WalkerUtils {
|
|
|
17198
17388
|
* ```
|
|
17199
17389
|
*/
|
|
17200
17390
|
this.dump = async (symbol, walkerName, path, strategyColumns, pnlColumns) => {
|
|
17201
|
-
|
|
17202
|
-
const walkerSchema =
|
|
17391
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_DUMP);
|
|
17392
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17203
17393
|
for (const strategyName of walkerSchema.strategies) {
|
|
17204
|
-
|
|
17205
|
-
const { riskName, riskList } =
|
|
17206
|
-
riskName &&
|
|
17207
|
-
|
|
17394
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_DUMP);
|
|
17395
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17396
|
+
riskName &&
|
|
17397
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_DUMP);
|
|
17398
|
+
riskList &&
|
|
17399
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_DUMP));
|
|
17208
17400
|
}
|
|
17209
17401
|
const instance = this._getInstance(symbol, walkerName);
|
|
17210
17402
|
return await instance.dump(symbol, walkerName, path, strategyColumns, pnlColumns);
|
|
@@ -17296,15 +17488,15 @@ class HeatUtils {
|
|
|
17296
17488
|
* });
|
|
17297
17489
|
* ```
|
|
17298
17490
|
*/
|
|
17299
|
-
this.getData = async (strategyName) => {
|
|
17300
|
-
|
|
17301
|
-
|
|
17491
|
+
this.getData = async (strategyName, backtest) => {
|
|
17492
|
+
bt.loggerService.info(HEAT_METHOD_NAME_GET_DATA, { strategyName });
|
|
17493
|
+
bt.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_DATA);
|
|
17302
17494
|
{
|
|
17303
|
-
const { riskName, riskList } =
|
|
17304
|
-
riskName &&
|
|
17305
|
-
riskList && riskList.forEach((riskName) =>
|
|
17495
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17496
|
+
riskName && bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_DATA);
|
|
17497
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_DATA));
|
|
17306
17498
|
}
|
|
17307
|
-
return await
|
|
17499
|
+
return await bt.heatMarkdownService.getData(strategyName, backtest);
|
|
17308
17500
|
};
|
|
17309
17501
|
/**
|
|
17310
17502
|
* Generates markdown report with portfolio heatmap table for a strategy.
|
|
@@ -17332,15 +17524,15 @@ class HeatUtils {
|
|
|
17332
17524
|
* // ...
|
|
17333
17525
|
* ```
|
|
17334
17526
|
*/
|
|
17335
|
-
this.getReport = async (strategyName, columns) => {
|
|
17336
|
-
|
|
17337
|
-
|
|
17527
|
+
this.getReport = async (strategyName, backtest, columns) => {
|
|
17528
|
+
bt.loggerService.info(HEAT_METHOD_NAME_GET_REPORT, { strategyName });
|
|
17529
|
+
bt.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_REPORT);
|
|
17338
17530
|
{
|
|
17339
|
-
const { riskName, riskList } =
|
|
17340
|
-
riskName &&
|
|
17341
|
-
riskList && riskList.forEach((riskName) =>
|
|
17531
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17532
|
+
riskName && bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_REPORT);
|
|
17533
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_REPORT));
|
|
17342
17534
|
}
|
|
17343
|
-
return await
|
|
17535
|
+
return await bt.heatMarkdownService.getReport(strategyName, backtest, columns);
|
|
17344
17536
|
};
|
|
17345
17537
|
/**
|
|
17346
17538
|
* Saves heatmap report to disk for a strategy.
|
|
@@ -17361,15 +17553,15 @@ class HeatUtils {
|
|
|
17361
17553
|
* await Heat.dump("my-strategy", "./reports");
|
|
17362
17554
|
* ```
|
|
17363
17555
|
*/
|
|
17364
|
-
this.dump = async (strategyName, path, columns) => {
|
|
17365
|
-
|
|
17366
|
-
|
|
17556
|
+
this.dump = async (strategyName, backtest, path, columns) => {
|
|
17557
|
+
bt.loggerService.info(HEAT_METHOD_NAME_DUMP, { strategyName, path });
|
|
17558
|
+
bt.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_DUMP);
|
|
17367
17559
|
{
|
|
17368
|
-
const { riskName, riskList } =
|
|
17369
|
-
riskName &&
|
|
17370
|
-
riskList && riskList.forEach((riskName) =>
|
|
17560
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17561
|
+
riskName && bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_DUMP);
|
|
17562
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_DUMP));
|
|
17371
17563
|
}
|
|
17372
|
-
await
|
|
17564
|
+
await bt.heatMarkdownService.dump(strategyName, backtest, path, columns);
|
|
17373
17565
|
};
|
|
17374
17566
|
}
|
|
17375
17567
|
}
|
|
@@ -17456,12 +17648,12 @@ class PositionSizeUtils {
|
|
|
17456
17648
|
* @throws Error if sizing schema method is not "fixed-percentage"
|
|
17457
17649
|
*/
|
|
17458
17650
|
PositionSizeUtils.fixedPercentage = async (symbol, accountBalance, priceOpen, priceStopLoss, context) => {
|
|
17459
|
-
|
|
17651
|
+
bt.loggerService.info(POSITION_SIZE_METHOD_NAME_FIXED, {
|
|
17460
17652
|
context,
|
|
17461
17653
|
symbol,
|
|
17462
17654
|
});
|
|
17463
|
-
|
|
17464
|
-
return await
|
|
17655
|
+
bt.sizingValidationService.validate(context.sizingName, POSITION_SIZE_METHOD_NAME_FIXED, "fixed-percentage");
|
|
17656
|
+
return await bt.sizingGlobalService.calculate({
|
|
17465
17657
|
symbol,
|
|
17466
17658
|
accountBalance,
|
|
17467
17659
|
priceOpen,
|
|
@@ -17482,12 +17674,12 @@ PositionSizeUtils.fixedPercentage = async (symbol, accountBalance, priceOpen, pr
|
|
|
17482
17674
|
* @throws Error if sizing schema method is not "kelly-criterion"
|
|
17483
17675
|
*/
|
|
17484
17676
|
PositionSizeUtils.kellyCriterion = async (symbol, accountBalance, priceOpen, winRate, winLossRatio, context) => {
|
|
17485
|
-
|
|
17677
|
+
bt.loggerService.info(POSITION_SIZE_METHOD_NAME_KELLY, {
|
|
17486
17678
|
context,
|
|
17487
17679
|
symbol,
|
|
17488
17680
|
});
|
|
17489
|
-
|
|
17490
|
-
return await
|
|
17681
|
+
bt.sizingValidationService.validate(context.sizingName, POSITION_SIZE_METHOD_NAME_KELLY, "kelly-criterion");
|
|
17682
|
+
return await bt.sizingGlobalService.calculate({
|
|
17491
17683
|
symbol,
|
|
17492
17684
|
accountBalance,
|
|
17493
17685
|
priceOpen,
|
|
@@ -17508,12 +17700,12 @@ PositionSizeUtils.kellyCriterion = async (symbol, accountBalance, priceOpen, win
|
|
|
17508
17700
|
* @throws Error if sizing schema method is not "atr-based"
|
|
17509
17701
|
*/
|
|
17510
17702
|
PositionSizeUtils.atrBased = async (symbol, accountBalance, priceOpen, atr, context) => {
|
|
17511
|
-
|
|
17703
|
+
bt.loggerService.info(POSITION_SIZE_METHOD_NAME_ATR, {
|
|
17512
17704
|
context,
|
|
17513
17705
|
symbol,
|
|
17514
17706
|
});
|
|
17515
|
-
|
|
17516
|
-
return await
|
|
17707
|
+
bt.sizingValidationService.validate(context.sizingName, POSITION_SIZE_METHOD_NAME_ATR, "atr-based");
|
|
17708
|
+
return await bt.sizingGlobalService.calculate({
|
|
17517
17709
|
symbol,
|
|
17518
17710
|
accountBalance,
|
|
17519
17711
|
priceOpen,
|
|
@@ -17562,12 +17754,12 @@ class OptimizerUtils {
|
|
|
17562
17754
|
* @throws Error if optimizer not found
|
|
17563
17755
|
*/
|
|
17564
17756
|
this.getData = async (symbol, context) => {
|
|
17565
|
-
|
|
17757
|
+
bt.loggerService.info(OPTIMIZER_METHOD_NAME_GET_DATA, {
|
|
17566
17758
|
symbol,
|
|
17567
17759
|
context,
|
|
17568
17760
|
});
|
|
17569
|
-
|
|
17570
|
-
return await
|
|
17761
|
+
bt.optimizerValidationService.validate(context.optimizerName, OPTIMIZER_METHOD_NAME_GET_DATA);
|
|
17762
|
+
return await bt.optimizerGlobalService.getData(symbol, context.optimizerName);
|
|
17571
17763
|
};
|
|
17572
17764
|
/**
|
|
17573
17765
|
* Generates complete executable strategy code.
|
|
@@ -17579,12 +17771,12 @@ class OptimizerUtils {
|
|
|
17579
17771
|
* @throws Error if optimizer not found
|
|
17580
17772
|
*/
|
|
17581
17773
|
this.getCode = async (symbol, context) => {
|
|
17582
|
-
|
|
17774
|
+
bt.loggerService.info(OPTIMIZER_METHOD_NAME_GET_CODE, {
|
|
17583
17775
|
symbol,
|
|
17584
17776
|
context,
|
|
17585
17777
|
});
|
|
17586
|
-
|
|
17587
|
-
return await
|
|
17778
|
+
bt.optimizerValidationService.validate(context.optimizerName, OPTIMIZER_METHOD_NAME_GET_CODE);
|
|
17779
|
+
return await bt.optimizerGlobalService.getCode(symbol, context.optimizerName);
|
|
17588
17780
|
};
|
|
17589
17781
|
/**
|
|
17590
17782
|
* Generates and saves strategy code to file.
|
|
@@ -17598,13 +17790,13 @@ class OptimizerUtils {
|
|
|
17598
17790
|
* @throws Error if optimizer not found or file write fails
|
|
17599
17791
|
*/
|
|
17600
17792
|
this.dump = async (symbol, context, path) => {
|
|
17601
|
-
|
|
17793
|
+
bt.loggerService.info(OPTIMIZER_METHOD_NAME_DUMP, {
|
|
17602
17794
|
symbol,
|
|
17603
17795
|
context,
|
|
17604
17796
|
path,
|
|
17605
17797
|
});
|
|
17606
|
-
|
|
17607
|
-
await
|
|
17798
|
+
bt.optimizerValidationService.validate(context.optimizerName, OPTIMIZER_METHOD_NAME_DUMP);
|
|
17799
|
+
await bt.optimizerGlobalService.dump(symbol, context.optimizerName, path);
|
|
17608
17800
|
};
|
|
17609
17801
|
}
|
|
17610
17802
|
}
|
|
@@ -17685,15 +17877,15 @@ class PartialUtils {
|
|
|
17685
17877
|
* }
|
|
17686
17878
|
* ```
|
|
17687
17879
|
*/
|
|
17688
|
-
this.getData = async (symbol, strategyName) => {
|
|
17689
|
-
|
|
17690
|
-
|
|
17880
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
17881
|
+
bt.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol, strategyName });
|
|
17882
|
+
bt.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_DATA);
|
|
17691
17883
|
{
|
|
17692
|
-
const { riskName, riskList } =
|
|
17693
|
-
riskName &&
|
|
17694
|
-
riskList && riskList.forEach((riskName) =>
|
|
17884
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17885
|
+
riskName && bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_DATA);
|
|
17886
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_DATA));
|
|
17695
17887
|
}
|
|
17696
|
-
return await
|
|
17888
|
+
return await bt.partialMarkdownService.getData(symbol, strategyName, backtest);
|
|
17697
17889
|
};
|
|
17698
17890
|
/**
|
|
17699
17891
|
* Generates markdown report with all partial profit/loss events for a symbol-strategy pair.
|
|
@@ -17734,15 +17926,15 @@ class PartialUtils {
|
|
|
17734
17926
|
* // **Loss events:** 1
|
|
17735
17927
|
* ```
|
|
17736
17928
|
*/
|
|
17737
|
-
this.getReport = async (symbol, strategyName, columns) => {
|
|
17738
|
-
|
|
17739
|
-
|
|
17929
|
+
this.getReport = async (symbol, strategyName, backtest, columns) => {
|
|
17930
|
+
bt.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol, strategyName });
|
|
17931
|
+
bt.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_REPORT);
|
|
17740
17932
|
{
|
|
17741
|
-
const { riskName, riskList } =
|
|
17742
|
-
riskName &&
|
|
17743
|
-
riskList && riskList.forEach((riskName) =>
|
|
17933
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17934
|
+
riskName && bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_REPORT);
|
|
17935
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_REPORT));
|
|
17744
17936
|
}
|
|
17745
|
-
return await
|
|
17937
|
+
return await bt.partialMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
17746
17938
|
};
|
|
17747
17939
|
/**
|
|
17748
17940
|
* Generates and saves markdown report to file.
|
|
@@ -17776,15 +17968,15 @@ class PartialUtils {
|
|
|
17776
17968
|
* }
|
|
17777
17969
|
* ```
|
|
17778
17970
|
*/
|
|
17779
|
-
this.dump = async (symbol, strategyName, path, columns) => {
|
|
17780
|
-
|
|
17781
|
-
|
|
17971
|
+
this.dump = async (symbol, strategyName, backtest, path, columns) => {
|
|
17972
|
+
bt.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, strategyName, path });
|
|
17973
|
+
bt.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_DUMP);
|
|
17782
17974
|
{
|
|
17783
|
-
const { riskName, riskList } =
|
|
17784
|
-
riskName &&
|
|
17785
|
-
riskList && riskList.forEach((riskName) =>
|
|
17975
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17976
|
+
riskName && bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_DUMP);
|
|
17977
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_DUMP));
|
|
17786
17978
|
}
|
|
17787
|
-
await
|
|
17979
|
+
await bt.partialMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
17788
17980
|
};
|
|
17789
17981
|
}
|
|
17790
17982
|
}
|