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.mjs
CHANGED
|
@@ -2041,7 +2041,7 @@ const BASE_WAIT_FOR_INIT_FN_METHOD_NAME = "PersistBase.waitForInitFn";
|
|
|
2041
2041
|
const BASE_UNLINK_RETRY_COUNT = 5;
|
|
2042
2042
|
const BASE_UNLINK_RETRY_DELAY = 1000;
|
|
2043
2043
|
const BASE_WAIT_FOR_INIT_FN = async (self) => {
|
|
2044
|
-
|
|
2044
|
+
bt.loggerService.debug(BASE_WAIT_FOR_INIT_FN_METHOD_NAME, {
|
|
2045
2045
|
entityName: self.entityName,
|
|
2046
2046
|
directory: self._directory,
|
|
2047
2047
|
});
|
|
@@ -2099,7 +2099,7 @@ const PersistBase = makeExtendable(class {
|
|
|
2099
2099
|
this.entityName = entityName;
|
|
2100
2100
|
this.baseDir = baseDir;
|
|
2101
2101
|
this[_a] = singleshot(async () => await BASE_WAIT_FOR_INIT_FN(this));
|
|
2102
|
-
|
|
2102
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_CTOR, {
|
|
2103
2103
|
entityName: this.entityName,
|
|
2104
2104
|
baseDir,
|
|
2105
2105
|
});
|
|
@@ -2115,7 +2115,7 @@ const PersistBase = makeExtendable(class {
|
|
|
2115
2115
|
return join(this.baseDir, this.entityName, `${entityId}.json`);
|
|
2116
2116
|
}
|
|
2117
2117
|
async waitForInit(initial) {
|
|
2118
|
-
|
|
2118
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_WAIT_FOR_INIT, {
|
|
2119
2119
|
entityName: this.entityName,
|
|
2120
2120
|
initial,
|
|
2121
2121
|
});
|
|
@@ -2132,7 +2132,7 @@ const PersistBase = makeExtendable(class {
|
|
|
2132
2132
|
return length;
|
|
2133
2133
|
}
|
|
2134
2134
|
async readValue(entityId) {
|
|
2135
|
-
|
|
2135
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_READ_VALUE, {
|
|
2136
2136
|
entityName: this.entityName,
|
|
2137
2137
|
entityId,
|
|
2138
2138
|
});
|
|
@@ -2149,7 +2149,7 @@ const PersistBase = makeExtendable(class {
|
|
|
2149
2149
|
}
|
|
2150
2150
|
}
|
|
2151
2151
|
async hasValue(entityId) {
|
|
2152
|
-
|
|
2152
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_HAS_VALUE, {
|
|
2153
2153
|
entityName: this.entityName,
|
|
2154
2154
|
entityId,
|
|
2155
2155
|
});
|
|
@@ -2166,7 +2166,7 @@ const PersistBase = makeExtendable(class {
|
|
|
2166
2166
|
}
|
|
2167
2167
|
}
|
|
2168
2168
|
async writeValue(entityId, entity) {
|
|
2169
|
-
|
|
2169
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_WRITE_VALUE, {
|
|
2170
2170
|
entityName: this.entityName,
|
|
2171
2171
|
entityId,
|
|
2172
2172
|
});
|
|
@@ -2187,7 +2187,7 @@ const PersistBase = makeExtendable(class {
|
|
|
2187
2187
|
* @throws Error if entity not found or deletion fails
|
|
2188
2188
|
*/
|
|
2189
2189
|
async removeValue(entityId) {
|
|
2190
|
-
|
|
2190
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_REMOVE_VALUE, {
|
|
2191
2191
|
entityName: this.entityName,
|
|
2192
2192
|
entityId,
|
|
2193
2193
|
});
|
|
@@ -2209,7 +2209,7 @@ const PersistBase = makeExtendable(class {
|
|
|
2209
2209
|
* @throws Error if deletion fails
|
|
2210
2210
|
*/
|
|
2211
2211
|
async removeAll() {
|
|
2212
|
-
|
|
2212
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_REMOVE_ALL, {
|
|
2213
2213
|
entityName: this.entityName,
|
|
2214
2214
|
});
|
|
2215
2215
|
try {
|
|
@@ -2231,7 +2231,7 @@ const PersistBase = makeExtendable(class {
|
|
|
2231
2231
|
* @throws Error if reading fails
|
|
2232
2232
|
*/
|
|
2233
2233
|
async *values() {
|
|
2234
|
-
|
|
2234
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_VALUES, {
|
|
2235
2235
|
entityName: this.entityName,
|
|
2236
2236
|
});
|
|
2237
2237
|
try {
|
|
@@ -2260,7 +2260,7 @@ const PersistBase = makeExtendable(class {
|
|
|
2260
2260
|
* @throws Error if reading fails
|
|
2261
2261
|
*/
|
|
2262
2262
|
async *keys() {
|
|
2263
|
-
|
|
2263
|
+
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_KEYS, {
|
|
2264
2264
|
entityName: this.entityName,
|
|
2265
2265
|
});
|
|
2266
2266
|
try {
|
|
@@ -2365,7 +2365,7 @@ class PersistSignalUtils {
|
|
|
2365
2365
|
* @returns Promise resolving to signal or null
|
|
2366
2366
|
*/
|
|
2367
2367
|
this.readSignalData = async (symbol, strategyName) => {
|
|
2368
|
-
|
|
2368
|
+
bt.loggerService.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_READ_DATA);
|
|
2369
2369
|
const key = `${symbol}:${strategyName}`;
|
|
2370
2370
|
const isInitial = !this.getSignalStorage.has(key);
|
|
2371
2371
|
const stateStorage = this.getSignalStorage(symbol, strategyName);
|
|
@@ -2387,7 +2387,7 @@ class PersistSignalUtils {
|
|
|
2387
2387
|
* @returns Promise that resolves when write is complete
|
|
2388
2388
|
*/
|
|
2389
2389
|
this.writeSignalData = async (signalRow, symbol, strategyName) => {
|
|
2390
|
-
|
|
2390
|
+
bt.loggerService.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2391
2391
|
const key = `${symbol}:${strategyName}`;
|
|
2392
2392
|
const isInitial = !this.getSignalStorage.has(key);
|
|
2393
2393
|
const stateStorage = this.getSignalStorage(symbol, strategyName);
|
|
@@ -2410,7 +2410,7 @@ class PersistSignalUtils {
|
|
|
2410
2410
|
* ```
|
|
2411
2411
|
*/
|
|
2412
2412
|
usePersistSignalAdapter(Ctor) {
|
|
2413
|
-
|
|
2413
|
+
bt.loggerService.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_PERSIST_SIGNAL_ADAPTER);
|
|
2414
2414
|
this.PersistSignalFactory = Ctor;
|
|
2415
2415
|
}
|
|
2416
2416
|
}
|
|
@@ -2462,7 +2462,7 @@ class PersistRiskUtils {
|
|
|
2462
2462
|
* @returns Promise resolving to Map of active positions
|
|
2463
2463
|
*/
|
|
2464
2464
|
this.readPositionData = async (riskName) => {
|
|
2465
|
-
|
|
2465
|
+
bt.loggerService.info(PERSIST_RISK_UTILS_METHOD_NAME_READ_DATA);
|
|
2466
2466
|
const isInitial = !this.getRiskStorage.has(riskName);
|
|
2467
2467
|
const stateStorage = this.getRiskStorage(riskName);
|
|
2468
2468
|
await stateStorage.waitForInit(isInitial);
|
|
@@ -2483,7 +2483,7 @@ class PersistRiskUtils {
|
|
|
2483
2483
|
* @returns Promise that resolves when write is complete
|
|
2484
2484
|
*/
|
|
2485
2485
|
this.writePositionData = async (riskRow, riskName) => {
|
|
2486
|
-
|
|
2486
|
+
bt.loggerService.info(PERSIST_RISK_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2487
2487
|
const isInitial = !this.getRiskStorage.has(riskName);
|
|
2488
2488
|
const stateStorage = this.getRiskStorage(riskName);
|
|
2489
2489
|
await stateStorage.waitForInit(isInitial);
|
|
@@ -2506,7 +2506,7 @@ class PersistRiskUtils {
|
|
|
2506
2506
|
* ```
|
|
2507
2507
|
*/
|
|
2508
2508
|
usePersistRiskAdapter(Ctor) {
|
|
2509
|
-
|
|
2509
|
+
bt.loggerService.info(PERSIST_RISK_UTILS_METHOD_NAME_USE_PERSIST_RISK_ADAPTER);
|
|
2510
2510
|
this.PersistRiskFactory = Ctor;
|
|
2511
2511
|
}
|
|
2512
2512
|
}
|
|
@@ -2556,7 +2556,7 @@ class PersistScheduleUtils {
|
|
|
2556
2556
|
* @returns Promise resolving to scheduled signal or null
|
|
2557
2557
|
*/
|
|
2558
2558
|
this.readScheduleData = async (symbol, strategyName) => {
|
|
2559
|
-
|
|
2559
|
+
bt.loggerService.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_READ_DATA);
|
|
2560
2560
|
const key = `${symbol}:${strategyName}`;
|
|
2561
2561
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
2562
2562
|
const stateStorage = this.getScheduleStorage(symbol, strategyName);
|
|
@@ -2578,7 +2578,7 @@ class PersistScheduleUtils {
|
|
|
2578
2578
|
* @returns Promise that resolves when write is complete
|
|
2579
2579
|
*/
|
|
2580
2580
|
this.writeScheduleData = async (scheduledSignalRow, symbol, strategyName) => {
|
|
2581
|
-
|
|
2581
|
+
bt.loggerService.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2582
2582
|
const key = `${symbol}:${strategyName}`;
|
|
2583
2583
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
2584
2584
|
const stateStorage = this.getScheduleStorage(symbol, strategyName);
|
|
@@ -2601,7 +2601,7 @@ class PersistScheduleUtils {
|
|
|
2601
2601
|
* ```
|
|
2602
2602
|
*/
|
|
2603
2603
|
usePersistScheduleAdapter(Ctor) {
|
|
2604
|
-
|
|
2604
|
+
bt.loggerService.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_PERSIST_SCHEDULE_ADAPTER);
|
|
2605
2605
|
this.PersistScheduleFactory = Ctor;
|
|
2606
2606
|
}
|
|
2607
2607
|
}
|
|
@@ -2626,7 +2626,7 @@ const PersistScheduleAdapter = new PersistScheduleUtils();
|
|
|
2626
2626
|
* Utility class for managing partial profit/loss levels persistence.
|
|
2627
2627
|
*
|
|
2628
2628
|
* Features:
|
|
2629
|
-
* - Memoized storage instances per symbol
|
|
2629
|
+
* - Memoized storage instances per symbol:strategyName
|
|
2630
2630
|
* - Custom adapter support
|
|
2631
2631
|
* - Atomic read/write operations for partial data
|
|
2632
2632
|
* - Crash-safe partial state management
|
|
@@ -2636,23 +2636,25 @@ const PersistScheduleAdapter = new PersistScheduleUtils();
|
|
|
2636
2636
|
class PersistPartialUtils {
|
|
2637
2637
|
constructor() {
|
|
2638
2638
|
this.PersistPartialFactory = PersistBase;
|
|
2639
|
-
this.getPartialStorage = memoize(([symbol]) => `${symbol}`, (symbol) => Reflect.construct(this.PersistPartialFactory, [
|
|
2640
|
-
symbol
|
|
2639
|
+
this.getPartialStorage = memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, (symbol, strategyName) => Reflect.construct(this.PersistPartialFactory, [
|
|
2640
|
+
`${symbol}_${strategyName}`,
|
|
2641
2641
|
`./dump/data/partial/`,
|
|
2642
2642
|
]));
|
|
2643
2643
|
/**
|
|
2644
|
-
* Reads persisted partial data for a symbol.
|
|
2644
|
+
* Reads persisted partial data for a symbol and strategy.
|
|
2645
2645
|
*
|
|
2646
2646
|
* Called by ClientPartial.waitForInit() to restore state.
|
|
2647
2647
|
* Returns empty object if no partial data exists.
|
|
2648
2648
|
*
|
|
2649
2649
|
* @param symbol - Trading pair symbol
|
|
2650
|
+
* @param strategyName - Strategy identifier
|
|
2650
2651
|
* @returns Promise resolving to partial data record
|
|
2651
2652
|
*/
|
|
2652
|
-
this.readPartialData = async (symbol) => {
|
|
2653
|
-
|
|
2654
|
-
const
|
|
2655
|
-
const
|
|
2653
|
+
this.readPartialData = async (symbol, strategyName) => {
|
|
2654
|
+
bt.loggerService.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_READ_DATA);
|
|
2655
|
+
const key = `${symbol}:${strategyName}`;
|
|
2656
|
+
const isInitial = !this.getPartialStorage.has(key);
|
|
2657
|
+
const stateStorage = this.getPartialStorage(symbol, strategyName);
|
|
2656
2658
|
await stateStorage.waitForInit(isInitial);
|
|
2657
2659
|
const PARTIAL_STORAGE_KEY = "levels";
|
|
2658
2660
|
if (await stateStorage.hasValue(PARTIAL_STORAGE_KEY)) {
|
|
@@ -2668,12 +2670,14 @@ class PersistPartialUtils {
|
|
|
2668
2670
|
*
|
|
2669
2671
|
* @param partialData - Record of signal IDs to partial data
|
|
2670
2672
|
* @param symbol - Trading pair symbol
|
|
2673
|
+
* @param strategyName - Strategy identifier
|
|
2671
2674
|
* @returns Promise that resolves when write is complete
|
|
2672
2675
|
*/
|
|
2673
|
-
this.writePartialData = async (partialData, symbol) => {
|
|
2674
|
-
|
|
2675
|
-
const
|
|
2676
|
-
const
|
|
2676
|
+
this.writePartialData = async (partialData, symbol, strategyName) => {
|
|
2677
|
+
bt.loggerService.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2678
|
+
const key = `${symbol}:${strategyName}`;
|
|
2679
|
+
const isInitial = !this.getPartialStorage.has(key);
|
|
2680
|
+
const stateStorage = this.getPartialStorage(symbol, strategyName);
|
|
2677
2681
|
await stateStorage.waitForInit(isInitial);
|
|
2678
2682
|
const PARTIAL_STORAGE_KEY = "levels";
|
|
2679
2683
|
await stateStorage.writeValue(PARTIAL_STORAGE_KEY, partialData);
|
|
@@ -2694,7 +2698,7 @@ class PersistPartialUtils {
|
|
|
2694
2698
|
* ```
|
|
2695
2699
|
*/
|
|
2696
2700
|
usePersistPartialAdapter(Ctor) {
|
|
2697
|
-
|
|
2701
|
+
bt.loggerService.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_PERSIST_PARTIAL_ADAPTER);
|
|
2698
2702
|
this.PersistPartialFactory = Ctor;
|
|
2699
2703
|
}
|
|
2700
2704
|
}
|
|
@@ -2708,10 +2712,10 @@ class PersistPartialUtils {
|
|
|
2708
2712
|
* PersistPartialAdapter.usePersistPartialAdapter(RedisPersist);
|
|
2709
2713
|
*
|
|
2710
2714
|
* // Read partial data
|
|
2711
|
-
* const partialData = await PersistPartialAdapter.readPartialData("BTCUSDT");
|
|
2715
|
+
* const partialData = await PersistPartialAdapter.readPartialData("BTCUSDT", "my-strategy");
|
|
2712
2716
|
*
|
|
2713
2717
|
* // Write partial data
|
|
2714
|
-
* await PersistPartialAdapter.writePartialData(partialData, "BTCUSDT");
|
|
2718
|
+
* await PersistPartialAdapter.writePartialData(partialData, "BTCUSDT", "my-strategy");
|
|
2715
2719
|
* ```
|
|
2716
2720
|
*/
|
|
2717
2721
|
const PersistPartialAdapter = new PersistPartialUtils();
|
|
@@ -3163,7 +3167,7 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
|
|
|
3163
3167
|
error: errorData(error),
|
|
3164
3168
|
message: getErrorMessage(error),
|
|
3165
3169
|
};
|
|
3166
|
-
|
|
3170
|
+
bt.loggerService.warn(message, payload);
|
|
3167
3171
|
console.warn(message, payload);
|
|
3168
3172
|
errorEmitter.next(error);
|
|
3169
3173
|
},
|
|
@@ -3242,6 +3246,7 @@ const CHECK_SCHEDULED_SIGNAL_TIMEOUT_FN = async (self, scheduled, currentPrice)
|
|
|
3242
3246
|
strategyName: self.params.method.context.strategyName,
|
|
3243
3247
|
exchangeName: self.params.method.context.exchangeName,
|
|
3244
3248
|
symbol: self.params.execution.context.symbol,
|
|
3249
|
+
backtest: self.params.execution.context.backtest,
|
|
3245
3250
|
};
|
|
3246
3251
|
if (self.params.callbacks?.onTick) {
|
|
3247
3252
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3293,6 +3298,7 @@ const CANCEL_SCHEDULED_SIGNAL_BY_STOPLOSS_FN = async (self, scheduled, currentPr
|
|
|
3293
3298
|
exchangeName: self.params.method.context.exchangeName,
|
|
3294
3299
|
symbol: self.params.execution.context.symbol,
|
|
3295
3300
|
currentPrice: currentPrice,
|
|
3301
|
+
backtest: self.params.execution.context.backtest,
|
|
3296
3302
|
};
|
|
3297
3303
|
if (self.params.callbacks?.onTick) {
|
|
3298
3304
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3360,6 +3366,7 @@ const ACTIVATE_SCHEDULED_SIGNAL_FN = async (self, scheduled, activationTimestamp
|
|
|
3360
3366
|
exchangeName: self.params.method.context.exchangeName,
|
|
3361
3367
|
symbol: self.params.execution.context.symbol,
|
|
3362
3368
|
currentPrice: self._pendingSignal.priceOpen,
|
|
3369
|
+
backtest: self.params.execution.context.backtest,
|
|
3363
3370
|
};
|
|
3364
3371
|
if (self.params.callbacks?.onTick) {
|
|
3365
3372
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3376,6 +3383,7 @@ const RETURN_SCHEDULED_SIGNAL_ACTIVE_FN = async (self, scheduled, currentPrice)
|
|
|
3376
3383
|
symbol: self.params.execution.context.symbol,
|
|
3377
3384
|
percentTp: 0,
|
|
3378
3385
|
percentSl: 0,
|
|
3386
|
+
backtest: self.params.execution.context.backtest,
|
|
3379
3387
|
};
|
|
3380
3388
|
if (self.params.callbacks?.onTick) {
|
|
3381
3389
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3401,6 +3409,7 @@ const OPEN_NEW_SCHEDULED_SIGNAL_FN = async (self, signal) => {
|
|
|
3401
3409
|
exchangeName: self.params.method.context.exchangeName,
|
|
3402
3410
|
symbol: self.params.execution.context.symbol,
|
|
3403
3411
|
currentPrice: currentPrice,
|
|
3412
|
+
backtest: self.params.execution.context.backtest,
|
|
3404
3413
|
};
|
|
3405
3414
|
if (self.params.callbacks?.onTick) {
|
|
3406
3415
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3432,6 +3441,7 @@ const OPEN_NEW_PENDING_SIGNAL_FN = async (self, signal) => {
|
|
|
3432
3441
|
exchangeName: self.params.method.context.exchangeName,
|
|
3433
3442
|
symbol: self.params.execution.context.symbol,
|
|
3434
3443
|
currentPrice: signal.priceOpen,
|
|
3444
|
+
backtest: self.params.execution.context.backtest,
|
|
3435
3445
|
};
|
|
3436
3446
|
if (self.params.callbacks?.onTick) {
|
|
3437
3447
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3496,6 +3506,7 @@ const CLOSE_PENDING_SIGNAL_FN = async (self, signal, currentPrice, closeReason)
|
|
|
3496
3506
|
strategyName: self.params.method.context.strategyName,
|
|
3497
3507
|
exchangeName: self.params.method.context.exchangeName,
|
|
3498
3508
|
symbol: self.params.execution.context.symbol,
|
|
3509
|
+
backtest: self.params.execution.context.backtest,
|
|
3499
3510
|
};
|
|
3500
3511
|
if (self.params.callbacks?.onTick) {
|
|
3501
3512
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3565,6 +3576,7 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice) => {
|
|
|
3565
3576
|
symbol: self.params.execution.context.symbol,
|
|
3566
3577
|
percentTp,
|
|
3567
3578
|
percentSl,
|
|
3579
|
+
backtest: self.params.execution.context.backtest,
|
|
3568
3580
|
};
|
|
3569
3581
|
if (self.params.callbacks?.onTick) {
|
|
3570
3582
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3582,6 +3594,7 @@ const RETURN_IDLE_FN = async (self, currentPrice) => {
|
|
|
3582
3594
|
exchangeName: self.params.method.context.exchangeName,
|
|
3583
3595
|
symbol: self.params.execution.context.symbol,
|
|
3584
3596
|
currentPrice: currentPrice,
|
|
3597
|
+
backtest: self.params.execution.context.backtest,
|
|
3585
3598
|
};
|
|
3586
3599
|
if (self.params.callbacks?.onTick) {
|
|
3587
3600
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3608,6 +3621,7 @@ const CANCEL_SCHEDULED_SIGNAL_IN_BACKTEST_FN = async (self, scheduled, averagePr
|
|
|
3608
3621
|
strategyName: self.params.method.context.strategyName,
|
|
3609
3622
|
exchangeName: self.params.method.context.exchangeName,
|
|
3610
3623
|
symbol: self.params.execution.context.symbol,
|
|
3624
|
+
backtest: self.params.execution.context.backtest,
|
|
3611
3625
|
};
|
|
3612
3626
|
if (self.params.callbacks?.onTick) {
|
|
3613
3627
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -3703,6 +3717,7 @@ const CLOSE_PENDING_SIGNAL_IN_BACKTEST_FN = async (self, signal, averagePrice, c
|
|
|
3703
3717
|
strategyName: self.params.method.context.strategyName,
|
|
3704
3718
|
exchangeName: self.params.method.context.exchangeName,
|
|
3705
3719
|
symbol: self.params.execution.context.symbol,
|
|
3720
|
+
backtest: self.params.execution.context.backtest,
|
|
3706
3721
|
};
|
|
3707
3722
|
if (self.params.callbacks?.onTick) {
|
|
3708
3723
|
self.params.callbacks.onTick(self.params.execution.context.symbol, result, self.params.execution.context.backtest);
|
|
@@ -4201,6 +4216,7 @@ class ClientStrategy {
|
|
|
4201
4216
|
strategyName: this.params.method.context.strategyName,
|
|
4202
4217
|
exchangeName: this.params.method.context.exchangeName,
|
|
4203
4218
|
symbol: this.params.execution.context.symbol,
|
|
4219
|
+
backtest: this.params.execution.context.backtest,
|
|
4204
4220
|
};
|
|
4205
4221
|
return result; // Cast to IStrategyBacktestResult (which includes Active)
|
|
4206
4222
|
}
|
|
@@ -4331,7 +4347,7 @@ class MergeRisk {
|
|
|
4331
4347
|
* @returns Promise resolving to true if all risks approve, false if any risk rejects
|
|
4332
4348
|
*/
|
|
4333
4349
|
async checkSignal(params) {
|
|
4334
|
-
|
|
4350
|
+
bt.loggerService.info("MergeRisk checkSignal", {
|
|
4335
4351
|
params,
|
|
4336
4352
|
});
|
|
4337
4353
|
const riskCheck = await Promise.all(this._riskList.map(async (risk) => await risk.checkSignal(params)));
|
|
@@ -4348,7 +4364,7 @@ class MergeRisk {
|
|
|
4348
4364
|
* @returns Promise that resolves when all risks have registered the signal
|
|
4349
4365
|
*/
|
|
4350
4366
|
async addSignal(symbol, context) {
|
|
4351
|
-
|
|
4367
|
+
bt.loggerService.info("MergeRisk addSignal", {
|
|
4352
4368
|
symbol,
|
|
4353
4369
|
context,
|
|
4354
4370
|
});
|
|
@@ -4365,7 +4381,7 @@ class MergeRisk {
|
|
|
4365
4381
|
* @returns Promise that resolves when all risks have removed the signal
|
|
4366
4382
|
*/
|
|
4367
4383
|
async removeSignal(symbol, context) {
|
|
4368
|
-
|
|
4384
|
+
bt.loggerService.info("MergeRisk removeSignal", {
|
|
4369
4385
|
symbol,
|
|
4370
4386
|
context,
|
|
4371
4387
|
});
|
|
@@ -4433,19 +4449,19 @@ class RiskUtils {
|
|
|
4433
4449
|
* }
|
|
4434
4450
|
* ```
|
|
4435
4451
|
*/
|
|
4436
|
-
this.getData = async (symbol, strategyName) => {
|
|
4437
|
-
|
|
4452
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
4453
|
+
bt.loggerService.info(RISK_METHOD_NAME_GET_DATA, {
|
|
4438
4454
|
symbol,
|
|
4439
4455
|
strategyName,
|
|
4440
4456
|
});
|
|
4441
|
-
|
|
4457
|
+
bt.strategyValidationService.validate(strategyName, RISK_METHOD_NAME_GET_DATA);
|
|
4442
4458
|
{
|
|
4443
|
-
const { riskName, riskList } =
|
|
4459
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
4444
4460
|
riskName &&
|
|
4445
|
-
|
|
4446
|
-
riskList && riskList.forEach((riskName) =>
|
|
4461
|
+
bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_DATA);
|
|
4462
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_DATA));
|
|
4447
4463
|
}
|
|
4448
|
-
return await
|
|
4464
|
+
return await bt.riskMarkdownService.getData(symbol, strategyName, backtest);
|
|
4449
4465
|
};
|
|
4450
4466
|
/**
|
|
4451
4467
|
* Generates markdown report with all risk rejection events for a symbol-strategy pair.
|
|
@@ -4488,19 +4504,19 @@ class RiskUtils {
|
|
|
4488
4504
|
* // - my-strategy: 1
|
|
4489
4505
|
* ```
|
|
4490
4506
|
*/
|
|
4491
|
-
this.getReport = async (symbol, strategyName, columns) => {
|
|
4492
|
-
|
|
4507
|
+
this.getReport = async (symbol, strategyName, backtest, columns) => {
|
|
4508
|
+
bt.loggerService.info(RISK_METHOD_NAME_GET_REPORT, {
|
|
4493
4509
|
symbol,
|
|
4494
4510
|
strategyName,
|
|
4495
4511
|
});
|
|
4496
|
-
|
|
4512
|
+
bt.strategyValidationService.validate(strategyName, RISK_METHOD_NAME_GET_REPORT);
|
|
4497
4513
|
{
|
|
4498
|
-
const { riskName, riskList } =
|
|
4514
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
4499
4515
|
riskName &&
|
|
4500
|
-
|
|
4501
|
-
riskList && riskList.forEach((riskName) =>
|
|
4516
|
+
bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_REPORT);
|
|
4517
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_GET_REPORT));
|
|
4502
4518
|
}
|
|
4503
|
-
return await
|
|
4519
|
+
return await bt.riskMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
4504
4520
|
};
|
|
4505
4521
|
/**
|
|
4506
4522
|
* Generates and saves markdown report to file.
|
|
@@ -4534,20 +4550,20 @@ class RiskUtils {
|
|
|
4534
4550
|
* }
|
|
4535
4551
|
* ```
|
|
4536
4552
|
*/
|
|
4537
|
-
this.dump = async (symbol, strategyName, path, columns) => {
|
|
4538
|
-
|
|
4553
|
+
this.dump = async (symbol, strategyName, backtest, path, columns) => {
|
|
4554
|
+
bt.loggerService.info(RISK_METHOD_NAME_DUMP, {
|
|
4539
4555
|
symbol,
|
|
4540
4556
|
strategyName,
|
|
4541
4557
|
path,
|
|
4542
4558
|
});
|
|
4543
|
-
|
|
4559
|
+
bt.strategyValidationService.validate(strategyName, RISK_METHOD_NAME_DUMP);
|
|
4544
4560
|
{
|
|
4545
|
-
const { riskName, riskList } =
|
|
4561
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
4546
4562
|
riskName &&
|
|
4547
|
-
|
|
4548
|
-
riskList && riskList.forEach((riskName) =>
|
|
4563
|
+
bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_DUMP);
|
|
4564
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, RISK_METHOD_NAME_DUMP));
|
|
4549
4565
|
}
|
|
4550
|
-
await
|
|
4566
|
+
await bt.riskMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
4551
4567
|
};
|
|
4552
4568
|
}
|
|
4553
4569
|
}
|
|
@@ -4572,25 +4588,25 @@ const NOOP_RISK = {
|
|
|
4572
4588
|
addSignal: () => Promise.resolve(),
|
|
4573
4589
|
removeSignal: () => Promise.resolve(),
|
|
4574
4590
|
};
|
|
4575
|
-
const GET_RISK_FN = (dto, self) => {
|
|
4591
|
+
const GET_RISK_FN = (dto, backtest, self) => {
|
|
4576
4592
|
const hasRiskName = !!dto.riskName;
|
|
4577
|
-
const hasRiskList = !!
|
|
4593
|
+
const hasRiskList = !!dto.riskList?.length;
|
|
4578
4594
|
// Нет ни riskName, ни riskList
|
|
4579
4595
|
if (!hasRiskName && !hasRiskList) {
|
|
4580
4596
|
return NOOP_RISK;
|
|
4581
4597
|
}
|
|
4582
4598
|
// Есть только riskName (без riskList)
|
|
4583
4599
|
if (hasRiskName && !hasRiskList) {
|
|
4584
|
-
return self.riskConnectionService.getRisk(dto.riskName);
|
|
4600
|
+
return self.riskConnectionService.getRisk(dto.riskName, backtest);
|
|
4585
4601
|
}
|
|
4586
4602
|
// Есть только riskList (без riskName)
|
|
4587
4603
|
if (!hasRiskName && hasRiskList) {
|
|
4588
|
-
return new MergeRisk(dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName)));
|
|
4604
|
+
return new MergeRisk(dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName, backtest)));
|
|
4589
4605
|
}
|
|
4590
4606
|
// Есть и riskName, и riskList - объединяем (riskName в начало)
|
|
4591
4607
|
return new MergeRisk([
|
|
4592
|
-
self.riskConnectionService.getRisk(dto.riskName),
|
|
4593
|
-
...dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName))
|
|
4608
|
+
self.riskConnectionService.getRisk(dto.riskName, backtest),
|
|
4609
|
+
...dto.riskList.map((riskName) => self.riskConnectionService.getRisk(riskName, backtest)),
|
|
4594
4610
|
]);
|
|
4595
4611
|
};
|
|
4596
4612
|
/**
|
|
@@ -4632,7 +4648,7 @@ class StrategyConnectionService {
|
|
|
4632
4648
|
* @param strategyName - Name of registered strategy schema
|
|
4633
4649
|
* @returns Configured ClientStrategy instance
|
|
4634
4650
|
*/
|
|
4635
|
-
this.getStrategy = memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, (symbol, strategyName) => {
|
|
4651
|
+
this.getStrategy = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, (symbol, strategyName, backtest) => {
|
|
4636
4652
|
const { riskName = "", riskList = [], getSignal, interval, callbacks, } = this.strategySchemaService.get(strategyName);
|
|
4637
4653
|
return new ClientStrategy({
|
|
4638
4654
|
symbol,
|
|
@@ -4645,7 +4661,7 @@ class StrategyConnectionService {
|
|
|
4645
4661
|
risk: GET_RISK_FN({
|
|
4646
4662
|
riskName,
|
|
4647
4663
|
riskList,
|
|
4648
|
-
}, this),
|
|
4664
|
+
}, backtest, this),
|
|
4649
4665
|
riskName,
|
|
4650
4666
|
strategyName,
|
|
4651
4667
|
getSignal,
|
|
@@ -4662,12 +4678,13 @@ class StrategyConnectionService {
|
|
|
4662
4678
|
*
|
|
4663
4679
|
* @returns Promise resolving to pending signal or null
|
|
4664
4680
|
*/
|
|
4665
|
-
this.getPendingSignal = async (symbol, strategyName) => {
|
|
4681
|
+
this.getPendingSignal = async (backtest, symbol, strategyName) => {
|
|
4666
4682
|
this.loggerService.log("strategyConnectionService getPendingSignal", {
|
|
4667
4683
|
symbol,
|
|
4668
4684
|
strategyName,
|
|
4685
|
+
backtest,
|
|
4669
4686
|
});
|
|
4670
|
-
const strategy = this.getStrategy(symbol, strategyName);
|
|
4687
|
+
const strategy = this.getStrategy(symbol, strategyName, backtest);
|
|
4671
4688
|
return await strategy.getPendingSignal(symbol, strategyName);
|
|
4672
4689
|
};
|
|
4673
4690
|
/**
|
|
@@ -4680,12 +4697,13 @@ class StrategyConnectionService {
|
|
|
4680
4697
|
* @param strategyName - Name of the strategy
|
|
4681
4698
|
* @returns Promise resolving to true if strategy is stopped, false otherwise
|
|
4682
4699
|
*/
|
|
4683
|
-
this.getStopped = async (symbol, strategyName) => {
|
|
4700
|
+
this.getStopped = async (backtest, symbol, strategyName) => {
|
|
4684
4701
|
this.loggerService.log("strategyConnectionService getStopped", {
|
|
4685
4702
|
symbol,
|
|
4686
4703
|
strategyName,
|
|
4704
|
+
backtest,
|
|
4687
4705
|
});
|
|
4688
|
-
const strategy = this.getStrategy(symbol, strategyName);
|
|
4706
|
+
const strategy = this.getStrategy(symbol, strategyName, backtest);
|
|
4689
4707
|
return await strategy.getStopped(symbol, strategyName);
|
|
4690
4708
|
};
|
|
4691
4709
|
/**
|
|
@@ -4703,7 +4721,8 @@ class StrategyConnectionService {
|
|
|
4703
4721
|
symbol,
|
|
4704
4722
|
strategyName,
|
|
4705
4723
|
});
|
|
4706
|
-
const
|
|
4724
|
+
const backtest = this.executionContextService.context.backtest;
|
|
4725
|
+
const strategy = this.getStrategy(symbol, strategyName, backtest);
|
|
4707
4726
|
await strategy.waitForInit();
|
|
4708
4727
|
const tick = await strategy.tick(symbol, strategyName);
|
|
4709
4728
|
{
|
|
@@ -4734,7 +4753,8 @@ class StrategyConnectionService {
|
|
|
4734
4753
|
strategyName,
|
|
4735
4754
|
candleCount: candles.length,
|
|
4736
4755
|
});
|
|
4737
|
-
const
|
|
4756
|
+
const backtest = this.executionContextService.context.backtest;
|
|
4757
|
+
const strategy = this.getStrategy(symbol, strategyName, backtest);
|
|
4738
4758
|
await strategy.waitForInit();
|
|
4739
4759
|
const tick = await strategy.backtest(symbol, strategyName, candles);
|
|
4740
4760
|
{
|
|
@@ -4755,11 +4775,11 @@ class StrategyConnectionService {
|
|
|
4755
4775
|
* @param strategyName - Name of strategy to stop
|
|
4756
4776
|
* @returns Promise that resolves when stop flag is set
|
|
4757
4777
|
*/
|
|
4758
|
-
this.stop = async (
|
|
4778
|
+
this.stop = async (backtest, ctx) => {
|
|
4759
4779
|
this.loggerService.log("strategyConnectionService stop", {
|
|
4760
4780
|
ctx,
|
|
4761
4781
|
});
|
|
4762
|
-
const strategy = this.getStrategy(ctx.symbol, ctx.strategyName);
|
|
4782
|
+
const strategy = this.getStrategy(ctx.symbol, ctx.strategyName, backtest);
|
|
4763
4783
|
await strategy.stop(ctx.symbol, ctx.strategyName, backtest);
|
|
4764
4784
|
};
|
|
4765
4785
|
/**
|
|
@@ -4770,12 +4790,12 @@ class StrategyConnectionService {
|
|
|
4770
4790
|
*
|
|
4771
4791
|
* @param ctx - Optional context with symbol and strategyName (clears all if not provided)
|
|
4772
4792
|
*/
|
|
4773
|
-
this.clear = async (ctx) => {
|
|
4793
|
+
this.clear = async (backtest, ctx) => {
|
|
4774
4794
|
this.loggerService.log("strategyConnectionService clear", {
|
|
4775
4795
|
ctx,
|
|
4776
4796
|
});
|
|
4777
4797
|
if (ctx) {
|
|
4778
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
4798
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
4779
4799
|
this.getStrategy.clear(key);
|
|
4780
4800
|
}
|
|
4781
4801
|
else {
|
|
@@ -5161,7 +5181,7 @@ const DO_VALIDATION_FN = trycatch(async (validation, params) => {
|
|
|
5161
5181
|
error: errorData(error),
|
|
5162
5182
|
message: getErrorMessage(error),
|
|
5163
5183
|
};
|
|
5164
|
-
|
|
5184
|
+
bt.loggerService.warn(message, payload);
|
|
5165
5185
|
console.warn(message, payload);
|
|
5166
5186
|
validationSubject.next(error);
|
|
5167
5187
|
},
|
|
@@ -5170,9 +5190,15 @@ const DO_VALIDATION_FN = trycatch(async (validation, params) => {
|
|
|
5170
5190
|
* Initializes active positions by reading from persistence.
|
|
5171
5191
|
* Uses singleshot pattern to ensure it only runs once.
|
|
5172
5192
|
* This function is exported for use in tests or other modules.
|
|
5193
|
+
*
|
|
5194
|
+
* In backtest mode, initializes with empty Map. In live mode, reads from persist storage.
|
|
5173
5195
|
*/
|
|
5174
5196
|
const WAIT_FOR_INIT_FN$1 = async (self) => {
|
|
5175
|
-
self.params.logger.debug("ClientRisk waitForInit");
|
|
5197
|
+
self.params.logger.debug("ClientRisk waitForInit", { backtest: self.params.backtest });
|
|
5198
|
+
if (self.params.backtest) {
|
|
5199
|
+
self._activePositions = new Map();
|
|
5200
|
+
return;
|
|
5201
|
+
}
|
|
5176
5202
|
const persistedPositions = await PersistRiskAdapter.readPositionData(self.params.riskName);
|
|
5177
5203
|
self._activePositions = new Map(persistedPositions);
|
|
5178
5204
|
};
|
|
@@ -5220,6 +5246,7 @@ class ClientRisk {
|
|
|
5220
5246
|
this.params.logger.debug("ClientRisk checkSignal", {
|
|
5221
5247
|
symbol: params.symbol,
|
|
5222
5248
|
strategyName: params.strategyName,
|
|
5249
|
+
backtest: this.params.backtest,
|
|
5223
5250
|
});
|
|
5224
5251
|
if (this._activePositions === POSITION_NEED_FETCH) {
|
|
5225
5252
|
await this.waitForInit();
|
|
@@ -5249,7 +5276,7 @@ class ClientRisk {
|
|
|
5249
5276
|
}
|
|
5250
5277
|
if (!isValid) {
|
|
5251
5278
|
// Call params.onRejected for riskSubject emission
|
|
5252
|
-
await this.params.onRejected(params.symbol, params, riskMap.size, rejectionNote, Date.now());
|
|
5279
|
+
await this.params.onRejected(params.symbol, params, riskMap.size, rejectionNote, Date.now(), this.params.backtest);
|
|
5253
5280
|
// Call schema callbacks.onRejected if defined
|
|
5254
5281
|
if (this.params.callbacks?.onRejected) {
|
|
5255
5282
|
this.params.callbacks.onRejected(params.symbol, params);
|
|
@@ -5265,8 +5292,12 @@ class ClientRisk {
|
|
|
5265
5292
|
}
|
|
5266
5293
|
/**
|
|
5267
5294
|
* Persists current active positions to disk.
|
|
5295
|
+
* Skips in backtest mode.
|
|
5268
5296
|
*/
|
|
5269
5297
|
async _updatePositions() {
|
|
5298
|
+
if (this.params.backtest) {
|
|
5299
|
+
return;
|
|
5300
|
+
}
|
|
5270
5301
|
if (this._activePositions === POSITION_NEED_FETCH) {
|
|
5271
5302
|
await this.waitForInit();
|
|
5272
5303
|
}
|
|
@@ -5280,6 +5311,7 @@ class ClientRisk {
|
|
|
5280
5311
|
this.params.logger.debug("ClientRisk addSignal", {
|
|
5281
5312
|
symbol,
|
|
5282
5313
|
context,
|
|
5314
|
+
backtest: this.params.backtest,
|
|
5283
5315
|
});
|
|
5284
5316
|
if (this._activePositions === POSITION_NEED_FETCH) {
|
|
5285
5317
|
await this.waitForInit();
|
|
@@ -5302,6 +5334,7 @@ class ClientRisk {
|
|
|
5302
5334
|
this.params.logger.debug("ClientRisk removeSignal", {
|
|
5303
5335
|
symbol,
|
|
5304
5336
|
context,
|
|
5337
|
+
backtest: this.params.backtest,
|
|
5305
5338
|
});
|
|
5306
5339
|
if (this._activePositions === POSITION_NEED_FETCH) {
|
|
5307
5340
|
await this.waitForInit();
|
|
@@ -5324,8 +5357,9 @@ class ClientRisk {
|
|
|
5324
5357
|
* @param activePositionCount - Number of active positions at rejection time
|
|
5325
5358
|
* @param comment - Rejection reason from validation note or "N/A"
|
|
5326
5359
|
* @param timestamp - Event timestamp in milliseconds
|
|
5360
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
5327
5361
|
*/
|
|
5328
|
-
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, comment, timestamp) => await riskSubject.next({
|
|
5362
|
+
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, comment, timestamp, backtest) => await riskSubject.next({
|
|
5329
5363
|
symbol,
|
|
5330
5364
|
pendingSignal: params.pendingSignal,
|
|
5331
5365
|
strategyName: params.strategyName,
|
|
@@ -5334,6 +5368,7 @@ const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, comment,
|
|
|
5334
5368
|
activePositionCount,
|
|
5335
5369
|
comment,
|
|
5336
5370
|
timestamp,
|
|
5371
|
+
backtest,
|
|
5337
5372
|
});
|
|
5338
5373
|
/**
|
|
5339
5374
|
* Connection service routing risk operations to correct ClientRisk instance.
|
|
@@ -5372,19 +5407,21 @@ class RiskConnectionService {
|
|
|
5372
5407
|
this.loggerService = inject(TYPES.loggerService);
|
|
5373
5408
|
this.riskSchemaService = inject(TYPES.riskSchemaService);
|
|
5374
5409
|
/**
|
|
5375
|
-
* Retrieves memoized ClientRisk instance for given risk name.
|
|
5410
|
+
* Retrieves memoized ClientRisk instance for given risk name and backtest mode.
|
|
5376
5411
|
*
|
|
5377
5412
|
* Creates ClientRisk on first call, returns cached instance on subsequent calls.
|
|
5378
|
-
* Cache key is riskName string.
|
|
5413
|
+
* Cache key is "riskName:backtest" string to separate live and backtest instances.
|
|
5379
5414
|
*
|
|
5380
5415
|
* @param riskName - Name of registered risk schema
|
|
5416
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
5381
5417
|
* @returns Configured ClientRisk instance
|
|
5382
5418
|
*/
|
|
5383
|
-
this.getRisk = memoize(([riskName]) => `${riskName}`, (riskName) => {
|
|
5419
|
+
this.getRisk = memoize(([riskName, backtest]) => `${riskName}:${backtest ? "backtest" : "live"}`, (riskName, backtest) => {
|
|
5384
5420
|
const schema = this.riskSchemaService.get(riskName);
|
|
5385
5421
|
return new ClientRisk({
|
|
5386
5422
|
...schema,
|
|
5387
5423
|
logger: this.loggerService,
|
|
5424
|
+
backtest,
|
|
5388
5425
|
onRejected: COMMIT_REJECTION_FN,
|
|
5389
5426
|
});
|
|
5390
5427
|
});
|
|
@@ -5396,7 +5433,7 @@ class RiskConnectionService {
|
|
|
5396
5433
|
* ClientRisk will emit riskSubject event via onRejected callback when signal is rejected.
|
|
5397
5434
|
*
|
|
5398
5435
|
* @param params - Risk check arguments (portfolio state, position details)
|
|
5399
|
-
* @param context - Execution context with risk name
|
|
5436
|
+
* @param context - Execution context with risk name and backtest mode
|
|
5400
5437
|
* @returns Promise resolving to risk check result
|
|
5401
5438
|
*/
|
|
5402
5439
|
this.checkSignal = async (params, context) => {
|
|
@@ -5404,46 +5441,48 @@ class RiskConnectionService {
|
|
|
5404
5441
|
symbol: params.symbol,
|
|
5405
5442
|
context,
|
|
5406
5443
|
});
|
|
5407
|
-
return await this.getRisk(context.riskName).checkSignal(params);
|
|
5444
|
+
return await this.getRisk(context.riskName, context.backtest).checkSignal(params);
|
|
5408
5445
|
};
|
|
5409
5446
|
/**
|
|
5410
5447
|
* Registers an opened signal with the risk management system.
|
|
5411
5448
|
* Routes to appropriate ClientRisk instance.
|
|
5412
5449
|
*
|
|
5413
5450
|
* @param symbol - Trading pair symbol
|
|
5414
|
-
* @param context - Context information (strategyName, riskName)
|
|
5451
|
+
* @param context - Context information (strategyName, riskName, backtest)
|
|
5415
5452
|
*/
|
|
5416
5453
|
this.addSignal = async (symbol, context) => {
|
|
5417
5454
|
this.loggerService.log("riskConnectionService addSignal", {
|
|
5418
5455
|
symbol,
|
|
5419
5456
|
context,
|
|
5420
5457
|
});
|
|
5421
|
-
await this.getRisk(context.riskName).addSignal(symbol, context);
|
|
5458
|
+
await this.getRisk(context.riskName, context.backtest).addSignal(symbol, context);
|
|
5422
5459
|
};
|
|
5423
5460
|
/**
|
|
5424
5461
|
* Removes a closed signal from the risk management system.
|
|
5425
5462
|
* Routes to appropriate ClientRisk instance.
|
|
5426
5463
|
*
|
|
5427
5464
|
* @param symbol - Trading pair symbol
|
|
5428
|
-
* @param context - Context information (strategyName, riskName)
|
|
5465
|
+
* @param context - Context information (strategyName, riskName, backtest)
|
|
5429
5466
|
*/
|
|
5430
5467
|
this.removeSignal = async (symbol, context) => {
|
|
5431
5468
|
this.loggerService.log("riskConnectionService removeSignal", {
|
|
5432
5469
|
symbol,
|
|
5433
5470
|
context,
|
|
5434
5471
|
});
|
|
5435
|
-
await this.getRisk(context.riskName).removeSignal(symbol, context);
|
|
5472
|
+
await this.getRisk(context.riskName, context.backtest).removeSignal(symbol, context);
|
|
5436
5473
|
};
|
|
5437
5474
|
/**
|
|
5438
5475
|
* Clears the cached ClientRisk instance for the given risk name.
|
|
5439
5476
|
*
|
|
5440
5477
|
* @param riskName - Name of the risk schema to clear from cache
|
|
5441
5478
|
*/
|
|
5442
|
-
this.clear = async (riskName) => {
|
|
5479
|
+
this.clear = async (backtest, riskName) => {
|
|
5443
5480
|
this.loggerService.log("riskConnectionService clear", {
|
|
5444
5481
|
riskName,
|
|
5482
|
+
backtest,
|
|
5445
5483
|
});
|
|
5446
|
-
|
|
5484
|
+
const key = `${riskName}:${backtest ? "backtest" : "live"}`;
|
|
5485
|
+
this.getRisk.clear(key);
|
|
5447
5486
|
};
|
|
5448
5487
|
}
|
|
5449
5488
|
}
|
|
@@ -5666,7 +5705,7 @@ class StrategyCoreService {
|
|
|
5666
5705
|
* @param strategyName - Name of the strategy
|
|
5667
5706
|
* @returns Promise resolving to pending signal or null
|
|
5668
5707
|
*/
|
|
5669
|
-
this.getPendingSignal = async (symbol, strategyName) => {
|
|
5708
|
+
this.getPendingSignal = async (backtest, symbol, strategyName) => {
|
|
5670
5709
|
this.loggerService.log("strategyCoreService getPendingSignal", {
|
|
5671
5710
|
symbol,
|
|
5672
5711
|
strategyName,
|
|
@@ -5675,7 +5714,7 @@ class StrategyCoreService {
|
|
|
5675
5714
|
throw new Error("strategyCoreService getPendingSignal requires a method context");
|
|
5676
5715
|
}
|
|
5677
5716
|
await this.validate(symbol, strategyName);
|
|
5678
|
-
return await this.strategyConnectionService.getPendingSignal(symbol, strategyName);
|
|
5717
|
+
return await this.strategyConnectionService.getPendingSignal(backtest, symbol, strategyName);
|
|
5679
5718
|
};
|
|
5680
5719
|
/**
|
|
5681
5720
|
* Checks if the strategy has been stopped.
|
|
@@ -5687,16 +5726,17 @@ class StrategyCoreService {
|
|
|
5687
5726
|
* @param strategyName - Name of the strategy
|
|
5688
5727
|
* @returns Promise resolving to true if strategy is stopped, false otherwise
|
|
5689
5728
|
*/
|
|
5690
|
-
this.getStopped = async (symbol, strategyName) => {
|
|
5729
|
+
this.getStopped = async (backtest, symbol, strategyName) => {
|
|
5691
5730
|
this.loggerService.log("strategyCoreService getStopped", {
|
|
5692
5731
|
symbol,
|
|
5693
5732
|
strategyName,
|
|
5733
|
+
backtest,
|
|
5694
5734
|
});
|
|
5695
5735
|
if (!MethodContextService.hasContext()) {
|
|
5696
5736
|
throw new Error("strategyCoreService getStopped requires a method context");
|
|
5697
5737
|
}
|
|
5698
5738
|
await this.validate(symbol, strategyName);
|
|
5699
|
-
return await this.strategyConnectionService.getStopped(symbol, strategyName);
|
|
5739
|
+
return await this.strategyConnectionService.getStopped(backtest, symbol, strategyName);
|
|
5700
5740
|
};
|
|
5701
5741
|
/**
|
|
5702
5742
|
* Checks signal status at a specific timestamp.
|
|
@@ -5770,13 +5810,13 @@ class StrategyCoreService {
|
|
|
5770
5810
|
* @param strategyName - Name of strategy to stop
|
|
5771
5811
|
* @returns Promise that resolves when stop flag is set
|
|
5772
5812
|
*/
|
|
5773
|
-
this.stop = async (
|
|
5813
|
+
this.stop = async (backtest, ctx) => {
|
|
5774
5814
|
this.loggerService.log("strategyCoreService stop", {
|
|
5775
5815
|
ctx,
|
|
5776
5816
|
backtest,
|
|
5777
5817
|
});
|
|
5778
5818
|
await this.validate(ctx.symbol, ctx.strategyName);
|
|
5779
|
-
return await this.strategyConnectionService.stop(
|
|
5819
|
+
return await this.strategyConnectionService.stop(backtest, ctx);
|
|
5780
5820
|
};
|
|
5781
5821
|
/**
|
|
5782
5822
|
* Clears the memoized ClientStrategy instance from cache.
|
|
@@ -5786,14 +5826,14 @@ class StrategyCoreService {
|
|
|
5786
5826
|
*
|
|
5787
5827
|
* @param ctx - Optional context with symbol and strategyName (clears all if not provided)
|
|
5788
5828
|
*/
|
|
5789
|
-
this.clear = async (ctx) => {
|
|
5829
|
+
this.clear = async (backtest, ctx) => {
|
|
5790
5830
|
this.loggerService.log("strategyCoreService clear", {
|
|
5791
5831
|
ctx,
|
|
5792
5832
|
});
|
|
5793
5833
|
if (ctx) {
|
|
5794
5834
|
await this.validate(ctx.symbol, ctx.strategyName);
|
|
5795
5835
|
}
|
|
5796
|
-
return await this.strategyConnectionService.clear(ctx);
|
|
5836
|
+
return await this.strategyConnectionService.clear(backtest, ctx);
|
|
5797
5837
|
};
|
|
5798
5838
|
}
|
|
5799
5839
|
}
|
|
@@ -5934,14 +5974,15 @@ class RiskGlobalService {
|
|
|
5934
5974
|
* If no riskName is provided, clears all risk data.
|
|
5935
5975
|
* @param riskName - Optional name of the risk instance to clear
|
|
5936
5976
|
*/
|
|
5937
|
-
this.clear = async (riskName) => {
|
|
5977
|
+
this.clear = async (backtest, riskName) => {
|
|
5938
5978
|
this.loggerService.log("riskGlobalService clear", {
|
|
5939
5979
|
riskName,
|
|
5980
|
+
backtest,
|
|
5940
5981
|
});
|
|
5941
5982
|
if (riskName) {
|
|
5942
5983
|
await this.validate(riskName);
|
|
5943
5984
|
}
|
|
5944
|
-
return await this.riskConnectionService.clear(riskName);
|
|
5985
|
+
return await this.riskConnectionService.clear(backtest, riskName);
|
|
5945
5986
|
};
|
|
5946
5987
|
}
|
|
5947
5988
|
}
|
|
@@ -6485,7 +6526,7 @@ class BacktestLogicPrivateService {
|
|
|
6485
6526
|
});
|
|
6486
6527
|
}
|
|
6487
6528
|
// Check if strategy should stop before processing next frame
|
|
6488
|
-
if (await this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName)) {
|
|
6529
|
+
if (await this.strategyCoreService.getStopped(true, symbol, this.methodContextService.context.strategyName)) {
|
|
6489
6530
|
this.loggerService.info("backtestLogicPrivateService stopped by user request (before tick)", {
|
|
6490
6531
|
symbol,
|
|
6491
6532
|
when: when.toISOString(),
|
|
@@ -6510,7 +6551,7 @@ class BacktestLogicPrivateService {
|
|
|
6510
6551
|
continue;
|
|
6511
6552
|
}
|
|
6512
6553
|
// Check if strategy should stop when idle (no active signal)
|
|
6513
|
-
if (await and(Promise.resolve(result.action === "idle"), this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName))) {
|
|
6554
|
+
if (await and(Promise.resolve(result.action === "idle"), this.strategyCoreService.getStopped(true, symbol, this.methodContextService.context.strategyName))) {
|
|
6514
6555
|
this.loggerService.info("backtestLogicPrivateService stopped by user request (idle state)", {
|
|
6515
6556
|
symbol,
|
|
6516
6557
|
when: when.toISOString(),
|
|
@@ -6612,7 +6653,7 @@ class BacktestLogicPrivateService {
|
|
|
6612
6653
|
}
|
|
6613
6654
|
yield backtestResult;
|
|
6614
6655
|
// Check if strategy should stop after signal is closed
|
|
6615
|
-
if (await this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName)) {
|
|
6656
|
+
if (await this.strategyCoreService.getStopped(true, symbol, this.methodContextService.context.strategyName)) {
|
|
6616
6657
|
this.loggerService.info("backtestLogicPrivateService stopped by user request (after scheduled signal closed)", {
|
|
6617
6658
|
symbol,
|
|
6618
6659
|
signalId: backtestResult.signal.id,
|
|
@@ -6705,7 +6746,7 @@ class BacktestLogicPrivateService {
|
|
|
6705
6746
|
}
|
|
6706
6747
|
yield backtestResult;
|
|
6707
6748
|
// Check if strategy should stop after signal is closed
|
|
6708
|
-
if (await this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName)) {
|
|
6749
|
+
if (await this.strategyCoreService.getStopped(true, symbol, this.methodContextService.context.strategyName)) {
|
|
6709
6750
|
this.loggerService.info("backtestLogicPrivateService stopped by user request (after signal closed)", {
|
|
6710
6751
|
symbol,
|
|
6711
6752
|
signalId: backtestResult.signal.id,
|
|
@@ -6848,7 +6889,7 @@ class LiveLogicPrivateService {
|
|
|
6848
6889
|
previousEventTimestamp = currentTimestamp;
|
|
6849
6890
|
// Check if strategy should stop when idle (no active signal)
|
|
6850
6891
|
if (result.action === "idle") {
|
|
6851
|
-
if (await and(Promise.resolve(true), this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName))) {
|
|
6892
|
+
if (await and(Promise.resolve(true), this.strategyCoreService.getStopped(false, symbol, this.methodContextService.context.strategyName))) {
|
|
6852
6893
|
this.loggerService.info("liveLogicPrivateService stopped by user request (idle state)", {
|
|
6853
6894
|
symbol,
|
|
6854
6895
|
when: when.toISOString(),
|
|
@@ -6870,7 +6911,7 @@ class LiveLogicPrivateService {
|
|
|
6870
6911
|
yield result;
|
|
6871
6912
|
// Check if strategy should stop after signal is closed
|
|
6872
6913
|
if (result.action === "closed") {
|
|
6873
|
-
if (await this.strategyCoreService.getStopped(symbol, this.methodContextService.context.strategyName)) {
|
|
6914
|
+
if (await this.strategyCoreService.getStopped(false, symbol, this.methodContextService.context.strategyName)) {
|
|
6874
6915
|
this.loggerService.info("liveLogicPrivateService stopped by user request (after signal closed)", {
|
|
6875
6916
|
symbol,
|
|
6876
6917
|
signalId: result.signal.id,
|
|
@@ -7002,7 +7043,7 @@ class WalkerLogicPrivateService {
|
|
|
7002
7043
|
symbol,
|
|
7003
7044
|
});
|
|
7004
7045
|
// Get statistics from BacktestMarkdownService
|
|
7005
|
-
const stats = await this.backtestMarkdownService.getData(symbol, strategyName);
|
|
7046
|
+
const stats = await this.backtestMarkdownService.getData(symbol, strategyName, true);
|
|
7006
7047
|
// Extract metric value
|
|
7007
7048
|
const value = stats[metric];
|
|
7008
7049
|
const metricValue = value !== null &&
|
|
@@ -7066,7 +7107,7 @@ class WalkerLogicPrivateService {
|
|
|
7066
7107
|
bestStrategy,
|
|
7067
7108
|
bestMetric,
|
|
7068
7109
|
bestStats: bestStrategy !== null
|
|
7069
|
-
? await this.backtestMarkdownService.getData(symbol, bestStrategy)
|
|
7110
|
+
? await this.backtestMarkdownService.getData(symbol, bestStrategy, true)
|
|
7070
7111
|
: null,
|
|
7071
7112
|
};
|
|
7072
7113
|
// Call onComplete callback if provided with final best results
|
|
@@ -7579,10 +7620,10 @@ class BacktestMarkdownService {
|
|
|
7579
7620
|
/** Logger service for debug output */
|
|
7580
7621
|
this.loggerService = inject(TYPES.loggerService);
|
|
7581
7622
|
/**
|
|
7582
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
7583
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
7623
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
7624
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
7584
7625
|
*/
|
|
7585
|
-
this.getStorage = memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$5());
|
|
7626
|
+
this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$5());
|
|
7586
7627
|
/**
|
|
7587
7628
|
* Processes tick events and accumulates closed signals.
|
|
7588
7629
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -7609,7 +7650,7 @@ class BacktestMarkdownService {
|
|
|
7609
7650
|
if (data.action !== "closed") {
|
|
7610
7651
|
return;
|
|
7611
7652
|
}
|
|
7612
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
7653
|
+
const storage = this.getStorage(data.symbol, data.strategyName, true);
|
|
7613
7654
|
storage.addSignal(data);
|
|
7614
7655
|
};
|
|
7615
7656
|
/**
|
|
@@ -7618,21 +7659,23 @@ class BacktestMarkdownService {
|
|
|
7618
7659
|
*
|
|
7619
7660
|
* @param symbol - Trading pair symbol
|
|
7620
7661
|
* @param strategyName - Strategy name to get data for
|
|
7662
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
7621
7663
|
* @returns Statistical data object with all metrics
|
|
7622
7664
|
*
|
|
7623
7665
|
* @example
|
|
7624
7666
|
* ```typescript
|
|
7625
7667
|
* const service = new BacktestMarkdownService();
|
|
7626
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
7668
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", true);
|
|
7627
7669
|
* console.log(stats.sharpeRatio, stats.winRate);
|
|
7628
7670
|
* ```
|
|
7629
7671
|
*/
|
|
7630
|
-
this.getData = async (symbol, strategyName) => {
|
|
7672
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
7631
7673
|
this.loggerService.log("backtestMarkdownService getData", {
|
|
7632
7674
|
symbol,
|
|
7633
7675
|
strategyName,
|
|
7676
|
+
backtest,
|
|
7634
7677
|
});
|
|
7635
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
7678
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
7636
7679
|
return storage.getData();
|
|
7637
7680
|
};
|
|
7638
7681
|
/**
|
|
@@ -7641,22 +7684,24 @@ class BacktestMarkdownService {
|
|
|
7641
7684
|
*
|
|
7642
7685
|
* @param symbol - Trading pair symbol
|
|
7643
7686
|
* @param strategyName - Strategy name to generate report for
|
|
7687
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
7644
7688
|
* @param columns - Column configuration for formatting the table
|
|
7645
7689
|
* @returns Markdown formatted report string with table of all closed signals
|
|
7646
7690
|
*
|
|
7647
7691
|
* @example
|
|
7648
7692
|
* ```typescript
|
|
7649
7693
|
* const service = new BacktestMarkdownService();
|
|
7650
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
7694
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", true);
|
|
7651
7695
|
* console.log(markdown);
|
|
7652
7696
|
* ```
|
|
7653
7697
|
*/
|
|
7654
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7698
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7655
7699
|
this.loggerService.log("backtestMarkdownService getReport", {
|
|
7656
7700
|
symbol,
|
|
7657
7701
|
strategyName,
|
|
7702
|
+
backtest,
|
|
7658
7703
|
});
|
|
7659
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
7704
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
7660
7705
|
return storage.getReport(strategyName, columns);
|
|
7661
7706
|
};
|
|
7662
7707
|
/**
|
|
@@ -7666,6 +7711,7 @@ class BacktestMarkdownService {
|
|
|
7666
7711
|
*
|
|
7667
7712
|
* @param symbol - Trading pair symbol
|
|
7668
7713
|
* @param strategyName - Strategy name to save report for
|
|
7714
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
7669
7715
|
* @param path - Directory path to save report (default: "./dump/backtest")
|
|
7670
7716
|
* @param columns - Column configuration for formatting the table
|
|
7671
7717
|
*
|
|
@@ -7674,45 +7720,48 @@ class BacktestMarkdownService {
|
|
|
7674
7720
|
* const service = new BacktestMarkdownService();
|
|
7675
7721
|
*
|
|
7676
7722
|
* // Save to default path: ./dump/backtest/my-strategy.md
|
|
7677
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
7723
|
+
* await service.dump("BTCUSDT", "my-strategy", true);
|
|
7678
7724
|
*
|
|
7679
7725
|
* // Save to custom path: ./custom/path/my-strategy.md
|
|
7680
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
7726
|
+
* await service.dump("BTCUSDT", "my-strategy", true, "./custom/path");
|
|
7681
7727
|
* ```
|
|
7682
7728
|
*/
|
|
7683
|
-
this.dump = async (symbol, strategyName, path = "./dump/backtest", columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7729
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/backtest", columns = COLUMN_CONFIG.backtest_columns) => {
|
|
7684
7730
|
this.loggerService.log("backtestMarkdownService dump", {
|
|
7685
7731
|
symbol,
|
|
7686
7732
|
strategyName,
|
|
7733
|
+
backtest,
|
|
7687
7734
|
path,
|
|
7688
7735
|
});
|
|
7689
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
7736
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
7690
7737
|
await storage.dump(strategyName, path, columns);
|
|
7691
7738
|
};
|
|
7692
7739
|
/**
|
|
7693
7740
|
* Clears accumulated signal data from storage.
|
|
7694
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
7741
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
7695
7742
|
* If nothing is provided, clears all data.
|
|
7696
7743
|
*
|
|
7744
|
+
* @param backtest - Backtest mode flag
|
|
7697
7745
|
* @param ctx - Optional context with symbol and strategyName
|
|
7698
7746
|
*
|
|
7699
7747
|
* @example
|
|
7700
7748
|
* ```typescript
|
|
7701
7749
|
* const service = new BacktestMarkdownService();
|
|
7702
7750
|
*
|
|
7703
|
-
* // Clear specific symbol-strategy
|
|
7704
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
7751
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
7752
|
+
* await service.clear(true, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
7705
7753
|
*
|
|
7706
7754
|
* // Clear all data
|
|
7707
7755
|
* await service.clear();
|
|
7708
7756
|
* ```
|
|
7709
7757
|
*/
|
|
7710
|
-
this.clear = async (ctx) => {
|
|
7758
|
+
this.clear = async (backtest, ctx) => {
|
|
7711
7759
|
this.loggerService.log("backtestMarkdownService clear", {
|
|
7760
|
+
backtest,
|
|
7712
7761
|
ctx,
|
|
7713
7762
|
});
|
|
7714
7763
|
if (ctx) {
|
|
7715
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
7764
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
7716
7765
|
this.getStorage.clear(key);
|
|
7717
7766
|
}
|
|
7718
7767
|
else {
|
|
@@ -8063,10 +8112,10 @@ class LiveMarkdownService {
|
|
|
8063
8112
|
/** Logger service for debug output */
|
|
8064
8113
|
this.loggerService = inject(TYPES.loggerService);
|
|
8065
8114
|
/**
|
|
8066
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
8067
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
8115
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
8116
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
8068
8117
|
*/
|
|
8069
|
-
this.getStorage = memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$4());
|
|
8118
|
+
this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$4());
|
|
8070
8119
|
/**
|
|
8071
8120
|
* Processes tick events and accumulates all event types.
|
|
8072
8121
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -8092,7 +8141,7 @@ class LiveMarkdownService {
|
|
|
8092
8141
|
this.loggerService.log("liveMarkdownService tick", {
|
|
8093
8142
|
data,
|
|
8094
8143
|
});
|
|
8095
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
8144
|
+
const storage = this.getStorage(data.symbol, data.strategyName, false);
|
|
8096
8145
|
if (data.action === "idle") {
|
|
8097
8146
|
storage.addIdleEvent(data.currentPrice);
|
|
8098
8147
|
}
|
|
@@ -8112,21 +8161,23 @@ class LiveMarkdownService {
|
|
|
8112
8161
|
*
|
|
8113
8162
|
* @param symbol - Trading pair symbol
|
|
8114
8163
|
* @param strategyName - Strategy name to get data for
|
|
8164
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8115
8165
|
* @returns Statistical data object with all metrics
|
|
8116
8166
|
*
|
|
8117
8167
|
* @example
|
|
8118
8168
|
* ```typescript
|
|
8119
8169
|
* const service = new LiveMarkdownService();
|
|
8120
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
8170
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
8121
8171
|
* console.log(stats.sharpeRatio, stats.winRate);
|
|
8122
8172
|
* ```
|
|
8123
8173
|
*/
|
|
8124
|
-
this.getData = async (symbol, strategyName) => {
|
|
8174
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
8125
8175
|
this.loggerService.log("liveMarkdownService getData", {
|
|
8126
8176
|
symbol,
|
|
8127
8177
|
strategyName,
|
|
8178
|
+
backtest,
|
|
8128
8179
|
});
|
|
8129
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8180
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8130
8181
|
return storage.getData();
|
|
8131
8182
|
};
|
|
8132
8183
|
/**
|
|
@@ -8135,22 +8186,24 @@ class LiveMarkdownService {
|
|
|
8135
8186
|
*
|
|
8136
8187
|
* @param symbol - Trading pair symbol
|
|
8137
8188
|
* @param strategyName - Strategy name to generate report for
|
|
8189
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8138
8190
|
* @param columns - Column configuration for formatting the table
|
|
8139
8191
|
* @returns Markdown formatted report string with table of all events
|
|
8140
8192
|
*
|
|
8141
8193
|
* @example
|
|
8142
8194
|
* ```typescript
|
|
8143
8195
|
* const service = new LiveMarkdownService();
|
|
8144
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
8196
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
8145
8197
|
* console.log(markdown);
|
|
8146
8198
|
* ```
|
|
8147
8199
|
*/
|
|
8148
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.live_columns) => {
|
|
8200
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.live_columns) => {
|
|
8149
8201
|
this.loggerService.log("liveMarkdownService getReport", {
|
|
8150
8202
|
symbol,
|
|
8151
8203
|
strategyName,
|
|
8204
|
+
backtest,
|
|
8152
8205
|
});
|
|
8153
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8206
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8154
8207
|
return storage.getReport(strategyName, columns);
|
|
8155
8208
|
};
|
|
8156
8209
|
/**
|
|
@@ -8160,6 +8213,7 @@ class LiveMarkdownService {
|
|
|
8160
8213
|
*
|
|
8161
8214
|
* @param symbol - Trading pair symbol
|
|
8162
8215
|
* @param strategyName - Strategy name to save report for
|
|
8216
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8163
8217
|
* @param path - Directory path to save report (default: "./dump/live")
|
|
8164
8218
|
* @param columns - Column configuration for formatting the table
|
|
8165
8219
|
*
|
|
@@ -8168,45 +8222,48 @@ class LiveMarkdownService {
|
|
|
8168
8222
|
* const service = new LiveMarkdownService();
|
|
8169
8223
|
*
|
|
8170
8224
|
* // Save to default path: ./dump/live/my-strategy.md
|
|
8171
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
8225
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
8172
8226
|
*
|
|
8173
8227
|
* // Save to custom path: ./custom/path/my-strategy.md
|
|
8174
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
8228
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
8175
8229
|
* ```
|
|
8176
8230
|
*/
|
|
8177
|
-
this.dump = async (symbol, strategyName, path = "./dump/live", columns = COLUMN_CONFIG.live_columns) => {
|
|
8231
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/live", columns = COLUMN_CONFIG.live_columns) => {
|
|
8178
8232
|
this.loggerService.log("liveMarkdownService dump", {
|
|
8179
8233
|
symbol,
|
|
8180
8234
|
strategyName,
|
|
8235
|
+
backtest,
|
|
8181
8236
|
path,
|
|
8182
8237
|
});
|
|
8183
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8238
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8184
8239
|
await storage.dump(strategyName, path, columns);
|
|
8185
8240
|
};
|
|
8186
8241
|
/**
|
|
8187
8242
|
* Clears accumulated event data from storage.
|
|
8188
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
8243
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
8189
8244
|
* If nothing is provided, clears all data.
|
|
8190
8245
|
*
|
|
8246
|
+
* @param backtest - Backtest mode flag
|
|
8191
8247
|
* @param ctx - Optional context with symbol and strategyName
|
|
8192
8248
|
*
|
|
8193
8249
|
* @example
|
|
8194
8250
|
* ```typescript
|
|
8195
8251
|
* const service = new LiveMarkdownService();
|
|
8196
8252
|
*
|
|
8197
|
-
* // Clear specific symbol-strategy
|
|
8198
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8253
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
8254
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8199
8255
|
*
|
|
8200
8256
|
* // Clear all data
|
|
8201
8257
|
* await service.clear();
|
|
8202
8258
|
* ```
|
|
8203
8259
|
*/
|
|
8204
|
-
this.clear = async (ctx) => {
|
|
8260
|
+
this.clear = async (backtest, ctx) => {
|
|
8205
8261
|
this.loggerService.log("liveMarkdownService clear", {
|
|
8262
|
+
backtest,
|
|
8206
8263
|
ctx,
|
|
8207
8264
|
});
|
|
8208
8265
|
if (ctx) {
|
|
8209
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
8266
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
8210
8267
|
this.getStorage.clear(key);
|
|
8211
8268
|
}
|
|
8212
8269
|
else {
|
|
@@ -8461,10 +8518,10 @@ class ScheduleMarkdownService {
|
|
|
8461
8518
|
/** Logger service for debug output */
|
|
8462
8519
|
this.loggerService = inject(TYPES.loggerService);
|
|
8463
8520
|
/**
|
|
8464
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
8465
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
8521
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
8522
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
8466
8523
|
*/
|
|
8467
|
-
this.getStorage = memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$3());
|
|
8524
|
+
this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$3());
|
|
8468
8525
|
/**
|
|
8469
8526
|
* Processes tick events and accumulates scheduled/opened/cancelled events.
|
|
8470
8527
|
* Should be called from signalEmitter subscription.
|
|
@@ -8483,7 +8540,7 @@ class ScheduleMarkdownService {
|
|
|
8483
8540
|
this.loggerService.log("scheduleMarkdownService tick", {
|
|
8484
8541
|
data,
|
|
8485
8542
|
});
|
|
8486
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
8543
|
+
const storage = this.getStorage(data.symbol, data.strategyName, data.backtest);
|
|
8487
8544
|
if (data.action === "scheduled") {
|
|
8488
8545
|
storage.addScheduledEvent(data);
|
|
8489
8546
|
}
|
|
@@ -8504,21 +8561,23 @@ class ScheduleMarkdownService {
|
|
|
8504
8561
|
*
|
|
8505
8562
|
* @param symbol - Trading pair symbol
|
|
8506
8563
|
* @param strategyName - Strategy name to get data for
|
|
8564
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8507
8565
|
* @returns Statistical data object with all metrics
|
|
8508
8566
|
*
|
|
8509
8567
|
* @example
|
|
8510
8568
|
* ```typescript
|
|
8511
8569
|
* const service = new ScheduleMarkdownService();
|
|
8512
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
8570
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
8513
8571
|
* console.log(stats.cancellationRate, stats.avgWaitTime);
|
|
8514
8572
|
* ```
|
|
8515
8573
|
*/
|
|
8516
|
-
this.getData = async (symbol, strategyName) => {
|
|
8574
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
8517
8575
|
this.loggerService.log("scheduleMarkdownService getData", {
|
|
8518
8576
|
symbol,
|
|
8519
8577
|
strategyName,
|
|
8578
|
+
backtest,
|
|
8520
8579
|
});
|
|
8521
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8580
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8522
8581
|
return storage.getData();
|
|
8523
8582
|
};
|
|
8524
8583
|
/**
|
|
@@ -8527,22 +8586,24 @@ class ScheduleMarkdownService {
|
|
|
8527
8586
|
*
|
|
8528
8587
|
* @param symbol - Trading pair symbol
|
|
8529
8588
|
* @param strategyName - Strategy name to generate report for
|
|
8589
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8530
8590
|
* @param columns - Column configuration for formatting the table
|
|
8531
8591
|
* @returns Markdown formatted report string with table of all events
|
|
8532
8592
|
*
|
|
8533
8593
|
* @example
|
|
8534
8594
|
* ```typescript
|
|
8535
8595
|
* const service = new ScheduleMarkdownService();
|
|
8536
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
8596
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
8537
8597
|
* console.log(markdown);
|
|
8538
8598
|
* ```
|
|
8539
8599
|
*/
|
|
8540
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8600
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8541
8601
|
this.loggerService.log("scheduleMarkdownService getReport", {
|
|
8542
8602
|
symbol,
|
|
8543
8603
|
strategyName,
|
|
8604
|
+
backtest,
|
|
8544
8605
|
});
|
|
8545
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8606
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8546
8607
|
return storage.getReport(strategyName, columns);
|
|
8547
8608
|
};
|
|
8548
8609
|
/**
|
|
@@ -8552,6 +8613,7 @@ class ScheduleMarkdownService {
|
|
|
8552
8613
|
*
|
|
8553
8614
|
* @param symbol - Trading pair symbol
|
|
8554
8615
|
* @param strategyName - Strategy name to save report for
|
|
8616
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8555
8617
|
* @param path - Directory path to save report (default: "./dump/schedule")
|
|
8556
8618
|
* @param columns - Column configuration for formatting the table
|
|
8557
8619
|
*
|
|
@@ -8560,45 +8622,48 @@ class ScheduleMarkdownService {
|
|
|
8560
8622
|
* const service = new ScheduleMarkdownService();
|
|
8561
8623
|
*
|
|
8562
8624
|
* // Save to default path: ./dump/schedule/my-strategy.md
|
|
8563
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
8625
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
8564
8626
|
*
|
|
8565
8627
|
* // Save to custom path: ./custom/path/my-strategy.md
|
|
8566
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
8628
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
8567
8629
|
* ```
|
|
8568
8630
|
*/
|
|
8569
|
-
this.dump = async (symbol, strategyName, path = "./dump/schedule", columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8631
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/schedule", columns = COLUMN_CONFIG.schedule_columns) => {
|
|
8570
8632
|
this.loggerService.log("scheduleMarkdownService dump", {
|
|
8571
8633
|
symbol,
|
|
8572
8634
|
strategyName,
|
|
8635
|
+
backtest,
|
|
8573
8636
|
path,
|
|
8574
8637
|
});
|
|
8575
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8638
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8576
8639
|
await storage.dump(strategyName, path, columns);
|
|
8577
8640
|
};
|
|
8578
8641
|
/**
|
|
8579
8642
|
* Clears accumulated event data from storage.
|
|
8580
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
8643
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
8581
8644
|
* If nothing is provided, clears all data.
|
|
8582
8645
|
*
|
|
8646
|
+
* @param backtest - Backtest mode flag
|
|
8583
8647
|
* @param ctx - Optional context with symbol and strategyName
|
|
8584
8648
|
*
|
|
8585
8649
|
* @example
|
|
8586
8650
|
* ```typescript
|
|
8587
8651
|
* const service = new ScheduleMarkdownService();
|
|
8588
8652
|
*
|
|
8589
|
-
* // Clear specific symbol-strategy
|
|
8590
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8653
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
8654
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
8591
8655
|
*
|
|
8592
8656
|
* // Clear all data
|
|
8593
8657
|
* await service.clear();
|
|
8594
8658
|
* ```
|
|
8595
8659
|
*/
|
|
8596
|
-
this.clear = async (ctx) => {
|
|
8660
|
+
this.clear = async (backtest, ctx) => {
|
|
8597
8661
|
this.loggerService.log("scheduleMarkdownService clear", {
|
|
8662
|
+
backtest,
|
|
8598
8663
|
ctx,
|
|
8599
8664
|
});
|
|
8600
8665
|
if (ctx) {
|
|
8601
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
8666
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
8602
8667
|
this.getStorage.clear(key);
|
|
8603
8668
|
}
|
|
8604
8669
|
else {
|
|
@@ -8837,10 +8902,10 @@ class PerformanceMarkdownService {
|
|
|
8837
8902
|
/** Logger service for debug output */
|
|
8838
8903
|
this.loggerService = inject(TYPES.loggerService);
|
|
8839
8904
|
/**
|
|
8840
|
-
* Memoized function to get or create PerformanceStorage for a symbol-strategy
|
|
8841
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
8905
|
+
* Memoized function to get or create PerformanceStorage for a symbol-strategy-backtest triple.
|
|
8906
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
8842
8907
|
*/
|
|
8843
|
-
this.getStorage = memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new PerformanceStorage());
|
|
8908
|
+
this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new PerformanceStorage());
|
|
8844
8909
|
/**
|
|
8845
8910
|
* Processes performance events and accumulates metrics.
|
|
8846
8911
|
* Should be called from performance tracking code.
|
|
@@ -8853,7 +8918,7 @@ class PerformanceMarkdownService {
|
|
|
8853
8918
|
});
|
|
8854
8919
|
const symbol = event.symbol || "global";
|
|
8855
8920
|
const strategyName = event.strategyName || "global";
|
|
8856
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8921
|
+
const storage = this.getStorage(symbol, strategyName, event.backtest);
|
|
8857
8922
|
storage.addEvent(event);
|
|
8858
8923
|
};
|
|
8859
8924
|
/**
|
|
@@ -8861,22 +8926,24 @@ class PerformanceMarkdownService {
|
|
|
8861
8926
|
*
|
|
8862
8927
|
* @param symbol - Trading pair symbol
|
|
8863
8928
|
* @param strategyName - Strategy name to get data for
|
|
8929
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8864
8930
|
* @returns Performance statistics with aggregated metrics
|
|
8865
8931
|
*
|
|
8866
8932
|
* @example
|
|
8867
8933
|
* ```typescript
|
|
8868
|
-
* const stats = await performanceService.getData("BTCUSDT", "my-strategy");
|
|
8934
|
+
* const stats = await performanceService.getData("BTCUSDT", "my-strategy", false);
|
|
8869
8935
|
* console.log("Total time:", stats.totalDuration);
|
|
8870
8936
|
* console.log("Slowest operation:", Object.values(stats.metricStats)
|
|
8871
8937
|
* .sort((a, b) => b.avgDuration - a.avgDuration)[0]);
|
|
8872
8938
|
* ```
|
|
8873
8939
|
*/
|
|
8874
|
-
this.getData = async (symbol, strategyName) => {
|
|
8940
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
8875
8941
|
this.loggerService.log("performanceMarkdownService getData", {
|
|
8876
8942
|
symbol,
|
|
8877
8943
|
strategyName,
|
|
8944
|
+
backtest,
|
|
8878
8945
|
});
|
|
8879
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8946
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8880
8947
|
return storage.getData(strategyName);
|
|
8881
8948
|
};
|
|
8882
8949
|
/**
|
|
@@ -8884,21 +8951,23 @@ class PerformanceMarkdownService {
|
|
|
8884
8951
|
*
|
|
8885
8952
|
* @param symbol - Trading pair symbol
|
|
8886
8953
|
* @param strategyName - Strategy name to generate report for
|
|
8954
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8887
8955
|
* @param columns - Column configuration for formatting the table
|
|
8888
8956
|
* @returns Markdown formatted report string
|
|
8889
8957
|
*
|
|
8890
8958
|
* @example
|
|
8891
8959
|
* ```typescript
|
|
8892
|
-
* const markdown = await performanceService.getReport("BTCUSDT", "my-strategy");
|
|
8960
|
+
* const markdown = await performanceService.getReport("BTCUSDT", "my-strategy", false);
|
|
8893
8961
|
* console.log(markdown);
|
|
8894
8962
|
* ```
|
|
8895
8963
|
*/
|
|
8896
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.performance_columns) => {
|
|
8964
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.performance_columns) => {
|
|
8897
8965
|
this.loggerService.log("performanceMarkdownService getReport", {
|
|
8898
8966
|
symbol,
|
|
8899
8967
|
strategyName,
|
|
8968
|
+
backtest,
|
|
8900
8969
|
});
|
|
8901
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8970
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8902
8971
|
return storage.getReport(strategyName, columns);
|
|
8903
8972
|
};
|
|
8904
8973
|
/**
|
|
@@ -8906,42 +8975,45 @@ class PerformanceMarkdownService {
|
|
|
8906
8975
|
*
|
|
8907
8976
|
* @param symbol - Trading pair symbol
|
|
8908
8977
|
* @param strategyName - Strategy name to save report for
|
|
8978
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
8909
8979
|
* @param path - Directory path to save report
|
|
8910
8980
|
* @param columns - Column configuration for formatting the table
|
|
8911
8981
|
*
|
|
8912
8982
|
* @example
|
|
8913
8983
|
* ```typescript
|
|
8914
8984
|
* // Save to default path: ./dump/performance/my-strategy.md
|
|
8915
|
-
* await performanceService.dump("BTCUSDT", "my-strategy");
|
|
8985
|
+
* await performanceService.dump("BTCUSDT", "my-strategy", false);
|
|
8916
8986
|
*
|
|
8917
8987
|
* // Save to custom path
|
|
8918
|
-
* await performanceService.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
8988
|
+
* await performanceService.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
8919
8989
|
* ```
|
|
8920
8990
|
*/
|
|
8921
|
-
this.dump = async (symbol, strategyName, path = "./dump/performance", columns = COLUMN_CONFIG.performance_columns) => {
|
|
8991
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/performance", columns = COLUMN_CONFIG.performance_columns) => {
|
|
8922
8992
|
this.loggerService.log("performanceMarkdownService dump", {
|
|
8923
8993
|
symbol,
|
|
8924
8994
|
strategyName,
|
|
8995
|
+
backtest,
|
|
8925
8996
|
path,
|
|
8926
8997
|
});
|
|
8927
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
8998
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
8928
8999
|
await storage.dump(strategyName, path, columns);
|
|
8929
9000
|
};
|
|
8930
9001
|
/**
|
|
8931
9002
|
* Clears accumulated performance data from storage.
|
|
8932
9003
|
*
|
|
8933
|
-
* @param
|
|
8934
|
-
* @param
|
|
9004
|
+
* @param backtest - Backtest mode flag
|
|
9005
|
+
* @param ctx - Optional context with symbol and strategyName
|
|
8935
9006
|
*/
|
|
8936
|
-
this.clear = async (ctx) => {
|
|
9007
|
+
this.clear = async (backtest, ctx) => {
|
|
8937
9008
|
this.loggerService.log("performanceMarkdownService clear", {
|
|
9009
|
+
backtest,
|
|
8938
9010
|
ctx,
|
|
8939
9011
|
});
|
|
8940
9012
|
if (ctx) {
|
|
8941
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
9013
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
8942
9014
|
this.getStorage.clear(key);
|
|
8943
9015
|
}
|
|
8944
|
-
{
|
|
9016
|
+
else {
|
|
8945
9017
|
this.getStorage.clear();
|
|
8946
9018
|
}
|
|
8947
9019
|
};
|
|
@@ -9705,10 +9777,10 @@ class HeatMarkdownService {
|
|
|
9705
9777
|
/** Logger service for debug output */
|
|
9706
9778
|
this.loggerService = inject(TYPES.loggerService);
|
|
9707
9779
|
/**
|
|
9708
|
-
* Memoized function to get or create HeatmapStorage for a strategy.
|
|
9709
|
-
* Each strategy gets its own isolated heatmap storage instance.
|
|
9780
|
+
* Memoized function to get or create HeatmapStorage for a strategy and backtest mode.
|
|
9781
|
+
* Each strategy + backtest mode combination gets its own isolated heatmap storage instance.
|
|
9710
9782
|
*/
|
|
9711
|
-
this.getStorage = memoize(([strategyName]) => `${strategyName}`, () => new HeatmapStorage());
|
|
9783
|
+
this.getStorage = memoize(([strategyName, backtest]) => `${strategyName}:${backtest ? "backtest" : "live"}`, () => new HeatmapStorage());
|
|
9712
9784
|
/**
|
|
9713
9785
|
* Processes tick events and accumulates closed signals.
|
|
9714
9786
|
* Should be called from signal emitter subscription.
|
|
@@ -9724,19 +9796,20 @@ class HeatMarkdownService {
|
|
|
9724
9796
|
if (data.action !== "closed") {
|
|
9725
9797
|
return;
|
|
9726
9798
|
}
|
|
9727
|
-
const storage = this.getStorage(data.strategyName);
|
|
9799
|
+
const storage = this.getStorage(data.strategyName, data.backtest);
|
|
9728
9800
|
storage.addSignal(data);
|
|
9729
9801
|
};
|
|
9730
9802
|
/**
|
|
9731
9803
|
* Gets aggregated portfolio heatmap statistics for a strategy.
|
|
9732
9804
|
*
|
|
9733
9805
|
* @param strategyName - Strategy name to get heatmap data for
|
|
9806
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
9734
9807
|
* @returns Promise resolving to heatmap statistics with per-symbol and portfolio-wide metrics
|
|
9735
9808
|
*
|
|
9736
9809
|
* @example
|
|
9737
9810
|
* ```typescript
|
|
9738
9811
|
* const service = new HeatMarkdownService();
|
|
9739
|
-
* const stats = await service.getData("my-strategy");
|
|
9812
|
+
* const stats = await service.getData("my-strategy", true);
|
|
9740
9813
|
*
|
|
9741
9814
|
* console.log(`Total symbols: ${stats.totalSymbols}`);
|
|
9742
9815
|
* console.log(`Portfolio PNL: ${stats.portfolioTotalPnl}%`);
|
|
@@ -9746,24 +9819,26 @@ class HeatMarkdownService {
|
|
|
9746
9819
|
* });
|
|
9747
9820
|
* ```
|
|
9748
9821
|
*/
|
|
9749
|
-
this.getData = async (strategyName) => {
|
|
9822
|
+
this.getData = async (strategyName, backtest) => {
|
|
9750
9823
|
this.loggerService.log(HEATMAP_METHOD_NAME_GET_DATA, {
|
|
9751
9824
|
strategyName,
|
|
9825
|
+
backtest,
|
|
9752
9826
|
});
|
|
9753
|
-
const storage = this.getStorage(strategyName);
|
|
9827
|
+
const storage = this.getStorage(strategyName, backtest);
|
|
9754
9828
|
return storage.getData();
|
|
9755
9829
|
};
|
|
9756
9830
|
/**
|
|
9757
9831
|
* Generates markdown report with portfolio heatmap table for a strategy.
|
|
9758
9832
|
*
|
|
9759
9833
|
* @param strategyName - Strategy name to generate heatmap report for
|
|
9834
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
9760
9835
|
* @param columns - Column configuration for formatting the table
|
|
9761
9836
|
* @returns Promise resolving to markdown formatted report string
|
|
9762
9837
|
*
|
|
9763
9838
|
* @example
|
|
9764
9839
|
* ```typescript
|
|
9765
9840
|
* const service = new HeatMarkdownService();
|
|
9766
|
-
* const markdown = await service.getReport("my-strategy");
|
|
9841
|
+
* const markdown = await service.getReport("my-strategy", true);
|
|
9767
9842
|
* console.log(markdown);
|
|
9768
9843
|
* // Output:
|
|
9769
9844
|
* // # Portfolio Heatmap: my-strategy
|
|
@@ -9777,11 +9852,12 @@ class HeatMarkdownService {
|
|
|
9777
9852
|
* // ...
|
|
9778
9853
|
* ```
|
|
9779
9854
|
*/
|
|
9780
|
-
this.getReport = async (strategyName, columns = COLUMN_CONFIG.heat_columns) => {
|
|
9855
|
+
this.getReport = async (strategyName, backtest, columns = COLUMN_CONFIG.heat_columns) => {
|
|
9781
9856
|
this.loggerService.log(HEATMAP_METHOD_NAME_GET_REPORT, {
|
|
9782
9857
|
strategyName,
|
|
9858
|
+
backtest,
|
|
9783
9859
|
});
|
|
9784
|
-
const storage = this.getStorage(strategyName);
|
|
9860
|
+
const storage = this.getStorage(strategyName, backtest);
|
|
9785
9861
|
return storage.getReport(strategyName, columns);
|
|
9786
9862
|
};
|
|
9787
9863
|
/**
|
|
@@ -9791,6 +9867,7 @@ class HeatMarkdownService {
|
|
|
9791
9867
|
* Default filename: {strategyName}.md
|
|
9792
9868
|
*
|
|
9793
9869
|
* @param strategyName - Strategy name to save heatmap report for
|
|
9870
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
9794
9871
|
* @param path - Optional directory path to save report (default: "./dump/heatmap")
|
|
9795
9872
|
* @param columns - Column configuration for formatting the table
|
|
9796
9873
|
*
|
|
@@ -9799,43 +9876,52 @@ class HeatMarkdownService {
|
|
|
9799
9876
|
* const service = new HeatMarkdownService();
|
|
9800
9877
|
*
|
|
9801
9878
|
* // Save to default path: ./dump/heatmap/my-strategy.md
|
|
9802
|
-
* await service.dump("my-strategy");
|
|
9879
|
+
* await service.dump("my-strategy", true);
|
|
9803
9880
|
*
|
|
9804
9881
|
* // Save to custom path: ./reports/my-strategy.md
|
|
9805
|
-
* await service.dump("my-strategy", "./reports");
|
|
9882
|
+
* await service.dump("my-strategy", true, "./reports");
|
|
9806
9883
|
* ```
|
|
9807
9884
|
*/
|
|
9808
|
-
this.dump = async (strategyName, path = "./dump/heatmap", columns = COLUMN_CONFIG.heat_columns) => {
|
|
9885
|
+
this.dump = async (strategyName, backtest, path = "./dump/heatmap", columns = COLUMN_CONFIG.heat_columns) => {
|
|
9809
9886
|
this.loggerService.log(HEATMAP_METHOD_NAME_DUMP, {
|
|
9810
9887
|
strategyName,
|
|
9888
|
+
backtest,
|
|
9811
9889
|
path,
|
|
9812
9890
|
});
|
|
9813
|
-
const storage = this.getStorage(strategyName);
|
|
9891
|
+
const storage = this.getStorage(strategyName, backtest);
|
|
9814
9892
|
await storage.dump(strategyName, path, columns);
|
|
9815
9893
|
};
|
|
9816
9894
|
/**
|
|
9817
9895
|
* Clears accumulated heatmap data from storage.
|
|
9818
|
-
* If
|
|
9819
|
-
* If
|
|
9896
|
+
* If ctx is provided, clears only that strategy+backtest combination's data.
|
|
9897
|
+
* If ctx is omitted, clears all data.
|
|
9820
9898
|
*
|
|
9821
|
-
* @param
|
|
9899
|
+
* @param backtest - Backtest mode flag
|
|
9900
|
+
* @param ctx - Optional context with strategyName to clear specific data
|
|
9822
9901
|
*
|
|
9823
9902
|
* @example
|
|
9824
9903
|
* ```typescript
|
|
9825
9904
|
* const service = new HeatMarkdownService();
|
|
9826
9905
|
*
|
|
9827
|
-
* // Clear specific strategy data
|
|
9828
|
-
* await service.clear("my-strategy");
|
|
9906
|
+
* // Clear specific strategy+backtest data
|
|
9907
|
+
* await service.clear(true, { strategyName: "my-strategy" });
|
|
9829
9908
|
*
|
|
9830
|
-
* // Clear all
|
|
9909
|
+
* // Clear all data
|
|
9831
9910
|
* await service.clear();
|
|
9832
9911
|
* ```
|
|
9833
9912
|
*/
|
|
9834
|
-
this.clear = async (
|
|
9913
|
+
this.clear = async (backtest, ctx) => {
|
|
9835
9914
|
this.loggerService.log(HEATMAP_METHOD_NAME_CLEAR, {
|
|
9836
|
-
|
|
9915
|
+
backtest,
|
|
9916
|
+
ctx,
|
|
9837
9917
|
});
|
|
9838
|
-
|
|
9918
|
+
if (ctx) {
|
|
9919
|
+
const key = `${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
9920
|
+
this.getStorage.clear(key);
|
|
9921
|
+
}
|
|
9922
|
+
else {
|
|
9923
|
+
this.getStorage.clear();
|
|
9924
|
+
}
|
|
9839
9925
|
};
|
|
9840
9926
|
/**
|
|
9841
9927
|
* Initializes the service by subscribing to signal events.
|
|
@@ -11665,6 +11751,9 @@ const HANDLE_PROFIT_FN = async (symbol, data, currentPrice, revenuePercent, back
|
|
|
11665
11751
|
if (self._states === NEED_FETCH) {
|
|
11666
11752
|
throw new Error("ClientPartial not initialized. Call waitForInit() before using.");
|
|
11667
11753
|
}
|
|
11754
|
+
if (data.id !== self.params.signalId) {
|
|
11755
|
+
throw new Error(`Signal ID mismatch: expected ${self.params.signalId}, got ${data.id}`);
|
|
11756
|
+
}
|
|
11668
11757
|
let state = self._states.get(data.id);
|
|
11669
11758
|
if (!state) {
|
|
11670
11759
|
state = {
|
|
@@ -11689,7 +11778,7 @@ const HANDLE_PROFIT_FN = async (symbol, data, currentPrice, revenuePercent, back
|
|
|
11689
11778
|
}
|
|
11690
11779
|
}
|
|
11691
11780
|
if (shouldPersist) {
|
|
11692
|
-
await self._persistState(symbol,
|
|
11781
|
+
await self._persistState(symbol, data.strategyName);
|
|
11693
11782
|
}
|
|
11694
11783
|
};
|
|
11695
11784
|
/**
|
|
@@ -11711,6 +11800,9 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
|
|
|
11711
11800
|
if (self._states === NEED_FETCH) {
|
|
11712
11801
|
throw new Error("ClientPartial not initialized. Call waitForInit() before using.");
|
|
11713
11802
|
}
|
|
11803
|
+
if (data.id !== self.params.signalId) {
|
|
11804
|
+
throw new Error(`Signal ID mismatch: expected ${self.params.signalId}, got ${data.id}`);
|
|
11805
|
+
}
|
|
11714
11806
|
let state = self._states.get(data.id);
|
|
11715
11807
|
if (!state) {
|
|
11716
11808
|
state = {
|
|
@@ -11736,7 +11828,7 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
|
|
|
11736
11828
|
}
|
|
11737
11829
|
}
|
|
11738
11830
|
if (shouldPersist) {
|
|
11739
|
-
await self._persistState(symbol,
|
|
11831
|
+
await self._persistState(symbol, data.strategyName);
|
|
11740
11832
|
}
|
|
11741
11833
|
};
|
|
11742
11834
|
/**
|
|
@@ -11745,15 +11837,29 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
|
|
|
11745
11837
|
* Loads persisted partial state from disk and restores in-memory Maps.
|
|
11746
11838
|
* Converts serialized arrays back to Sets for O(1) lookups.
|
|
11747
11839
|
*
|
|
11840
|
+
* ONLY runs in LIVE mode (backtest=false). In backtest mode, state is not persisted.
|
|
11841
|
+
*
|
|
11748
11842
|
* @param symbol - Trading pair symbol
|
|
11843
|
+
* @param strategyName - Strategy identifier
|
|
11844
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
11749
11845
|
* @param self - ClientPartial instance reference
|
|
11750
11846
|
*/
|
|
11751
|
-
const WAIT_FOR_INIT_FN = async (symbol, self) => {
|
|
11752
|
-
self.params.logger.debug("ClientPartial waitForInit", {
|
|
11753
|
-
|
|
11754
|
-
|
|
11847
|
+
const WAIT_FOR_INIT_FN = async (symbol, strategyName, self) => {
|
|
11848
|
+
self.params.logger.debug("ClientPartial waitForInit", {
|
|
11849
|
+
symbol,
|
|
11850
|
+
strategyName,
|
|
11851
|
+
backtest: self.params.backtest
|
|
11852
|
+
});
|
|
11853
|
+
if (self._states !== NEED_FETCH) {
|
|
11854
|
+
throw new Error("ClientPartial WAIT_FOR_INIT_FN should be called once!");
|
|
11755
11855
|
}
|
|
11756
|
-
|
|
11856
|
+
self._states = new Map();
|
|
11857
|
+
// Skip persistence in backtest mode
|
|
11858
|
+
if (self.params.backtest) {
|
|
11859
|
+
self.params.logger.debug("ClientPartial waitForInit: skipping persist read in backtest mode");
|
|
11860
|
+
return;
|
|
11861
|
+
}
|
|
11862
|
+
const partialData = await PersistPartialAdapter.readPartialData(symbol, strategyName);
|
|
11757
11863
|
for (const [signalId, data] of Object.entries(partialData)) {
|
|
11758
11864
|
const state = {
|
|
11759
11865
|
profitLevels: new Set(data.profitLevels),
|
|
@@ -11763,6 +11869,7 @@ const WAIT_FOR_INIT_FN = async (symbol, self) => {
|
|
|
11763
11869
|
}
|
|
11764
11870
|
self.params.logger.info("ClientPartial restored state", {
|
|
11765
11871
|
symbol,
|
|
11872
|
+
strategyName,
|
|
11766
11873
|
signalCount: Object.keys(partialData).length,
|
|
11767
11874
|
});
|
|
11768
11875
|
};
|
|
@@ -11841,23 +11948,24 @@ class ClientPartial {
|
|
|
11841
11948
|
/**
|
|
11842
11949
|
* Initializes partial state by loading from disk.
|
|
11843
11950
|
*
|
|
11844
|
-
* Uses singleshot pattern to ensure initialization happens exactly once per symbol.
|
|
11951
|
+
* Uses singleshot pattern to ensure initialization happens exactly once per symbol:strategyName.
|
|
11845
11952
|
* Reads persisted state from PersistPartialAdapter and restores to _states Map.
|
|
11846
11953
|
*
|
|
11847
11954
|
* Must be called before profit()/loss()/clear() methods.
|
|
11848
11955
|
*
|
|
11849
11956
|
* @param symbol - Trading pair symbol
|
|
11957
|
+
* @param strategyName - Strategy identifier
|
|
11958
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
11850
11959
|
* @returns Promise that resolves when initialization is complete
|
|
11851
11960
|
*
|
|
11852
11961
|
* @example
|
|
11853
11962
|
* ```typescript
|
|
11854
11963
|
* const partial = new ClientPartial(params);
|
|
11855
|
-
* await partial.waitForInit("BTCUSDT"); // Load persisted state
|
|
11964
|
+
* await partial.waitForInit("BTCUSDT", "my-strategy", false); // Load persisted state (live mode)
|
|
11856
11965
|
* // Now profit()/loss() can be called
|
|
11857
11966
|
* ```
|
|
11858
11967
|
*/
|
|
11859
|
-
this.waitForInit = singleshot(async (symbol) => await WAIT_FOR_INIT_FN(symbol, this));
|
|
11860
|
-
this._states = new Map();
|
|
11968
|
+
this.waitForInit = singleshot(async (symbol, strategyName) => await WAIT_FOR_INIT_FN(symbol, strategyName, this));
|
|
11861
11969
|
}
|
|
11862
11970
|
/**
|
|
11863
11971
|
* Persists current partial state to disk.
|
|
@@ -11870,13 +11978,15 @@ class ClientPartial {
|
|
|
11870
11978
|
* Uses atomic file writes via PersistPartialAdapter.
|
|
11871
11979
|
*
|
|
11872
11980
|
* @param symbol - Trading pair symbol
|
|
11981
|
+
* @param strategyName - Strategy identifier
|
|
11982
|
+
* @param backtest - True if backtest mode
|
|
11873
11983
|
* @returns Promise that resolves when persistence is complete
|
|
11874
11984
|
*/
|
|
11875
|
-
async _persistState(symbol,
|
|
11876
|
-
if (backtest) {
|
|
11985
|
+
async _persistState(symbol, strategyName) {
|
|
11986
|
+
if (this.params.backtest) {
|
|
11877
11987
|
return;
|
|
11878
11988
|
}
|
|
11879
|
-
this.params.logger.debug("ClientPartial persistState", { symbol });
|
|
11989
|
+
this.params.logger.debug("ClientPartial persistState", { symbol, strategyName });
|
|
11880
11990
|
if (this._states === NEED_FETCH) {
|
|
11881
11991
|
throw new Error("ClientPartial not initialized. Call waitForInit() before using.");
|
|
11882
11992
|
}
|
|
@@ -11887,7 +11997,7 @@ class ClientPartial {
|
|
|
11887
11997
|
lossLevels: Array.from(state.lossLevels),
|
|
11888
11998
|
};
|
|
11889
11999
|
}
|
|
11890
|
-
await PersistPartialAdapter.writePartialData(partialData, symbol);
|
|
12000
|
+
await PersistPartialAdapter.writePartialData(partialData, symbol, strategyName);
|
|
11891
12001
|
}
|
|
11892
12002
|
/**
|
|
11893
12003
|
* Processes profit state and emits events for newly reached profit levels.
|
|
@@ -12008,8 +12118,11 @@ class ClientPartial {
|
|
|
12008
12118
|
if (this._states === NEED_FETCH) {
|
|
12009
12119
|
throw new Error("ClientPartial not initialized. Call waitForInit() before using.");
|
|
12010
12120
|
}
|
|
12121
|
+
if (data.id !== this.params.signalId) {
|
|
12122
|
+
throw new Error(`Signal ID mismatch: expected ${this.params.signalId}, got ${data.id}`);
|
|
12123
|
+
}
|
|
12011
12124
|
this._states.delete(data.id);
|
|
12012
|
-
await this._persistState(symbol,
|
|
12125
|
+
await this._persistState(symbol, data.strategyName);
|
|
12013
12126
|
}
|
|
12014
12127
|
}
|
|
12015
12128
|
|
|
@@ -12104,15 +12217,17 @@ class PartialConnectionService {
|
|
|
12104
12217
|
/**
|
|
12105
12218
|
* Memoized factory function for ClientPartial instances.
|
|
12106
12219
|
*
|
|
12107
|
-
* Creates one ClientPartial per signal ID with configured callbacks.
|
|
12220
|
+
* Creates one ClientPartial per signal ID and backtest mode with configured callbacks.
|
|
12108
12221
|
* Instances are cached until clear() is called.
|
|
12109
12222
|
*
|
|
12110
|
-
* Key format: signalId
|
|
12223
|
+
* Key format: "signalId:backtest" or "signalId:live"
|
|
12111
12224
|
* Value: ClientPartial instance with logger and event emitters
|
|
12112
12225
|
*/
|
|
12113
|
-
this.getPartial = memoize(([signalId]) => `${signalId}`, () => {
|
|
12226
|
+
this.getPartial = memoize(([signalId, backtest]) => `${signalId}:${backtest ? "backtest" : "live"}`, (signalId, backtest) => {
|
|
12114
12227
|
return new ClientPartial({
|
|
12228
|
+
signalId,
|
|
12115
12229
|
logger: this.loggerService,
|
|
12230
|
+
backtest,
|
|
12116
12231
|
onProfit: COMMIT_PROFIT_FN,
|
|
12117
12232
|
onLoss: COMMIT_LOSS_FN,
|
|
12118
12233
|
});
|
|
@@ -12140,8 +12255,8 @@ class PartialConnectionService {
|
|
|
12140
12255
|
backtest,
|
|
12141
12256
|
when,
|
|
12142
12257
|
});
|
|
12143
|
-
const partial = this.getPartial(data.id);
|
|
12144
|
-
await partial.waitForInit(symbol);
|
|
12258
|
+
const partial = this.getPartial(data.id, backtest);
|
|
12259
|
+
await partial.waitForInit(symbol, data.strategyName);
|
|
12145
12260
|
return await partial.profit(symbol, data, currentPrice, revenuePercent, backtest, when);
|
|
12146
12261
|
};
|
|
12147
12262
|
/**
|
|
@@ -12167,8 +12282,8 @@ class PartialConnectionService {
|
|
|
12167
12282
|
backtest,
|
|
12168
12283
|
when,
|
|
12169
12284
|
});
|
|
12170
|
-
const partial = this.getPartial(data.id);
|
|
12171
|
-
await partial.waitForInit(symbol);
|
|
12285
|
+
const partial = this.getPartial(data.id, backtest);
|
|
12286
|
+
await partial.waitForInit(symbol, data.strategyName);
|
|
12172
12287
|
return await partial.loss(symbol, data, currentPrice, lossPercent, backtest, when);
|
|
12173
12288
|
};
|
|
12174
12289
|
/**
|
|
@@ -12189,15 +12304,17 @@ class PartialConnectionService {
|
|
|
12189
12304
|
* @returns Promise that resolves when clear is complete
|
|
12190
12305
|
*/
|
|
12191
12306
|
this.clear = async (symbol, data, priceClose, backtest) => {
|
|
12192
|
-
this.loggerService.log("partialConnectionService
|
|
12307
|
+
this.loggerService.log("partialConnectionService clear", {
|
|
12193
12308
|
symbol,
|
|
12194
12309
|
data,
|
|
12195
12310
|
priceClose,
|
|
12311
|
+
backtest,
|
|
12196
12312
|
});
|
|
12197
|
-
const partial = this.getPartial(data.id);
|
|
12198
|
-
await partial.waitForInit(symbol);
|
|
12313
|
+
const partial = this.getPartial(data.id, backtest);
|
|
12314
|
+
await partial.waitForInit(symbol, data.strategyName);
|
|
12199
12315
|
await partial.clear(symbol, data, priceClose, backtest);
|
|
12200
|
-
|
|
12316
|
+
const key = `${data.id}:${backtest ? "backtest" : "live"}`;
|
|
12317
|
+
this.getPartial.clear(key);
|
|
12201
12318
|
};
|
|
12202
12319
|
}
|
|
12203
12320
|
}
|
|
@@ -12373,10 +12490,10 @@ class PartialMarkdownService {
|
|
|
12373
12490
|
/** Logger service for debug output */
|
|
12374
12491
|
this.loggerService = inject(TYPES.loggerService);
|
|
12375
12492
|
/**
|
|
12376
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
12377
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
12493
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
12494
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
12378
12495
|
*/
|
|
12379
|
-
this.getStorage = memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$1());
|
|
12496
|
+
this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage$1());
|
|
12380
12497
|
/**
|
|
12381
12498
|
* Processes profit events and accumulates them.
|
|
12382
12499
|
* Should be called from partialProfitSubject subscription.
|
|
@@ -12393,7 +12510,7 @@ class PartialMarkdownService {
|
|
|
12393
12510
|
this.loggerService.log("partialMarkdownService tickProfit", {
|
|
12394
12511
|
data,
|
|
12395
12512
|
});
|
|
12396
|
-
const storage = this.getStorage(data.symbol, data.data.strategyName);
|
|
12513
|
+
const storage = this.getStorage(data.symbol, data.data.strategyName, data.backtest);
|
|
12397
12514
|
storage.addProfitEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
|
|
12398
12515
|
};
|
|
12399
12516
|
/**
|
|
@@ -12412,7 +12529,7 @@ class PartialMarkdownService {
|
|
|
12412
12529
|
this.loggerService.log("partialMarkdownService tickLoss", {
|
|
12413
12530
|
data,
|
|
12414
12531
|
});
|
|
12415
|
-
const storage = this.getStorage(data.symbol, data.data.strategyName);
|
|
12532
|
+
const storage = this.getStorage(data.symbol, data.data.strategyName, data.backtest);
|
|
12416
12533
|
storage.addLossEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
|
|
12417
12534
|
};
|
|
12418
12535
|
/**
|
|
@@ -12421,21 +12538,23 @@ class PartialMarkdownService {
|
|
|
12421
12538
|
*
|
|
12422
12539
|
* @param symbol - Trading pair symbol to get data for
|
|
12423
12540
|
* @param strategyName - Strategy name to get data for
|
|
12541
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
12424
12542
|
* @returns Statistical data object with all metrics
|
|
12425
12543
|
*
|
|
12426
12544
|
* @example
|
|
12427
12545
|
* ```typescript
|
|
12428
12546
|
* const service = new PartialMarkdownService();
|
|
12429
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
12547
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
12430
12548
|
* console.log(stats.totalProfit, stats.totalLoss);
|
|
12431
12549
|
* ```
|
|
12432
12550
|
*/
|
|
12433
|
-
this.getData = async (symbol, strategyName) => {
|
|
12551
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
12434
12552
|
this.loggerService.log("partialMarkdownService getData", {
|
|
12435
12553
|
symbol,
|
|
12436
12554
|
strategyName,
|
|
12555
|
+
backtest,
|
|
12437
12556
|
});
|
|
12438
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
12557
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
12439
12558
|
return storage.getData();
|
|
12440
12559
|
};
|
|
12441
12560
|
/**
|
|
@@ -12444,22 +12563,24 @@ class PartialMarkdownService {
|
|
|
12444
12563
|
*
|
|
12445
12564
|
* @param symbol - Trading pair symbol to generate report for
|
|
12446
12565
|
* @param strategyName - Strategy name to generate report for
|
|
12566
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
12447
12567
|
* @param columns - Column configuration for formatting the table
|
|
12448
12568
|
* @returns Markdown formatted report string with table of all events
|
|
12449
12569
|
*
|
|
12450
12570
|
* @example
|
|
12451
12571
|
* ```typescript
|
|
12452
12572
|
* const service = new PartialMarkdownService();
|
|
12453
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
12573
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
12454
12574
|
* console.log(markdown);
|
|
12455
12575
|
* ```
|
|
12456
12576
|
*/
|
|
12457
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.partial_columns) => {
|
|
12577
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.partial_columns) => {
|
|
12458
12578
|
this.loggerService.log("partialMarkdownService getReport", {
|
|
12459
12579
|
symbol,
|
|
12460
12580
|
strategyName,
|
|
12581
|
+
backtest,
|
|
12461
12582
|
});
|
|
12462
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
12583
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
12463
12584
|
return storage.getReport(symbol, strategyName, columns);
|
|
12464
12585
|
};
|
|
12465
12586
|
/**
|
|
@@ -12469,6 +12590,7 @@ class PartialMarkdownService {
|
|
|
12469
12590
|
*
|
|
12470
12591
|
* @param symbol - Trading pair symbol to save report for
|
|
12471
12592
|
* @param strategyName - Strategy name to save report for
|
|
12593
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
12472
12594
|
* @param path - Directory path to save report (default: "./dump/partial")
|
|
12473
12595
|
* @param columns - Column configuration for formatting the table
|
|
12474
12596
|
*
|
|
@@ -12477,45 +12599,48 @@ class PartialMarkdownService {
|
|
|
12477
12599
|
* const service = new PartialMarkdownService();
|
|
12478
12600
|
*
|
|
12479
12601
|
* // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
|
|
12480
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
12602
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
12481
12603
|
*
|
|
12482
12604
|
* // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
|
|
12483
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
12605
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
12484
12606
|
* ```
|
|
12485
12607
|
*/
|
|
12486
|
-
this.dump = async (symbol, strategyName, path = "./dump/partial", columns = COLUMN_CONFIG.partial_columns) => {
|
|
12608
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/partial", columns = COLUMN_CONFIG.partial_columns) => {
|
|
12487
12609
|
this.loggerService.log("partialMarkdownService dump", {
|
|
12488
12610
|
symbol,
|
|
12489
12611
|
strategyName,
|
|
12612
|
+
backtest,
|
|
12490
12613
|
path,
|
|
12491
12614
|
});
|
|
12492
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
12615
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
12493
12616
|
await storage.dump(symbol, strategyName, path, columns);
|
|
12494
12617
|
};
|
|
12495
12618
|
/**
|
|
12496
12619
|
* Clears accumulated event data from storage.
|
|
12497
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
12620
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
12498
12621
|
* If nothing is provided, clears all data.
|
|
12499
12622
|
*
|
|
12623
|
+
* @param backtest - Backtest mode flag
|
|
12500
12624
|
* @param ctx - Optional context with symbol and strategyName
|
|
12501
12625
|
*
|
|
12502
12626
|
* @example
|
|
12503
12627
|
* ```typescript
|
|
12504
12628
|
* const service = new PartialMarkdownService();
|
|
12505
12629
|
*
|
|
12506
|
-
* // Clear specific symbol-strategy
|
|
12507
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
12630
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
12631
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
12508
12632
|
*
|
|
12509
12633
|
* // Clear all data
|
|
12510
12634
|
* await service.clear();
|
|
12511
12635
|
* ```
|
|
12512
12636
|
*/
|
|
12513
|
-
this.clear = async (ctx) => {
|
|
12637
|
+
this.clear = async (backtest, ctx) => {
|
|
12514
12638
|
this.loggerService.log("partialMarkdownService clear", {
|
|
12639
|
+
backtest,
|
|
12515
12640
|
ctx,
|
|
12516
12641
|
});
|
|
12517
12642
|
if (ctx) {
|
|
12518
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
12643
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
12519
12644
|
this.getStorage.clear(key);
|
|
12520
12645
|
}
|
|
12521
12646
|
else {
|
|
@@ -13091,10 +13216,10 @@ class RiskMarkdownService {
|
|
|
13091
13216
|
/** Logger service for debug output */
|
|
13092
13217
|
this.loggerService = inject(TYPES.loggerService);
|
|
13093
13218
|
/**
|
|
13094
|
-
* Memoized function to get or create ReportStorage for a symbol-strategy
|
|
13095
|
-
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
13219
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy-backtest triple.
|
|
13220
|
+
* Each symbol-strategy-backtest combination gets its own isolated storage instance.
|
|
13096
13221
|
*/
|
|
13097
|
-
this.getStorage = memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage());
|
|
13222
|
+
this.getStorage = memoize(([symbol, strategyName, backtest]) => `${symbol}:${strategyName}:${backtest ? "backtest" : "live"}`, () => new ReportStorage());
|
|
13098
13223
|
/**
|
|
13099
13224
|
* Processes risk rejection events and accumulates them.
|
|
13100
13225
|
* Should be called from riskSubject subscription.
|
|
@@ -13111,7 +13236,7 @@ class RiskMarkdownService {
|
|
|
13111
13236
|
this.loggerService.log("riskMarkdownService tickRejection", {
|
|
13112
13237
|
data,
|
|
13113
13238
|
});
|
|
13114
|
-
const storage = this.getStorage(data.symbol, data.strategyName);
|
|
13239
|
+
const storage = this.getStorage(data.symbol, data.strategyName, data.backtest);
|
|
13115
13240
|
storage.addRejectionEvent(data);
|
|
13116
13241
|
};
|
|
13117
13242
|
/**
|
|
@@ -13120,21 +13245,23 @@ class RiskMarkdownService {
|
|
|
13120
13245
|
*
|
|
13121
13246
|
* @param symbol - Trading pair symbol to get data for
|
|
13122
13247
|
* @param strategyName - Strategy name to get data for
|
|
13248
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
13123
13249
|
* @returns Statistical data object with all metrics
|
|
13124
13250
|
*
|
|
13125
13251
|
* @example
|
|
13126
13252
|
* ```typescript
|
|
13127
13253
|
* const service = new RiskMarkdownService();
|
|
13128
|
-
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
13254
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy", false);
|
|
13129
13255
|
* console.log(stats.totalRejections, stats.bySymbol);
|
|
13130
13256
|
* ```
|
|
13131
13257
|
*/
|
|
13132
|
-
this.getData = async (symbol, strategyName) => {
|
|
13258
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
13133
13259
|
this.loggerService.log("riskMarkdownService getData", {
|
|
13134
13260
|
symbol,
|
|
13135
13261
|
strategyName,
|
|
13262
|
+
backtest,
|
|
13136
13263
|
});
|
|
13137
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
13264
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
13138
13265
|
return storage.getData();
|
|
13139
13266
|
};
|
|
13140
13267
|
/**
|
|
@@ -13143,22 +13270,24 @@ class RiskMarkdownService {
|
|
|
13143
13270
|
*
|
|
13144
13271
|
* @param symbol - Trading pair symbol to generate report for
|
|
13145
13272
|
* @param strategyName - Strategy name to generate report for
|
|
13273
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
13146
13274
|
* @param columns - Column configuration for formatting the table
|
|
13147
13275
|
* @returns Markdown formatted report string with table of all events
|
|
13148
13276
|
*
|
|
13149
13277
|
* @example
|
|
13150
13278
|
* ```typescript
|
|
13151
13279
|
* const service = new RiskMarkdownService();
|
|
13152
|
-
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
13280
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy", false);
|
|
13153
13281
|
* console.log(markdown);
|
|
13154
13282
|
* ```
|
|
13155
13283
|
*/
|
|
13156
|
-
this.getReport = async (symbol, strategyName, columns = COLUMN_CONFIG.risk_columns) => {
|
|
13284
|
+
this.getReport = async (symbol, strategyName, backtest, columns = COLUMN_CONFIG.risk_columns) => {
|
|
13157
13285
|
this.loggerService.log("riskMarkdownService getReport", {
|
|
13158
13286
|
symbol,
|
|
13159
13287
|
strategyName,
|
|
13288
|
+
backtest,
|
|
13160
13289
|
});
|
|
13161
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
13290
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
13162
13291
|
return storage.getReport(symbol, strategyName, columns);
|
|
13163
13292
|
};
|
|
13164
13293
|
/**
|
|
@@ -13168,6 +13297,7 @@ class RiskMarkdownService {
|
|
|
13168
13297
|
*
|
|
13169
13298
|
* @param symbol - Trading pair symbol to save report for
|
|
13170
13299
|
* @param strategyName - Strategy name to save report for
|
|
13300
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
13171
13301
|
* @param path - Directory path to save report (default: "./dump/risk")
|
|
13172
13302
|
* @param columns - Column configuration for formatting the table
|
|
13173
13303
|
*
|
|
@@ -13176,45 +13306,48 @@ class RiskMarkdownService {
|
|
|
13176
13306
|
* const service = new RiskMarkdownService();
|
|
13177
13307
|
*
|
|
13178
13308
|
* // Save to default path: ./dump/risk/BTCUSDT_my-strategy.md
|
|
13179
|
-
* await service.dump("BTCUSDT", "my-strategy");
|
|
13309
|
+
* await service.dump("BTCUSDT", "my-strategy", false);
|
|
13180
13310
|
*
|
|
13181
13311
|
* // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
|
|
13182
|
-
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
13312
|
+
* await service.dump("BTCUSDT", "my-strategy", false, "./custom/path");
|
|
13183
13313
|
* ```
|
|
13184
13314
|
*/
|
|
13185
|
-
this.dump = async (symbol, strategyName, path = "./dump/risk", columns = COLUMN_CONFIG.risk_columns) => {
|
|
13315
|
+
this.dump = async (symbol, strategyName, backtest, path = "./dump/risk", columns = COLUMN_CONFIG.risk_columns) => {
|
|
13186
13316
|
this.loggerService.log("riskMarkdownService dump", {
|
|
13187
13317
|
symbol,
|
|
13188
13318
|
strategyName,
|
|
13319
|
+
backtest,
|
|
13189
13320
|
path,
|
|
13190
13321
|
});
|
|
13191
|
-
const storage = this.getStorage(symbol, strategyName);
|
|
13322
|
+
const storage = this.getStorage(symbol, strategyName, backtest);
|
|
13192
13323
|
await storage.dump(symbol, strategyName, path, columns);
|
|
13193
13324
|
};
|
|
13194
13325
|
/**
|
|
13195
13326
|
* Clears accumulated event data from storage.
|
|
13196
|
-
* If ctx is provided, clears only that specific symbol-strategy
|
|
13327
|
+
* If ctx is provided, clears only that specific symbol-strategy-backtest triple's data.
|
|
13197
13328
|
* If nothing is provided, clears all data.
|
|
13198
13329
|
*
|
|
13330
|
+
* @param backtest - Backtest mode flag
|
|
13199
13331
|
* @param ctx - Optional context with symbol and strategyName
|
|
13200
13332
|
*
|
|
13201
13333
|
* @example
|
|
13202
13334
|
* ```typescript
|
|
13203
13335
|
* const service = new RiskMarkdownService();
|
|
13204
13336
|
*
|
|
13205
|
-
* // Clear specific symbol-strategy
|
|
13206
|
-
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
13337
|
+
* // Clear specific symbol-strategy-backtest triple
|
|
13338
|
+
* await service.clear(false, { symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
13207
13339
|
*
|
|
13208
13340
|
* // Clear all data
|
|
13209
13341
|
* await service.clear();
|
|
13210
13342
|
* ```
|
|
13211
13343
|
*/
|
|
13212
|
-
this.clear = async (ctx) => {
|
|
13344
|
+
this.clear = async (backtest, ctx) => {
|
|
13213
13345
|
this.loggerService.log("riskMarkdownService clear", {
|
|
13346
|
+
backtest,
|
|
13214
13347
|
ctx,
|
|
13215
13348
|
});
|
|
13216
13349
|
if (ctx) {
|
|
13217
|
-
const key = `${ctx.symbol}:${ctx.strategyName}`;
|
|
13350
|
+
const key = `${ctx.symbol}:${ctx.strategyName}:${backtest ? "backtest" : "live"}`;
|
|
13218
13351
|
this.getStorage.clear(key);
|
|
13219
13352
|
}
|
|
13220
13353
|
else {
|
|
@@ -13519,7 +13652,7 @@ const backtest = {
|
|
|
13519
13652
|
...templateServices,
|
|
13520
13653
|
};
|
|
13521
13654
|
init();
|
|
13522
|
-
var
|
|
13655
|
+
var bt = backtest;
|
|
13523
13656
|
|
|
13524
13657
|
/**
|
|
13525
13658
|
* Sets custom logger implementation for the framework.
|
|
@@ -13539,7 +13672,7 @@ var backtest$1 = backtest;
|
|
|
13539
13672
|
* ```
|
|
13540
13673
|
*/
|
|
13541
13674
|
function setLogger(logger) {
|
|
13542
|
-
|
|
13675
|
+
bt.loggerService.setLogger(logger);
|
|
13543
13676
|
}
|
|
13544
13677
|
/**
|
|
13545
13678
|
* Sets global configuration parameters for the framework.
|
|
@@ -13557,7 +13690,7 @@ function setConfig(config, _unsafe) {
|
|
|
13557
13690
|
const prevConfig = Object.assign({}, GLOBAL_CONFIG);
|
|
13558
13691
|
try {
|
|
13559
13692
|
Object.assign(GLOBAL_CONFIG, config);
|
|
13560
|
-
!_unsafe &&
|
|
13693
|
+
!_unsafe && bt.configValidationService.validate();
|
|
13561
13694
|
}
|
|
13562
13695
|
catch (error) {
|
|
13563
13696
|
console.warn(`backtest-kit setConfig failed: ${getErrorMessage(error)}`, config);
|
|
@@ -13628,7 +13761,7 @@ function setColumns(columns, _unsafe) {
|
|
|
13628
13761
|
const prevConfig = Object.assign({}, COLUMN_CONFIG);
|
|
13629
13762
|
try {
|
|
13630
13763
|
Object.assign(COLUMN_CONFIG, columns);
|
|
13631
|
-
!_unsafe &&
|
|
13764
|
+
!_unsafe && bt.columnValidationService.validate();
|
|
13632
13765
|
}
|
|
13633
13766
|
catch (error) {
|
|
13634
13767
|
console.warn(`backtest-kit setColumns failed: ${getErrorMessage(error)}`, columns);
|
|
@@ -13713,11 +13846,11 @@ const ADD_OPTIMIZER_METHOD_NAME = "add.addOptimizer";
|
|
|
13713
13846
|
* ```
|
|
13714
13847
|
*/
|
|
13715
13848
|
function addStrategy(strategySchema) {
|
|
13716
|
-
|
|
13849
|
+
bt.loggerService.info(ADD_STRATEGY_METHOD_NAME, {
|
|
13717
13850
|
strategySchema,
|
|
13718
13851
|
});
|
|
13719
|
-
|
|
13720
|
-
|
|
13852
|
+
bt.strategyValidationService.addStrategy(strategySchema.strategyName, strategySchema);
|
|
13853
|
+
bt.strategySchemaService.register(strategySchema.strategyName, strategySchema);
|
|
13721
13854
|
}
|
|
13722
13855
|
/**
|
|
13723
13856
|
* Registers an exchange data source in the framework.
|
|
@@ -13755,11 +13888,11 @@ function addStrategy(strategySchema) {
|
|
|
13755
13888
|
* ```
|
|
13756
13889
|
*/
|
|
13757
13890
|
function addExchange(exchangeSchema) {
|
|
13758
|
-
|
|
13891
|
+
bt.loggerService.info(ADD_EXCHANGE_METHOD_NAME, {
|
|
13759
13892
|
exchangeSchema,
|
|
13760
13893
|
});
|
|
13761
|
-
|
|
13762
|
-
|
|
13894
|
+
bt.exchangeValidationService.addExchange(exchangeSchema.exchangeName, exchangeSchema);
|
|
13895
|
+
bt.exchangeSchemaService.register(exchangeSchema.exchangeName, exchangeSchema);
|
|
13763
13896
|
}
|
|
13764
13897
|
/**
|
|
13765
13898
|
* Registers a timeframe generator for backtesting.
|
|
@@ -13792,11 +13925,11 @@ function addExchange(exchangeSchema) {
|
|
|
13792
13925
|
* ```
|
|
13793
13926
|
*/
|
|
13794
13927
|
function addFrame(frameSchema) {
|
|
13795
|
-
|
|
13928
|
+
bt.loggerService.info(ADD_FRAME_METHOD_NAME, {
|
|
13796
13929
|
frameSchema,
|
|
13797
13930
|
});
|
|
13798
|
-
|
|
13799
|
-
|
|
13931
|
+
bt.frameValidationService.addFrame(frameSchema.frameName, frameSchema);
|
|
13932
|
+
bt.frameSchemaService.register(frameSchema.frameName, frameSchema);
|
|
13800
13933
|
}
|
|
13801
13934
|
/**
|
|
13802
13935
|
* Registers a walker for strategy comparison.
|
|
@@ -13836,11 +13969,11 @@ function addFrame(frameSchema) {
|
|
|
13836
13969
|
* ```
|
|
13837
13970
|
*/
|
|
13838
13971
|
function addWalker(walkerSchema) {
|
|
13839
|
-
|
|
13972
|
+
bt.loggerService.info(ADD_WALKER_METHOD_NAME, {
|
|
13840
13973
|
walkerSchema,
|
|
13841
13974
|
});
|
|
13842
|
-
|
|
13843
|
-
|
|
13975
|
+
bt.walkerValidationService.addWalker(walkerSchema.walkerName, walkerSchema);
|
|
13976
|
+
bt.walkerSchemaService.register(walkerSchema.walkerName, walkerSchema);
|
|
13844
13977
|
}
|
|
13845
13978
|
/**
|
|
13846
13979
|
* Registers a position sizing configuration in the framework.
|
|
@@ -13895,11 +14028,11 @@ function addWalker(walkerSchema) {
|
|
|
13895
14028
|
* ```
|
|
13896
14029
|
*/
|
|
13897
14030
|
function addSizing(sizingSchema) {
|
|
13898
|
-
|
|
14031
|
+
bt.loggerService.info(ADD_SIZING_METHOD_NAME, {
|
|
13899
14032
|
sizingSchema,
|
|
13900
14033
|
});
|
|
13901
|
-
|
|
13902
|
-
|
|
14034
|
+
bt.sizingValidationService.addSizing(sizingSchema.sizingName, sizingSchema);
|
|
14035
|
+
bt.sizingSchemaService.register(sizingSchema.sizingName, sizingSchema);
|
|
13903
14036
|
}
|
|
13904
14037
|
/**
|
|
13905
14038
|
* Registers a risk management configuration in the framework.
|
|
@@ -13963,11 +14096,11 @@ function addSizing(sizingSchema) {
|
|
|
13963
14096
|
* ```
|
|
13964
14097
|
*/
|
|
13965
14098
|
function addRisk(riskSchema) {
|
|
13966
|
-
|
|
14099
|
+
bt.loggerService.info(ADD_RISK_METHOD_NAME, {
|
|
13967
14100
|
riskSchema,
|
|
13968
14101
|
});
|
|
13969
|
-
|
|
13970
|
-
|
|
14102
|
+
bt.riskValidationService.addRisk(riskSchema.riskName, riskSchema);
|
|
14103
|
+
bt.riskSchemaService.register(riskSchema.riskName, riskSchema);
|
|
13971
14104
|
}
|
|
13972
14105
|
/**
|
|
13973
14106
|
* Registers an optimizer configuration in the framework.
|
|
@@ -14057,11 +14190,11 @@ function addRisk(riskSchema) {
|
|
|
14057
14190
|
* ```
|
|
14058
14191
|
*/
|
|
14059
14192
|
function addOptimizer(optimizerSchema) {
|
|
14060
|
-
|
|
14193
|
+
bt.loggerService.info(ADD_OPTIMIZER_METHOD_NAME, {
|
|
14061
14194
|
optimizerSchema,
|
|
14062
14195
|
});
|
|
14063
|
-
|
|
14064
|
-
|
|
14196
|
+
bt.optimizerValidationService.addOptimizer(optimizerSchema.optimizerName, optimizerSchema);
|
|
14197
|
+
bt.optimizerSchemaService.register(optimizerSchema.optimizerName, optimizerSchema);
|
|
14065
14198
|
}
|
|
14066
14199
|
|
|
14067
14200
|
const LIST_EXCHANGES_METHOD_NAME = "list.listExchanges";
|
|
@@ -14097,8 +14230,8 @@ const LIST_OPTIMIZERS_METHOD_NAME = "list.listOptimizers";
|
|
|
14097
14230
|
* ```
|
|
14098
14231
|
*/
|
|
14099
14232
|
async function listExchanges() {
|
|
14100
|
-
|
|
14101
|
-
return await
|
|
14233
|
+
bt.loggerService.log(LIST_EXCHANGES_METHOD_NAME);
|
|
14234
|
+
return await bt.exchangeValidationService.list();
|
|
14102
14235
|
}
|
|
14103
14236
|
/**
|
|
14104
14237
|
* Returns a list of all registered strategy schemas.
|
|
@@ -14131,8 +14264,8 @@ async function listExchanges() {
|
|
|
14131
14264
|
* ```
|
|
14132
14265
|
*/
|
|
14133
14266
|
async function listStrategies() {
|
|
14134
|
-
|
|
14135
|
-
return await
|
|
14267
|
+
bt.loggerService.log(LIST_STRATEGIES_METHOD_NAME);
|
|
14268
|
+
return await bt.strategyValidationService.list();
|
|
14136
14269
|
}
|
|
14137
14270
|
/**
|
|
14138
14271
|
* Returns a list of all registered frame schemas.
|
|
@@ -14160,8 +14293,8 @@ async function listStrategies() {
|
|
|
14160
14293
|
* ```
|
|
14161
14294
|
*/
|
|
14162
14295
|
async function listFrames() {
|
|
14163
|
-
|
|
14164
|
-
return await
|
|
14296
|
+
bt.loggerService.log(LIST_FRAMES_METHOD_NAME);
|
|
14297
|
+
return await bt.frameValidationService.list();
|
|
14165
14298
|
}
|
|
14166
14299
|
/**
|
|
14167
14300
|
* Returns a list of all registered walker schemas.
|
|
@@ -14190,8 +14323,8 @@ async function listFrames() {
|
|
|
14190
14323
|
* ```
|
|
14191
14324
|
*/
|
|
14192
14325
|
async function listWalkers() {
|
|
14193
|
-
|
|
14194
|
-
return await
|
|
14326
|
+
bt.loggerService.log(LIST_WALKERS_METHOD_NAME);
|
|
14327
|
+
return await bt.walkerValidationService.list();
|
|
14195
14328
|
}
|
|
14196
14329
|
/**
|
|
14197
14330
|
* Returns a list of all registered sizing schemas.
|
|
@@ -14229,8 +14362,8 @@ async function listWalkers() {
|
|
|
14229
14362
|
* ```
|
|
14230
14363
|
*/
|
|
14231
14364
|
async function listSizings() {
|
|
14232
|
-
|
|
14233
|
-
return await
|
|
14365
|
+
bt.loggerService.log(LIST_SIZINGS_METHOD_NAME);
|
|
14366
|
+
return await bt.sizingValidationService.list();
|
|
14234
14367
|
}
|
|
14235
14368
|
/**
|
|
14236
14369
|
* Returns a list of all registered risk schemas.
|
|
@@ -14265,8 +14398,8 @@ async function listSizings() {
|
|
|
14265
14398
|
* ```
|
|
14266
14399
|
*/
|
|
14267
14400
|
async function listRisks() {
|
|
14268
|
-
|
|
14269
|
-
return await
|
|
14401
|
+
bt.loggerService.log(LIST_RISKS_METHOD_NAME);
|
|
14402
|
+
return await bt.riskValidationService.list();
|
|
14270
14403
|
}
|
|
14271
14404
|
/**
|
|
14272
14405
|
* Returns a list of all registered optimizer schemas.
|
|
@@ -14305,8 +14438,8 @@ async function listRisks() {
|
|
|
14305
14438
|
* ```
|
|
14306
14439
|
*/
|
|
14307
14440
|
async function listOptimizers() {
|
|
14308
|
-
|
|
14309
|
-
return await
|
|
14441
|
+
bt.loggerService.log(LIST_OPTIMIZERS_METHOD_NAME);
|
|
14442
|
+
return await bt.optimizerValidationService.list();
|
|
14310
14443
|
}
|
|
14311
14444
|
|
|
14312
14445
|
const LISTEN_SIGNAL_METHOD_NAME = "event.listenSignal";
|
|
@@ -14363,7 +14496,7 @@ const LISTEN_RISK_ONCE_METHOD_NAME = "event.listenRiskOnce";
|
|
|
14363
14496
|
* ```
|
|
14364
14497
|
*/
|
|
14365
14498
|
function listenSignal(fn) {
|
|
14366
|
-
|
|
14499
|
+
bt.loggerService.log(LISTEN_SIGNAL_METHOD_NAME);
|
|
14367
14500
|
return signalEmitter.subscribe(queued(async (event) => fn(event)));
|
|
14368
14501
|
}
|
|
14369
14502
|
/**
|
|
@@ -14399,7 +14532,7 @@ function listenSignal(fn) {
|
|
|
14399
14532
|
* ```
|
|
14400
14533
|
*/
|
|
14401
14534
|
function listenSignalOnce(filterFn, fn) {
|
|
14402
|
-
|
|
14535
|
+
bt.loggerService.log(LISTEN_SIGNAL_ONCE_METHOD_NAME);
|
|
14403
14536
|
return signalEmitter.filter(filterFn).once(fn);
|
|
14404
14537
|
}
|
|
14405
14538
|
/**
|
|
@@ -14423,7 +14556,7 @@ function listenSignalOnce(filterFn, fn) {
|
|
|
14423
14556
|
* ```
|
|
14424
14557
|
*/
|
|
14425
14558
|
function listenSignalLive(fn) {
|
|
14426
|
-
|
|
14559
|
+
bt.loggerService.log(LISTEN_SIGNAL_LIVE_METHOD_NAME);
|
|
14427
14560
|
return signalLiveEmitter.subscribe(queued(async (event) => fn(event)));
|
|
14428
14561
|
}
|
|
14429
14562
|
/**
|
|
@@ -14448,7 +14581,7 @@ function listenSignalLive(fn) {
|
|
|
14448
14581
|
* ```
|
|
14449
14582
|
*/
|
|
14450
14583
|
function listenSignalLiveOnce(filterFn, fn) {
|
|
14451
|
-
|
|
14584
|
+
bt.loggerService.log(LISTEN_SIGNAL_LIVE_ONCE_METHOD_NAME);
|
|
14452
14585
|
return signalLiveEmitter.filter(filterFn).once(fn);
|
|
14453
14586
|
}
|
|
14454
14587
|
/**
|
|
@@ -14472,7 +14605,7 @@ function listenSignalLiveOnce(filterFn, fn) {
|
|
|
14472
14605
|
* ```
|
|
14473
14606
|
*/
|
|
14474
14607
|
function listenSignalBacktest(fn) {
|
|
14475
|
-
|
|
14608
|
+
bt.loggerService.log(LISTEN_SIGNAL_BACKTEST_METHOD_NAME);
|
|
14476
14609
|
return signalBacktestEmitter.subscribe(queued(async (event) => fn(event)));
|
|
14477
14610
|
}
|
|
14478
14611
|
/**
|
|
@@ -14497,7 +14630,7 @@ function listenSignalBacktest(fn) {
|
|
|
14497
14630
|
* ```
|
|
14498
14631
|
*/
|
|
14499
14632
|
function listenSignalBacktestOnce(filterFn, fn) {
|
|
14500
|
-
|
|
14633
|
+
bt.loggerService.log(LISTEN_SIGNAL_BACKTEST_ONCE_METHOD_NAME);
|
|
14501
14634
|
return signalBacktestEmitter.filter(filterFn).once(fn);
|
|
14502
14635
|
}
|
|
14503
14636
|
/**
|
|
@@ -14525,7 +14658,7 @@ function listenSignalBacktestOnce(filterFn, fn) {
|
|
|
14525
14658
|
* ```
|
|
14526
14659
|
*/
|
|
14527
14660
|
function listenError(fn) {
|
|
14528
|
-
|
|
14661
|
+
bt.loggerService.log(LISTEN_ERROR_METHOD_NAME);
|
|
14529
14662
|
return errorEmitter.subscribe(queued(async (error) => fn(error)));
|
|
14530
14663
|
}
|
|
14531
14664
|
/**
|
|
@@ -14553,7 +14686,7 @@ function listenError(fn) {
|
|
|
14553
14686
|
* ```
|
|
14554
14687
|
*/
|
|
14555
14688
|
function listenExit(fn) {
|
|
14556
|
-
|
|
14689
|
+
bt.loggerService.log(LISTEN_EXIT_METHOD_NAME);
|
|
14557
14690
|
return exitEmitter.subscribe(queued(async (error) => fn(error)));
|
|
14558
14691
|
}
|
|
14559
14692
|
/**
|
|
@@ -14584,7 +14717,7 @@ function listenExit(fn) {
|
|
|
14584
14717
|
* ```
|
|
14585
14718
|
*/
|
|
14586
14719
|
function listenDoneLive(fn) {
|
|
14587
|
-
|
|
14720
|
+
bt.loggerService.log(LISTEN_DONE_LIVE_METHOD_NAME);
|
|
14588
14721
|
return doneLiveSubject.subscribe(queued(async (event) => fn(event)));
|
|
14589
14722
|
}
|
|
14590
14723
|
/**
|
|
@@ -14614,7 +14747,7 @@ function listenDoneLive(fn) {
|
|
|
14614
14747
|
* ```
|
|
14615
14748
|
*/
|
|
14616
14749
|
function listenDoneLiveOnce(filterFn, fn) {
|
|
14617
|
-
|
|
14750
|
+
bt.loggerService.log(LISTEN_DONE_LIVE_ONCE_METHOD_NAME);
|
|
14618
14751
|
return doneLiveSubject.filter(filterFn).once(fn);
|
|
14619
14752
|
}
|
|
14620
14753
|
/**
|
|
@@ -14646,7 +14779,7 @@ function listenDoneLiveOnce(filterFn, fn) {
|
|
|
14646
14779
|
* ```
|
|
14647
14780
|
*/
|
|
14648
14781
|
function listenDoneBacktest(fn) {
|
|
14649
|
-
|
|
14782
|
+
bt.loggerService.log(LISTEN_DONE_BACKTEST_METHOD_NAME);
|
|
14650
14783
|
return doneBacktestSubject.subscribe(queued(async (event) => fn(event)));
|
|
14651
14784
|
}
|
|
14652
14785
|
/**
|
|
@@ -14677,7 +14810,7 @@ function listenDoneBacktest(fn) {
|
|
|
14677
14810
|
* ```
|
|
14678
14811
|
*/
|
|
14679
14812
|
function listenDoneBacktestOnce(filterFn, fn) {
|
|
14680
|
-
|
|
14813
|
+
bt.loggerService.log(LISTEN_DONE_BACKTEST_ONCE_METHOD_NAME);
|
|
14681
14814
|
return doneBacktestSubject.filter(filterFn).once(fn);
|
|
14682
14815
|
}
|
|
14683
14816
|
/**
|
|
@@ -14707,7 +14840,7 @@ function listenDoneBacktestOnce(filterFn, fn) {
|
|
|
14707
14840
|
* ```
|
|
14708
14841
|
*/
|
|
14709
14842
|
function listenDoneWalker(fn) {
|
|
14710
|
-
|
|
14843
|
+
bt.loggerService.log(LISTEN_DONE_WALKER_METHOD_NAME);
|
|
14711
14844
|
return doneWalkerSubject.subscribe(queued(async (event) => fn(event)));
|
|
14712
14845
|
}
|
|
14713
14846
|
/**
|
|
@@ -14736,7 +14869,7 @@ function listenDoneWalker(fn) {
|
|
|
14736
14869
|
* ```
|
|
14737
14870
|
*/
|
|
14738
14871
|
function listenDoneWalkerOnce(filterFn, fn) {
|
|
14739
|
-
|
|
14872
|
+
bt.loggerService.log(LISTEN_DONE_WALKER_ONCE_METHOD_NAME);
|
|
14740
14873
|
return doneWalkerSubject.filter(filterFn).once(fn);
|
|
14741
14874
|
}
|
|
14742
14875
|
/**
|
|
@@ -14770,7 +14903,7 @@ function listenDoneWalkerOnce(filterFn, fn) {
|
|
|
14770
14903
|
* ```
|
|
14771
14904
|
*/
|
|
14772
14905
|
function listenBacktestProgress(fn) {
|
|
14773
|
-
|
|
14906
|
+
bt.loggerService.log(LISTEN_PROGRESS_METHOD_NAME);
|
|
14774
14907
|
return progressBacktestEmitter.subscribe(queued(async (event) => fn(event)));
|
|
14775
14908
|
}
|
|
14776
14909
|
/**
|
|
@@ -14804,7 +14937,7 @@ function listenBacktestProgress(fn) {
|
|
|
14804
14937
|
* ```
|
|
14805
14938
|
*/
|
|
14806
14939
|
function listenWalkerProgress(fn) {
|
|
14807
|
-
|
|
14940
|
+
bt.loggerService.log(LISTEN_PROGRESS_WALKER_METHOD_NAME);
|
|
14808
14941
|
return progressWalkerEmitter.subscribe(queued(async (event) => fn(event)));
|
|
14809
14942
|
}
|
|
14810
14943
|
/**
|
|
@@ -14832,7 +14965,7 @@ function listenWalkerProgress(fn) {
|
|
|
14832
14965
|
* ```
|
|
14833
14966
|
*/
|
|
14834
14967
|
function listenOptimizerProgress(fn) {
|
|
14835
|
-
|
|
14968
|
+
bt.loggerService.log(LISTEN_PROGRESS_OPTIMIZER_METHOD_NAME);
|
|
14836
14969
|
return progressOptimizerEmitter.subscribe(queued(async (event) => fn(event)));
|
|
14837
14970
|
}
|
|
14838
14971
|
/**
|
|
@@ -14868,7 +15001,7 @@ function listenOptimizerProgress(fn) {
|
|
|
14868
15001
|
* ```
|
|
14869
15002
|
*/
|
|
14870
15003
|
function listenPerformance(fn) {
|
|
14871
|
-
|
|
15004
|
+
bt.loggerService.log(LISTEN_PERFORMANCE_METHOD_NAME);
|
|
14872
15005
|
return performanceEmitter.subscribe(queued(async (event) => fn(event)));
|
|
14873
15006
|
}
|
|
14874
15007
|
/**
|
|
@@ -14902,7 +15035,7 @@ function listenPerformance(fn) {
|
|
|
14902
15035
|
* ```
|
|
14903
15036
|
*/
|
|
14904
15037
|
function listenWalker(fn) {
|
|
14905
|
-
|
|
15038
|
+
bt.loggerService.log(LISTEN_WALKER_METHOD_NAME);
|
|
14906
15039
|
return walkerEmitter.subscribe(queued(async (event) => fn(event)));
|
|
14907
15040
|
}
|
|
14908
15041
|
/**
|
|
@@ -14945,7 +15078,7 @@ function listenWalker(fn) {
|
|
|
14945
15078
|
* ```
|
|
14946
15079
|
*/
|
|
14947
15080
|
function listenWalkerOnce(filterFn, fn) {
|
|
14948
|
-
|
|
15081
|
+
bt.loggerService.log(LISTEN_WALKER_ONCE_METHOD_NAME);
|
|
14949
15082
|
return walkerEmitter.filter(filterFn).once(fn);
|
|
14950
15083
|
}
|
|
14951
15084
|
/**
|
|
@@ -14980,7 +15113,7 @@ function listenWalkerOnce(filterFn, fn) {
|
|
|
14980
15113
|
* ```
|
|
14981
15114
|
*/
|
|
14982
15115
|
function listenWalkerComplete(fn) {
|
|
14983
|
-
|
|
15116
|
+
bt.loggerService.log(LISTEN_WALKER_COMPLETE_METHOD_NAME);
|
|
14984
15117
|
return walkerCompleteSubject.subscribe(queued(async (event) => fn(event)));
|
|
14985
15118
|
}
|
|
14986
15119
|
/**
|
|
@@ -15008,7 +15141,7 @@ function listenWalkerComplete(fn) {
|
|
|
15008
15141
|
* ```
|
|
15009
15142
|
*/
|
|
15010
15143
|
function listenValidation(fn) {
|
|
15011
|
-
|
|
15144
|
+
bt.loggerService.log(LISTEN_VALIDATION_METHOD_NAME);
|
|
15012
15145
|
return validationSubject.subscribe(queued(async (error) => fn(error)));
|
|
15013
15146
|
}
|
|
15014
15147
|
/**
|
|
@@ -15036,7 +15169,7 @@ function listenValidation(fn) {
|
|
|
15036
15169
|
* ```
|
|
15037
15170
|
*/
|
|
15038
15171
|
function listenPartialProfit(fn) {
|
|
15039
|
-
|
|
15172
|
+
bt.loggerService.log(LISTEN_PARTIAL_PROFIT_METHOD_NAME);
|
|
15040
15173
|
return partialProfitSubject.subscribe(queued(async (event) => fn(event)));
|
|
15041
15174
|
}
|
|
15042
15175
|
/**
|
|
@@ -15070,7 +15203,7 @@ function listenPartialProfit(fn) {
|
|
|
15070
15203
|
* ```
|
|
15071
15204
|
*/
|
|
15072
15205
|
function listenPartialProfitOnce(filterFn, fn) {
|
|
15073
|
-
|
|
15206
|
+
bt.loggerService.log(LISTEN_PARTIAL_PROFIT_ONCE_METHOD_NAME);
|
|
15074
15207
|
return partialProfitSubject.filter(filterFn).once(fn);
|
|
15075
15208
|
}
|
|
15076
15209
|
/**
|
|
@@ -15098,7 +15231,7 @@ function listenPartialProfitOnce(filterFn, fn) {
|
|
|
15098
15231
|
* ```
|
|
15099
15232
|
*/
|
|
15100
15233
|
function listenPartialLoss(fn) {
|
|
15101
|
-
|
|
15234
|
+
bt.loggerService.log(LISTEN_PARTIAL_LOSS_METHOD_NAME);
|
|
15102
15235
|
return partialLossSubject.subscribe(queued(async (event) => fn(event)));
|
|
15103
15236
|
}
|
|
15104
15237
|
/**
|
|
@@ -15132,7 +15265,7 @@ function listenPartialLoss(fn) {
|
|
|
15132
15265
|
* ```
|
|
15133
15266
|
*/
|
|
15134
15267
|
function listenPartialLossOnce(filterFn, fn) {
|
|
15135
|
-
|
|
15268
|
+
bt.loggerService.log(LISTEN_PARTIAL_LOSS_ONCE_METHOD_NAME);
|
|
15136
15269
|
return partialLossSubject.filter(filterFn).once(fn);
|
|
15137
15270
|
}
|
|
15138
15271
|
/**
|
|
@@ -15164,7 +15297,7 @@ function listenPartialLossOnce(filterFn, fn) {
|
|
|
15164
15297
|
* ```
|
|
15165
15298
|
*/
|
|
15166
15299
|
function listenRisk(fn) {
|
|
15167
|
-
|
|
15300
|
+
bt.loggerService.log(LISTEN_RISK_METHOD_NAME);
|
|
15168
15301
|
return riskSubject.subscribe(queued(async (event) => fn(event)));
|
|
15169
15302
|
}
|
|
15170
15303
|
/**
|
|
@@ -15201,7 +15334,7 @@ function listenRisk(fn) {
|
|
|
15201
15334
|
* ```
|
|
15202
15335
|
*/
|
|
15203
15336
|
function listenRiskOnce(filterFn, fn) {
|
|
15204
|
-
|
|
15337
|
+
bt.loggerService.log(LISTEN_RISK_ONCE_METHOD_NAME);
|
|
15205
15338
|
return riskSubject.filter(filterFn).once(fn);
|
|
15206
15339
|
}
|
|
15207
15340
|
|
|
@@ -15229,12 +15362,12 @@ const GET_MODE_METHOD_NAME = "exchange.getMode";
|
|
|
15229
15362
|
* ```
|
|
15230
15363
|
*/
|
|
15231
15364
|
async function getCandles(symbol, interval, limit) {
|
|
15232
|
-
|
|
15365
|
+
bt.loggerService.info(GET_CANDLES_METHOD_NAME, {
|
|
15233
15366
|
symbol,
|
|
15234
15367
|
interval,
|
|
15235
15368
|
limit,
|
|
15236
15369
|
});
|
|
15237
|
-
return await
|
|
15370
|
+
return await bt.exchangeConnectionService.getCandles(symbol, interval, limit);
|
|
15238
15371
|
}
|
|
15239
15372
|
/**
|
|
15240
15373
|
* Calculates VWAP (Volume Weighted Average Price) for a symbol.
|
|
@@ -15255,10 +15388,10 @@ async function getCandles(symbol, interval, limit) {
|
|
|
15255
15388
|
* ```
|
|
15256
15389
|
*/
|
|
15257
15390
|
async function getAveragePrice(symbol) {
|
|
15258
|
-
|
|
15391
|
+
bt.loggerService.info(GET_AVERAGE_PRICE_METHOD_NAME, {
|
|
15259
15392
|
symbol,
|
|
15260
15393
|
});
|
|
15261
|
-
return await
|
|
15394
|
+
return await bt.exchangeConnectionService.getAveragePrice(symbol);
|
|
15262
15395
|
}
|
|
15263
15396
|
/**
|
|
15264
15397
|
* Formats a price value according to exchange rules.
|
|
@@ -15276,11 +15409,11 @@ async function getAveragePrice(symbol) {
|
|
|
15276
15409
|
* ```
|
|
15277
15410
|
*/
|
|
15278
15411
|
async function formatPrice(symbol, price) {
|
|
15279
|
-
|
|
15412
|
+
bt.loggerService.info(FORMAT_PRICE_METHOD_NAME, {
|
|
15280
15413
|
symbol,
|
|
15281
15414
|
price,
|
|
15282
15415
|
});
|
|
15283
|
-
return await
|
|
15416
|
+
return await bt.exchangeConnectionService.formatPrice(symbol, price);
|
|
15284
15417
|
}
|
|
15285
15418
|
/**
|
|
15286
15419
|
* Formats a quantity value according to exchange rules.
|
|
@@ -15298,11 +15431,11 @@ async function formatPrice(symbol, price) {
|
|
|
15298
15431
|
* ```
|
|
15299
15432
|
*/
|
|
15300
15433
|
async function formatQuantity(symbol, quantity) {
|
|
15301
|
-
|
|
15434
|
+
bt.loggerService.info(FORMAT_QUANTITY_METHOD_NAME, {
|
|
15302
15435
|
symbol,
|
|
15303
15436
|
quantity,
|
|
15304
15437
|
});
|
|
15305
|
-
return await
|
|
15438
|
+
return await bt.exchangeConnectionService.formatQuantity(symbol, quantity);
|
|
15306
15439
|
}
|
|
15307
15440
|
/**
|
|
15308
15441
|
* Gets the current date from execution context.
|
|
@@ -15319,8 +15452,8 @@ async function formatQuantity(symbol, quantity) {
|
|
|
15319
15452
|
* ```
|
|
15320
15453
|
*/
|
|
15321
15454
|
async function getDate() {
|
|
15322
|
-
|
|
15323
|
-
const { when } =
|
|
15455
|
+
bt.loggerService.info(GET_DATE_METHOD_NAME);
|
|
15456
|
+
const { when } = bt.executionContextService.context;
|
|
15324
15457
|
return new Date(when.getTime());
|
|
15325
15458
|
}
|
|
15326
15459
|
/**
|
|
@@ -15339,9 +15472,9 @@ async function getDate() {
|
|
|
15339
15472
|
* ```
|
|
15340
15473
|
*/
|
|
15341
15474
|
async function getMode() {
|
|
15342
|
-
|
|
15343
|
-
const { backtest: bt } =
|
|
15344
|
-
return bt ? "backtest" : "live";
|
|
15475
|
+
bt.loggerService.info(GET_MODE_METHOD_NAME);
|
|
15476
|
+
const { backtest: bt$1 } = bt.executionContextService.context;
|
|
15477
|
+
return bt$1 ? "backtest" : "live";
|
|
15345
15478
|
}
|
|
15346
15479
|
|
|
15347
15480
|
const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
|
|
@@ -15412,13 +15545,13 @@ const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
|
|
|
15412
15545
|
* ```
|
|
15413
15546
|
*/
|
|
15414
15547
|
async function dumpSignal(signalId, history, signal, outputDir = "./dump/strategy") {
|
|
15415
|
-
|
|
15548
|
+
bt.loggerService.info(DUMP_SIGNAL_METHOD_NAME, {
|
|
15416
15549
|
signalId,
|
|
15417
15550
|
history,
|
|
15418
15551
|
signal,
|
|
15419
15552
|
outputDir,
|
|
15420
15553
|
});
|
|
15421
|
-
return await
|
|
15554
|
+
return await bt.outlineMarkdownService.dumpSignal(signalId, history, signal, outputDir);
|
|
15422
15555
|
}
|
|
15423
15556
|
|
|
15424
15557
|
const BACKTEST_METHOD_NAME_RUN = "BacktestUtils.run";
|
|
@@ -15505,7 +15638,7 @@ class BacktestInstance {
|
|
|
15505
15638
|
* @internal
|
|
15506
15639
|
*/
|
|
15507
15640
|
this.task = singlerun(async (symbol, context) => {
|
|
15508
|
-
|
|
15641
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_TASK, {
|
|
15509
15642
|
symbol,
|
|
15510
15643
|
context,
|
|
15511
15644
|
});
|
|
@@ -15524,7 +15657,7 @@ class BacktestInstance {
|
|
|
15524
15657
|
* ```
|
|
15525
15658
|
*/
|
|
15526
15659
|
this.getStatus = async () => {
|
|
15527
|
-
|
|
15660
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_GET_STATUS);
|
|
15528
15661
|
return {
|
|
15529
15662
|
id: this.id,
|
|
15530
15663
|
symbol: this.symbol,
|
|
@@ -15540,23 +15673,27 @@ class BacktestInstance {
|
|
|
15540
15673
|
* @returns Async generator yielding closed signals with PNL
|
|
15541
15674
|
*/
|
|
15542
15675
|
this.run = (symbol, context) => {
|
|
15543
|
-
|
|
15676
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_RUN, {
|
|
15544
15677
|
symbol,
|
|
15545
15678
|
context,
|
|
15546
15679
|
});
|
|
15547
15680
|
{
|
|
15548
|
-
|
|
15549
|
-
|
|
15681
|
+
bt.backtestMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15682
|
+
bt.liveMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15683
|
+
bt.scheduleMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15684
|
+
bt.performanceMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15685
|
+
bt.partialMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15686
|
+
bt.riskMarkdownService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15550
15687
|
}
|
|
15551
15688
|
{
|
|
15552
|
-
|
|
15689
|
+
bt.strategyCoreService.clear(true, { symbol, strategyName: context.strategyName });
|
|
15553
15690
|
}
|
|
15554
15691
|
{
|
|
15555
|
-
const { riskName, riskList } =
|
|
15556
|
-
riskName &&
|
|
15557
|
-
riskList && riskList.forEach((riskName) =>
|
|
15692
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
15693
|
+
riskName && bt.riskGlobalService.clear(true, riskName);
|
|
15694
|
+
riskList && riskList.forEach((riskName) => bt.riskGlobalService.clear(true, riskName));
|
|
15558
15695
|
}
|
|
15559
|
-
return
|
|
15696
|
+
return bt.backtestCommandService.run(symbol, context);
|
|
15560
15697
|
};
|
|
15561
15698
|
/**
|
|
15562
15699
|
* Runs backtest in background without yielding results.
|
|
@@ -15579,15 +15716,24 @@ class BacktestInstance {
|
|
|
15579
15716
|
* ```
|
|
15580
15717
|
*/
|
|
15581
15718
|
this.background = (symbol, context) => {
|
|
15582
|
-
|
|
15719
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_BACKGROUND, {
|
|
15583
15720
|
symbol,
|
|
15584
15721
|
context,
|
|
15585
15722
|
});
|
|
15723
|
+
{
|
|
15724
|
+
const currentStatus = this.task.getStatus();
|
|
15725
|
+
if (currentStatus === "pending") {
|
|
15726
|
+
throw new Error(`Backtest.background is already running for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName} frameName=${context.frameName}`);
|
|
15727
|
+
}
|
|
15728
|
+
if (currentStatus === "rejected") {
|
|
15729
|
+
throw new Error(`Backtest.background has failed for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName} frameName=${context.frameName}`);
|
|
15730
|
+
}
|
|
15731
|
+
}
|
|
15586
15732
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(getErrorMessage(error))));
|
|
15587
15733
|
return () => {
|
|
15588
|
-
|
|
15589
|
-
|
|
15590
|
-
.getPendingSignal(symbol, context.strategyName)
|
|
15734
|
+
bt.strategyCoreService.stop(true, { symbol, strategyName: context.strategyName });
|
|
15735
|
+
bt.strategyCoreService
|
|
15736
|
+
.getPendingSignal(true, symbol, context.strategyName)
|
|
15591
15737
|
.then(async (pendingSignal) => {
|
|
15592
15738
|
if (pendingSignal) {
|
|
15593
15739
|
return;
|
|
@@ -15623,11 +15769,11 @@ class BacktestInstance {
|
|
|
15623
15769
|
* ```
|
|
15624
15770
|
*/
|
|
15625
15771
|
this.stop = async (symbol, strategyName) => {
|
|
15626
|
-
|
|
15772
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_STOP, {
|
|
15627
15773
|
symbol,
|
|
15628
15774
|
strategyName,
|
|
15629
15775
|
});
|
|
15630
|
-
await
|
|
15776
|
+
await bt.strategyCoreService.stop(true, { symbol, strategyName });
|
|
15631
15777
|
};
|
|
15632
15778
|
/**
|
|
15633
15779
|
* Gets statistical data from all closed signals for a symbol-strategy pair.
|
|
@@ -15644,11 +15790,11 @@ class BacktestInstance {
|
|
|
15644
15790
|
* ```
|
|
15645
15791
|
*/
|
|
15646
15792
|
this.getData = async (symbol, strategyName) => {
|
|
15647
|
-
|
|
15793
|
+
bt.loggerService.info("BacktestUtils.getData", {
|
|
15648
15794
|
symbol,
|
|
15649
15795
|
strategyName,
|
|
15650
15796
|
});
|
|
15651
|
-
return await
|
|
15797
|
+
return await bt.backtestMarkdownService.getData(symbol, strategyName, true);
|
|
15652
15798
|
};
|
|
15653
15799
|
/**
|
|
15654
15800
|
* Generates markdown report with all closed signals for a symbol-strategy pair.
|
|
@@ -15666,11 +15812,11 @@ class BacktestInstance {
|
|
|
15666
15812
|
* ```
|
|
15667
15813
|
*/
|
|
15668
15814
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
15669
|
-
|
|
15815
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_GET_REPORT, {
|
|
15670
15816
|
symbol,
|
|
15671
15817
|
strategyName,
|
|
15672
15818
|
});
|
|
15673
|
-
return await
|
|
15819
|
+
return await bt.backtestMarkdownService.getReport(symbol, strategyName, true, columns);
|
|
15674
15820
|
};
|
|
15675
15821
|
/**
|
|
15676
15822
|
* Saves strategy report to disk.
|
|
@@ -15691,12 +15837,12 @@ class BacktestInstance {
|
|
|
15691
15837
|
* ```
|
|
15692
15838
|
*/
|
|
15693
15839
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
15694
|
-
|
|
15840
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_DUMP, {
|
|
15695
15841
|
symbol,
|
|
15696
15842
|
strategyName,
|
|
15697
15843
|
path,
|
|
15698
15844
|
});
|
|
15699
|
-
await
|
|
15845
|
+
await bt.backtestMarkdownService.dump(symbol, strategyName, true, path, columns);
|
|
15700
15846
|
};
|
|
15701
15847
|
}
|
|
15702
15848
|
}
|
|
@@ -15735,14 +15881,14 @@ class BacktestUtils {
|
|
|
15735
15881
|
*/
|
|
15736
15882
|
this.run = (symbol, context) => {
|
|
15737
15883
|
{
|
|
15738
|
-
|
|
15739
|
-
|
|
15740
|
-
|
|
15884
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_RUN);
|
|
15885
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_RUN);
|
|
15886
|
+
bt.frameValidationService.validate(context.frameName, BACKTEST_METHOD_NAME_RUN);
|
|
15741
15887
|
}
|
|
15742
15888
|
{
|
|
15743
|
-
const { riskName, riskList } =
|
|
15744
|
-
riskName &&
|
|
15745
|
-
riskList && riskList.forEach((riskName) =>
|
|
15889
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
15890
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_RUN);
|
|
15891
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_RUN));
|
|
15746
15892
|
}
|
|
15747
15893
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
15748
15894
|
return instance.run(symbol, context);
|
|
@@ -15769,13 +15915,13 @@ class BacktestUtils {
|
|
|
15769
15915
|
* ```
|
|
15770
15916
|
*/
|
|
15771
15917
|
this.background = (symbol, context) => {
|
|
15772
|
-
|
|
15773
|
-
|
|
15774
|
-
|
|
15918
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15919
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15920
|
+
bt.frameValidationService.validate(context.frameName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15775
15921
|
{
|
|
15776
|
-
const { riskName, riskList } =
|
|
15777
|
-
riskName &&
|
|
15778
|
-
riskList && riskList.forEach((riskName) =>
|
|
15922
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
15923
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BACKGROUND);
|
|
15924
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_BACKGROUND));
|
|
15779
15925
|
}
|
|
15780
15926
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
15781
15927
|
return instance.background(symbol, context);
|
|
@@ -15798,11 +15944,11 @@ class BacktestUtils {
|
|
|
15798
15944
|
* ```
|
|
15799
15945
|
*/
|
|
15800
15946
|
this.stop = async (symbol, strategyName) => {
|
|
15801
|
-
|
|
15947
|
+
bt.strategyValidationService.validate(strategyName, BACKTEST_METHOD_NAME_STOP);
|
|
15802
15948
|
{
|
|
15803
|
-
const { riskName, riskList } =
|
|
15804
|
-
riskName &&
|
|
15805
|
-
riskList && riskList.forEach((riskName) =>
|
|
15949
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
15950
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_STOP);
|
|
15951
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_STOP));
|
|
15806
15952
|
}
|
|
15807
15953
|
const instance = this._getInstance(symbol, strategyName);
|
|
15808
15954
|
return await instance.stop(symbol, strategyName);
|
|
@@ -15821,11 +15967,11 @@ class BacktestUtils {
|
|
|
15821
15967
|
* ```
|
|
15822
15968
|
*/
|
|
15823
15969
|
this.getData = async (symbol, strategyName) => {
|
|
15824
|
-
|
|
15970
|
+
bt.strategyValidationService.validate(strategyName, "BacktestUtils.getData");
|
|
15825
15971
|
{
|
|
15826
|
-
const { riskName, riskList } =
|
|
15827
|
-
riskName &&
|
|
15828
|
-
riskList && riskList.forEach((riskName) =>
|
|
15972
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
15973
|
+
riskName && bt.riskValidationService.validate(riskName, "BacktestUtils.getData");
|
|
15974
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, "BacktestUtils.getData"));
|
|
15829
15975
|
}
|
|
15830
15976
|
const instance = this._getInstance(symbol, strategyName);
|
|
15831
15977
|
return await instance.getData(symbol, strategyName);
|
|
@@ -15845,11 +15991,11 @@ class BacktestUtils {
|
|
|
15845
15991
|
* ```
|
|
15846
15992
|
*/
|
|
15847
15993
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
15848
|
-
|
|
15994
|
+
bt.strategyValidationService.validate(strategyName, BACKTEST_METHOD_NAME_GET_REPORT);
|
|
15849
15995
|
{
|
|
15850
|
-
const { riskName, riskList } =
|
|
15851
|
-
riskName &&
|
|
15852
|
-
riskList && riskList.forEach((riskName) =>
|
|
15996
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
15997
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_REPORT);
|
|
15998
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_REPORT));
|
|
15853
15999
|
}
|
|
15854
16000
|
const instance = this._getInstance(symbol, strategyName);
|
|
15855
16001
|
return await instance.getReport(symbol, strategyName, columns);
|
|
@@ -15872,11 +16018,11 @@ class BacktestUtils {
|
|
|
15872
16018
|
* ```
|
|
15873
16019
|
*/
|
|
15874
16020
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
15875
|
-
|
|
16021
|
+
bt.strategyValidationService.validate(strategyName, BACKTEST_METHOD_NAME_DUMP);
|
|
15876
16022
|
{
|
|
15877
|
-
const { riskName, riskList } =
|
|
15878
|
-
riskName &&
|
|
15879
|
-
riskList && riskList.forEach((riskName) =>
|
|
16023
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16024
|
+
riskName && bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_DUMP);
|
|
16025
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_DUMP));
|
|
15880
16026
|
}
|
|
15881
16027
|
const instance = this._getInstance(symbol, strategyName);
|
|
15882
16028
|
return await instance.dump(symbol, strategyName, path, columns);
|
|
@@ -16006,7 +16152,7 @@ class LiveInstance {
|
|
|
16006
16152
|
* @internal
|
|
16007
16153
|
*/
|
|
16008
16154
|
this.task = singlerun(async (symbol, context) => {
|
|
16009
|
-
|
|
16155
|
+
bt.loggerService.info(LIVE_METHOD_NAME_TASK, {
|
|
16010
16156
|
symbol,
|
|
16011
16157
|
context,
|
|
16012
16158
|
});
|
|
@@ -16025,7 +16171,7 @@ class LiveInstance {
|
|
|
16025
16171
|
* ```
|
|
16026
16172
|
*/
|
|
16027
16173
|
this.getStatus = async () => {
|
|
16028
|
-
|
|
16174
|
+
bt.loggerService.info(LIVE_METHOD_NAME_GET_STATUS);
|
|
16029
16175
|
return {
|
|
16030
16176
|
id: this.id,
|
|
16031
16177
|
symbol: this.symbol,
|
|
@@ -16044,23 +16190,27 @@ class LiveInstance {
|
|
|
16044
16190
|
* @returns Infinite async generator yielding opened and closed signals
|
|
16045
16191
|
*/
|
|
16046
16192
|
this.run = (symbol, context) => {
|
|
16047
|
-
|
|
16193
|
+
bt.loggerService.info(LIVE_METHOD_NAME_RUN, {
|
|
16048
16194
|
symbol,
|
|
16049
16195
|
context,
|
|
16050
16196
|
});
|
|
16051
16197
|
{
|
|
16052
|
-
|
|
16053
|
-
|
|
16198
|
+
bt.backtestMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16199
|
+
bt.liveMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16200
|
+
bt.scheduleMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16201
|
+
bt.performanceMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16202
|
+
bt.partialMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16203
|
+
bt.riskMarkdownService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16054
16204
|
}
|
|
16055
16205
|
{
|
|
16056
|
-
|
|
16206
|
+
bt.strategyCoreService.clear(false, { symbol, strategyName: context.strategyName });
|
|
16057
16207
|
}
|
|
16058
16208
|
{
|
|
16059
|
-
const { riskName, riskList } =
|
|
16060
|
-
riskName &&
|
|
16061
|
-
riskList && riskList.forEach((riskName) =>
|
|
16209
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
16210
|
+
riskName && bt.riskGlobalService.clear(false, riskName);
|
|
16211
|
+
riskList && riskList.forEach((riskName) => bt.riskGlobalService.clear(false, riskName));
|
|
16062
16212
|
}
|
|
16063
|
-
return
|
|
16213
|
+
return bt.liveCommandService.run(symbol, context);
|
|
16064
16214
|
};
|
|
16065
16215
|
/**
|
|
16066
16216
|
* Runs live trading in background without yielding results.
|
|
@@ -16083,15 +16233,24 @@ class LiveInstance {
|
|
|
16083
16233
|
* ```
|
|
16084
16234
|
*/
|
|
16085
16235
|
this.background = (symbol, context) => {
|
|
16086
|
-
|
|
16236
|
+
bt.loggerService.info(LIVE_METHOD_NAME_BACKGROUND, {
|
|
16087
16237
|
symbol,
|
|
16088
16238
|
context,
|
|
16089
16239
|
});
|
|
16240
|
+
const currentStatus = this.task.getStatus();
|
|
16241
|
+
{
|
|
16242
|
+
if (currentStatus === "pending") {
|
|
16243
|
+
throw new Error(`Live.background is already running for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName}`);
|
|
16244
|
+
}
|
|
16245
|
+
if (currentStatus === "rejected") {
|
|
16246
|
+
throw new Error(`Live.background has failed for symbol=${symbol} strategyName=${context.strategyName} exchangeName=${context.exchangeName}`);
|
|
16247
|
+
}
|
|
16248
|
+
}
|
|
16090
16249
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(getErrorMessage(error))));
|
|
16091
16250
|
return () => {
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
.getPendingSignal(symbol, context.strategyName)
|
|
16251
|
+
bt.strategyCoreService.stop(false, { symbol, strategyName: context.strategyName });
|
|
16252
|
+
bt.strategyCoreService
|
|
16253
|
+
.getPendingSignal(false, symbol, context.strategyName)
|
|
16095
16254
|
.then(async (pendingSignal) => {
|
|
16096
16255
|
if (pendingSignal) {
|
|
16097
16256
|
return;
|
|
@@ -16127,11 +16286,11 @@ class LiveInstance {
|
|
|
16127
16286
|
* ```
|
|
16128
16287
|
*/
|
|
16129
16288
|
this.stop = async (symbol, strategyName) => {
|
|
16130
|
-
|
|
16289
|
+
bt.loggerService.info(LIVE_METHOD_NAME_STOP, {
|
|
16131
16290
|
symbol,
|
|
16132
16291
|
strategyName,
|
|
16133
16292
|
});
|
|
16134
|
-
await
|
|
16293
|
+
await bt.strategyCoreService.stop(false, { symbol, strategyName });
|
|
16135
16294
|
};
|
|
16136
16295
|
/**
|
|
16137
16296
|
* Gets statistical data from all live trading events for a symbol-strategy pair.
|
|
@@ -16148,11 +16307,11 @@ class LiveInstance {
|
|
|
16148
16307
|
* ```
|
|
16149
16308
|
*/
|
|
16150
16309
|
this.getData = async (symbol, strategyName) => {
|
|
16151
|
-
|
|
16310
|
+
bt.loggerService.info("LiveUtils.getData", {
|
|
16152
16311
|
symbol,
|
|
16153
16312
|
strategyName,
|
|
16154
16313
|
});
|
|
16155
|
-
return await
|
|
16314
|
+
return await bt.liveMarkdownService.getData(symbol, strategyName, false);
|
|
16156
16315
|
};
|
|
16157
16316
|
/**
|
|
16158
16317
|
* Generates markdown report with all events for a symbol-strategy pair.
|
|
@@ -16170,11 +16329,11 @@ class LiveInstance {
|
|
|
16170
16329
|
* ```
|
|
16171
16330
|
*/
|
|
16172
16331
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
16173
|
-
|
|
16332
|
+
bt.loggerService.info(LIVE_METHOD_NAME_GET_REPORT, {
|
|
16174
16333
|
symbol,
|
|
16175
16334
|
strategyName,
|
|
16176
16335
|
});
|
|
16177
|
-
return await
|
|
16336
|
+
return await bt.liveMarkdownService.getReport(symbol, strategyName, false, columns);
|
|
16178
16337
|
};
|
|
16179
16338
|
/**
|
|
16180
16339
|
* Saves strategy report to disk.
|
|
@@ -16195,12 +16354,12 @@ class LiveInstance {
|
|
|
16195
16354
|
* ```
|
|
16196
16355
|
*/
|
|
16197
16356
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
16198
|
-
|
|
16357
|
+
bt.loggerService.info(LIVE_METHOD_NAME_DUMP, {
|
|
16199
16358
|
symbol,
|
|
16200
16359
|
strategyName,
|
|
16201
16360
|
path,
|
|
16202
16361
|
});
|
|
16203
|
-
await
|
|
16362
|
+
await bt.liveMarkdownService.dump(symbol, strategyName, false, path, columns);
|
|
16204
16363
|
};
|
|
16205
16364
|
}
|
|
16206
16365
|
}
|
|
@@ -16252,13 +16411,13 @@ class LiveUtils {
|
|
|
16252
16411
|
*/
|
|
16253
16412
|
this.run = (symbol, context) => {
|
|
16254
16413
|
{
|
|
16255
|
-
|
|
16256
|
-
|
|
16414
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_RUN);
|
|
16415
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_RUN);
|
|
16257
16416
|
}
|
|
16258
16417
|
{
|
|
16259
|
-
const { riskName, riskList } =
|
|
16260
|
-
riskName &&
|
|
16261
|
-
riskList && riskList.forEach((riskName) =>
|
|
16418
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
16419
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_RUN);
|
|
16420
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_RUN));
|
|
16262
16421
|
}
|
|
16263
16422
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
16264
16423
|
return instance.run(symbol, context);
|
|
@@ -16285,12 +16444,12 @@ class LiveUtils {
|
|
|
16285
16444
|
* ```
|
|
16286
16445
|
*/
|
|
16287
16446
|
this.background = (symbol, context) => {
|
|
16288
|
-
|
|
16289
|
-
|
|
16447
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_BACKGROUND);
|
|
16448
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_BACKGROUND);
|
|
16290
16449
|
{
|
|
16291
|
-
const { riskName, riskList } =
|
|
16292
|
-
riskName &&
|
|
16293
|
-
riskList && riskList.forEach((riskName) =>
|
|
16450
|
+
const { riskName, riskList } = bt.strategySchemaService.get(context.strategyName);
|
|
16451
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_BACKGROUND);
|
|
16452
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_BACKGROUND));
|
|
16294
16453
|
}
|
|
16295
16454
|
const instance = this._getInstance(symbol, context.strategyName);
|
|
16296
16455
|
return instance.background(symbol, context);
|
|
@@ -16313,11 +16472,11 @@ class LiveUtils {
|
|
|
16313
16472
|
* ```
|
|
16314
16473
|
*/
|
|
16315
16474
|
this.stop = async (symbol, strategyName) => {
|
|
16316
|
-
|
|
16475
|
+
bt.strategyValidationService.validate(strategyName, LIVE_METHOD_NAME_STOP);
|
|
16317
16476
|
{
|
|
16318
|
-
const { riskName, riskList } =
|
|
16319
|
-
riskName &&
|
|
16320
|
-
riskList && riskList.forEach((riskName) =>
|
|
16477
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16478
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_STOP);
|
|
16479
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_STOP));
|
|
16321
16480
|
}
|
|
16322
16481
|
const instance = this._getInstance(symbol, strategyName);
|
|
16323
16482
|
return await instance.stop(symbol, strategyName);
|
|
@@ -16336,11 +16495,11 @@ class LiveUtils {
|
|
|
16336
16495
|
* ```
|
|
16337
16496
|
*/
|
|
16338
16497
|
this.getData = async (symbol, strategyName) => {
|
|
16339
|
-
|
|
16498
|
+
bt.strategyValidationService.validate(strategyName, "LiveUtils.getData");
|
|
16340
16499
|
{
|
|
16341
|
-
const { riskName, riskList } =
|
|
16342
|
-
riskName &&
|
|
16343
|
-
riskList && riskList.forEach((riskName) =>
|
|
16500
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16501
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_DATA);
|
|
16502
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_DATA));
|
|
16344
16503
|
}
|
|
16345
16504
|
const instance = this._getInstance(symbol, strategyName);
|
|
16346
16505
|
return await instance.getData(symbol, strategyName);
|
|
@@ -16360,11 +16519,11 @@ class LiveUtils {
|
|
|
16360
16519
|
* ```
|
|
16361
16520
|
*/
|
|
16362
16521
|
this.getReport = async (symbol, strategyName, columns) => {
|
|
16363
|
-
|
|
16522
|
+
bt.strategyValidationService.validate(strategyName, LIVE_METHOD_NAME_GET_REPORT);
|
|
16364
16523
|
{
|
|
16365
|
-
const { riskName, riskList } =
|
|
16366
|
-
riskName &&
|
|
16367
|
-
riskList && riskList.forEach((riskName) =>
|
|
16524
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16525
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_REPORT);
|
|
16526
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_REPORT));
|
|
16368
16527
|
}
|
|
16369
16528
|
const instance = this._getInstance(symbol, strategyName);
|
|
16370
16529
|
return await instance.getReport(symbol, strategyName, columns);
|
|
@@ -16387,11 +16546,11 @@ class LiveUtils {
|
|
|
16387
16546
|
* ```
|
|
16388
16547
|
*/
|
|
16389
16548
|
this.dump = async (symbol, strategyName, path, columns) => {
|
|
16390
|
-
|
|
16549
|
+
bt.strategyValidationService.validate(strategyName, LIVE_METHOD_NAME_DUMP);
|
|
16391
16550
|
{
|
|
16392
|
-
const { riskName, riskList } =
|
|
16393
|
-
riskName &&
|
|
16394
|
-
riskList && riskList.forEach((riskName) =>
|
|
16551
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16552
|
+
riskName && bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_DUMP);
|
|
16553
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_DUMP));
|
|
16395
16554
|
}
|
|
16396
16555
|
const instance = this._getInstance(symbol, strategyName);
|
|
16397
16556
|
return await instance.dump(symbol, strategyName, path, columns);
|
|
@@ -16475,18 +16634,19 @@ class ScheduleUtils {
|
|
|
16475
16634
|
* console.log(stats.cancellationRate, stats.avgWaitTime);
|
|
16476
16635
|
* ```
|
|
16477
16636
|
*/
|
|
16478
|
-
this.getData = async (symbol, strategyName) => {
|
|
16479
|
-
|
|
16637
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
16638
|
+
bt.loggerService.info(SCHEDULE_METHOD_NAME_GET_DATA, {
|
|
16480
16639
|
symbol,
|
|
16481
16640
|
strategyName,
|
|
16641
|
+
backtest,
|
|
16482
16642
|
});
|
|
16483
|
-
|
|
16643
|
+
bt.strategyValidationService.validate(strategyName, SCHEDULE_METHOD_NAME_GET_DATA);
|
|
16484
16644
|
{
|
|
16485
|
-
const { riskName, riskList } =
|
|
16486
|
-
riskName &&
|
|
16487
|
-
riskList && riskList.forEach((riskName) =>
|
|
16645
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16646
|
+
riskName && bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_DATA);
|
|
16647
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_DATA));
|
|
16488
16648
|
}
|
|
16489
|
-
return await
|
|
16649
|
+
return await bt.scheduleMarkdownService.getData(symbol, strategyName, backtest);
|
|
16490
16650
|
};
|
|
16491
16651
|
/**
|
|
16492
16652
|
* Generates markdown report with all scheduled events for a symbol-strategy pair.
|
|
@@ -16502,18 +16662,19 @@ class ScheduleUtils {
|
|
|
16502
16662
|
* console.log(markdown);
|
|
16503
16663
|
* ```
|
|
16504
16664
|
*/
|
|
16505
|
-
this.getReport = async (symbol, strategyName, columns) => {
|
|
16506
|
-
|
|
16665
|
+
this.getReport = async (symbol, strategyName, backtest, columns) => {
|
|
16666
|
+
bt.loggerService.info(SCHEDULE_METHOD_NAME_GET_REPORT, {
|
|
16507
16667
|
symbol,
|
|
16508
16668
|
strategyName,
|
|
16669
|
+
backtest,
|
|
16509
16670
|
});
|
|
16510
|
-
|
|
16671
|
+
bt.strategyValidationService.validate(strategyName, SCHEDULE_METHOD_NAME_GET_REPORT);
|
|
16511
16672
|
{
|
|
16512
|
-
const { riskName, riskList } =
|
|
16513
|
-
riskName &&
|
|
16514
|
-
riskList && riskList.forEach((riskName) =>
|
|
16673
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16674
|
+
riskName && bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_REPORT);
|
|
16675
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_GET_REPORT));
|
|
16515
16676
|
}
|
|
16516
|
-
return await
|
|
16677
|
+
return await bt.scheduleMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
16517
16678
|
};
|
|
16518
16679
|
/**
|
|
16519
16680
|
* Saves strategy report to disk.
|
|
@@ -16532,19 +16693,20 @@ class ScheduleUtils {
|
|
|
16532
16693
|
* await Schedule.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
16533
16694
|
* ```
|
|
16534
16695
|
*/
|
|
16535
|
-
this.dump = async (symbol, strategyName, path, columns) => {
|
|
16536
|
-
|
|
16696
|
+
this.dump = async (symbol, strategyName, backtest, path, columns) => {
|
|
16697
|
+
bt.loggerService.info(SCHEDULE_METHOD_NAME_DUMP, {
|
|
16537
16698
|
symbol,
|
|
16538
16699
|
strategyName,
|
|
16700
|
+
backtest,
|
|
16539
16701
|
path,
|
|
16540
16702
|
});
|
|
16541
|
-
|
|
16703
|
+
bt.strategyValidationService.validate(strategyName, SCHEDULE_METHOD_NAME_DUMP);
|
|
16542
16704
|
{
|
|
16543
|
-
const { riskName, riskList } =
|
|
16544
|
-
riskName &&
|
|
16545
|
-
riskList && riskList.forEach((riskName) =>
|
|
16705
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16706
|
+
riskName && bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_DUMP);
|
|
16707
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, SCHEDULE_METHOD_NAME_DUMP));
|
|
16546
16708
|
}
|
|
16547
|
-
await
|
|
16709
|
+
await bt.scheduleMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
16548
16710
|
};
|
|
16549
16711
|
}
|
|
16550
16712
|
}
|
|
@@ -16582,7 +16744,7 @@ const PERFORMANCE_METHOD_NAME_DUMP = "Performance.dump";
|
|
|
16582
16744
|
* console.log(`${event.metricType}: ${event.duration.toFixed(2)}ms`);
|
|
16583
16745
|
* });
|
|
16584
16746
|
*
|
|
16585
|
-
* // Run
|
|
16747
|
+
* // Run bt...
|
|
16586
16748
|
*
|
|
16587
16749
|
* // Get aggregated statistics
|
|
16588
16750
|
* const stats = await Performance.getData("my-strategy");
|
|
@@ -16625,14 +16787,14 @@ class Performance {
|
|
|
16625
16787
|
* }
|
|
16626
16788
|
* ```
|
|
16627
16789
|
*/
|
|
16628
|
-
static async getData(symbol, strategyName) {
|
|
16629
|
-
|
|
16790
|
+
static async getData(symbol, strategyName, backtest) {
|
|
16791
|
+
bt.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_DATA);
|
|
16630
16792
|
{
|
|
16631
|
-
const { riskName, riskList } =
|
|
16632
|
-
riskName &&
|
|
16633
|
-
riskList && riskList.forEach((riskName) =>
|
|
16793
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16794
|
+
riskName && bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_DATA);
|
|
16795
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_DATA));
|
|
16634
16796
|
}
|
|
16635
|
-
return
|
|
16797
|
+
return bt.performanceMarkdownService.getData(symbol, strategyName, backtest);
|
|
16636
16798
|
}
|
|
16637
16799
|
/**
|
|
16638
16800
|
* Generates markdown report with performance analysis.
|
|
@@ -16657,14 +16819,14 @@ class Performance {
|
|
|
16657
16819
|
* await fs.writeFile("performance-report.md", markdown);
|
|
16658
16820
|
* ```
|
|
16659
16821
|
*/
|
|
16660
|
-
static async getReport(symbol, strategyName, columns) {
|
|
16661
|
-
|
|
16822
|
+
static async getReport(symbol, strategyName, backtest, columns) {
|
|
16823
|
+
bt.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_GET_REPORT);
|
|
16662
16824
|
{
|
|
16663
|
-
const { riskName, riskList } =
|
|
16664
|
-
riskName &&
|
|
16665
|
-
riskList && riskList.forEach((riskName) =>
|
|
16825
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16826
|
+
riskName && bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_REPORT);
|
|
16827
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_GET_REPORT));
|
|
16666
16828
|
}
|
|
16667
|
-
return
|
|
16829
|
+
return bt.performanceMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
16668
16830
|
}
|
|
16669
16831
|
/**
|
|
16670
16832
|
* Saves performance report to disk.
|
|
@@ -16686,14 +16848,14 @@ class Performance {
|
|
|
16686
16848
|
* await Performance.dump("BTCUSDT", "my-strategy", "./reports/perf");
|
|
16687
16849
|
* ```
|
|
16688
16850
|
*/
|
|
16689
|
-
static async dump(symbol, strategyName, path = "./dump/performance", columns) {
|
|
16690
|
-
|
|
16851
|
+
static async dump(symbol, strategyName, backtest, path = "./dump/performance", columns) {
|
|
16852
|
+
bt.strategyValidationService.validate(strategyName, PERFORMANCE_METHOD_NAME_DUMP);
|
|
16691
16853
|
{
|
|
16692
|
-
const { riskName, riskList } =
|
|
16693
|
-
riskName &&
|
|
16694
|
-
riskList && riskList.forEach((riskName) =>
|
|
16854
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
16855
|
+
riskName && bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_DUMP);
|
|
16856
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PERFORMANCE_METHOD_NAME_DUMP));
|
|
16695
16857
|
}
|
|
16696
|
-
return
|
|
16858
|
+
return bt.performanceMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
16697
16859
|
}
|
|
16698
16860
|
}
|
|
16699
16861
|
|
|
@@ -16727,7 +16889,7 @@ const INSTANCE_TASK_FN = async (symbol, context, self) => {
|
|
|
16727
16889
|
}
|
|
16728
16890
|
}
|
|
16729
16891
|
if (!self._isDone) {
|
|
16730
|
-
const walkerSchema =
|
|
16892
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
16731
16893
|
await doneWalkerSubject.next({
|
|
16732
16894
|
exchangeName: walkerSchema.exchangeName,
|
|
16733
16895
|
strategyName: context.walkerName,
|
|
@@ -16781,7 +16943,7 @@ class WalkerInstance {
|
|
|
16781
16943
|
* @internal
|
|
16782
16944
|
*/
|
|
16783
16945
|
this.task = singlerun(async (symbol, context) => {
|
|
16784
|
-
|
|
16946
|
+
bt.loggerService.info(WALKER_METHOD_NAME_TASK, {
|
|
16785
16947
|
symbol,
|
|
16786
16948
|
context,
|
|
16787
16949
|
});
|
|
@@ -16800,7 +16962,7 @@ class WalkerInstance {
|
|
|
16800
16962
|
* ```
|
|
16801
16963
|
*/
|
|
16802
16964
|
this.getStatus = async () => {
|
|
16803
|
-
|
|
16965
|
+
bt.loggerService.info(WALKER_METHOD_NAME_GET_STATUS);
|
|
16804
16966
|
return {
|
|
16805
16967
|
id: this.id,
|
|
16806
16968
|
symbol: this.symbol,
|
|
@@ -16816,34 +16978,39 @@ class WalkerInstance {
|
|
|
16816
16978
|
* @returns Async generator yielding progress updates after each strategy
|
|
16817
16979
|
*/
|
|
16818
16980
|
this.run = (symbol, context) => {
|
|
16819
|
-
|
|
16981
|
+
bt.loggerService.info(WALKER_METHOD_NAME_RUN, {
|
|
16820
16982
|
symbol,
|
|
16821
16983
|
context,
|
|
16822
16984
|
});
|
|
16823
|
-
|
|
16824
|
-
const walkerSchema =
|
|
16825
|
-
|
|
16826
|
-
|
|
16985
|
+
bt.walkerValidationService.validate(context.walkerName, WALKER_METHOD_NAME_RUN);
|
|
16986
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
16987
|
+
bt.exchangeValidationService.validate(walkerSchema.exchangeName, WALKER_METHOD_NAME_RUN);
|
|
16988
|
+
bt.frameValidationService.validate(walkerSchema.frameName, WALKER_METHOD_NAME_RUN);
|
|
16827
16989
|
for (const strategyName of walkerSchema.strategies) {
|
|
16828
|
-
|
|
16990
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_RUN);
|
|
16829
16991
|
}
|
|
16830
|
-
|
|
16992
|
+
bt.walkerMarkdownService.clear(context.walkerName);
|
|
16831
16993
|
// Clear backtest data for all strategies
|
|
16832
16994
|
for (const strategyName of walkerSchema.strategies) {
|
|
16833
16995
|
{
|
|
16834
|
-
|
|
16835
|
-
|
|
16996
|
+
bt.backtestMarkdownService.clear(true, { symbol, strategyName });
|
|
16997
|
+
bt.liveMarkdownService.clear(true, { symbol, strategyName });
|
|
16998
|
+
bt.scheduleMarkdownService.clear(true, { symbol, strategyName });
|
|
16999
|
+
bt.performanceMarkdownService.clear(true, { symbol, strategyName });
|
|
17000
|
+
bt.partialMarkdownService.clear(true, { symbol, strategyName });
|
|
17001
|
+
bt.riskMarkdownService.clear(true, { symbol, strategyName });
|
|
16836
17002
|
}
|
|
16837
17003
|
{
|
|
16838
|
-
|
|
17004
|
+
bt.strategyCoreService.clear(true, { symbol, strategyName });
|
|
16839
17005
|
}
|
|
16840
17006
|
{
|
|
16841
|
-
const { riskName, riskList } =
|
|
16842
|
-
riskName &&
|
|
16843
|
-
riskList &&
|
|
17007
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17008
|
+
riskName && bt.riskGlobalService.clear(true, riskName);
|
|
17009
|
+
riskList &&
|
|
17010
|
+
riskList.forEach((riskName) => bt.riskGlobalService.clear(true, riskName));
|
|
16844
17011
|
}
|
|
16845
17012
|
}
|
|
16846
|
-
return
|
|
17013
|
+
return bt.walkerCommandService.run(symbol, {
|
|
16847
17014
|
walkerName: context.walkerName,
|
|
16848
17015
|
exchangeName: walkerSchema.exchangeName,
|
|
16849
17016
|
frameName: walkerSchema.frameName,
|
|
@@ -16868,16 +17035,29 @@ class WalkerInstance {
|
|
|
16868
17035
|
* ```
|
|
16869
17036
|
*/
|
|
16870
17037
|
this.background = (symbol, context) => {
|
|
16871
|
-
|
|
17038
|
+
bt.loggerService.info(WALKER_METHOD_NAME_BACKGROUND, {
|
|
16872
17039
|
symbol,
|
|
16873
17040
|
context,
|
|
16874
17041
|
});
|
|
16875
|
-
const walkerSchema =
|
|
17042
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
17043
|
+
{
|
|
17044
|
+
const currentStatus = this.task.getStatus();
|
|
17045
|
+
if (currentStatus === "pending") {
|
|
17046
|
+
throw new Error(`Walker.background is already running for symbol=${symbol} walkerName=${context.walkerName}`);
|
|
17047
|
+
}
|
|
17048
|
+
if (currentStatus === "rejected") {
|
|
17049
|
+
throw new Error(`Walker.background has failed for symbol=${symbol} walkerName=${context.walkerName}`);
|
|
17050
|
+
}
|
|
17051
|
+
}
|
|
16876
17052
|
this.task(symbol, context).catch((error) => exitEmitter.next(new Error(getErrorMessage(error))));
|
|
16877
17053
|
return () => {
|
|
16878
17054
|
for (const strategyName of walkerSchema.strategies) {
|
|
16879
|
-
|
|
16880
|
-
walkerStopSubject.next({
|
|
17055
|
+
bt.strategyCoreService.stop(true, { symbol, strategyName });
|
|
17056
|
+
walkerStopSubject.next({
|
|
17057
|
+
symbol,
|
|
17058
|
+
strategyName,
|
|
17059
|
+
walkerName: context.walkerName,
|
|
17060
|
+
});
|
|
16881
17061
|
}
|
|
16882
17062
|
if (!this._isDone) {
|
|
16883
17063
|
doneWalkerSubject.next({
|
|
@@ -16915,14 +17095,14 @@ class WalkerInstance {
|
|
|
16915
17095
|
* ```
|
|
16916
17096
|
*/
|
|
16917
17097
|
this.stop = async (symbol, walkerName) => {
|
|
16918
|
-
|
|
17098
|
+
bt.loggerService.info(WALKER_METHOD_NAME_STOP, {
|
|
16919
17099
|
symbol,
|
|
16920
17100
|
walkerName,
|
|
16921
17101
|
});
|
|
16922
|
-
const walkerSchema =
|
|
17102
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
16923
17103
|
for (const strategyName of walkerSchema.strategies) {
|
|
16924
17104
|
await walkerStopSubject.next({ symbol, strategyName, walkerName });
|
|
16925
|
-
await
|
|
17105
|
+
await bt.strategyCoreService.stop(true, { symbol, strategyName });
|
|
16926
17106
|
}
|
|
16927
17107
|
};
|
|
16928
17108
|
/**
|
|
@@ -16940,12 +17120,12 @@ class WalkerInstance {
|
|
|
16940
17120
|
* ```
|
|
16941
17121
|
*/
|
|
16942
17122
|
this.getData = async (symbol, walkerName) => {
|
|
16943
|
-
|
|
17123
|
+
bt.loggerService.info(WALKER_METHOD_NAME_GET_DATA, {
|
|
16944
17124
|
symbol,
|
|
16945
17125
|
walkerName,
|
|
16946
17126
|
});
|
|
16947
|
-
const walkerSchema =
|
|
16948
|
-
return await
|
|
17127
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17128
|
+
return await bt.walkerMarkdownService.getData(walkerName, symbol, walkerSchema.metric || "sharpeRatio", {
|
|
16949
17129
|
exchangeName: walkerSchema.exchangeName,
|
|
16950
17130
|
frameName: walkerSchema.frameName,
|
|
16951
17131
|
});
|
|
@@ -16967,12 +17147,12 @@ class WalkerInstance {
|
|
|
16967
17147
|
* ```
|
|
16968
17148
|
*/
|
|
16969
17149
|
this.getReport = async (symbol, walkerName, strategyColumns, pnlColumns) => {
|
|
16970
|
-
|
|
17150
|
+
bt.loggerService.info(WALKER_METHOD_NAME_GET_REPORT, {
|
|
16971
17151
|
symbol,
|
|
16972
17152
|
walkerName,
|
|
16973
17153
|
});
|
|
16974
|
-
const walkerSchema =
|
|
16975
|
-
return await
|
|
17154
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17155
|
+
return await bt.walkerMarkdownService.getReport(walkerName, symbol, walkerSchema.metric || "sharpeRatio", {
|
|
16976
17156
|
exchangeName: walkerSchema.exchangeName,
|
|
16977
17157
|
frameName: walkerSchema.frameName,
|
|
16978
17158
|
}, strategyColumns, pnlColumns);
|
|
@@ -16997,13 +17177,13 @@ class WalkerInstance {
|
|
|
16997
17177
|
* ```
|
|
16998
17178
|
*/
|
|
16999
17179
|
this.dump = async (symbol, walkerName, path, strategyColumns, pnlColumns) => {
|
|
17000
|
-
|
|
17180
|
+
bt.loggerService.info(WALKER_METHOD_NAME_DUMP, {
|
|
17001
17181
|
symbol,
|
|
17002
17182
|
walkerName,
|
|
17003
17183
|
path,
|
|
17004
17184
|
});
|
|
17005
|
-
const walkerSchema =
|
|
17006
|
-
await
|
|
17185
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17186
|
+
await bt.walkerMarkdownService.dump(walkerName, symbol, walkerSchema.metric || "sharpeRatio", {
|
|
17007
17187
|
exchangeName: walkerSchema.exchangeName,
|
|
17008
17188
|
frameName: walkerSchema.frameName,
|
|
17009
17189
|
}, path, strategyColumns, pnlColumns);
|
|
@@ -17044,15 +17224,17 @@ class WalkerUtils {
|
|
|
17044
17224
|
* @returns Async generator yielding progress updates after each strategy
|
|
17045
17225
|
*/
|
|
17046
17226
|
this.run = (symbol, context) => {
|
|
17047
|
-
|
|
17048
|
-
const walkerSchema =
|
|
17049
|
-
|
|
17050
|
-
|
|
17227
|
+
bt.walkerValidationService.validate(context.walkerName, WALKER_METHOD_NAME_RUN);
|
|
17228
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
17229
|
+
bt.exchangeValidationService.validate(walkerSchema.exchangeName, WALKER_METHOD_NAME_RUN);
|
|
17230
|
+
bt.frameValidationService.validate(walkerSchema.frameName, WALKER_METHOD_NAME_RUN);
|
|
17051
17231
|
for (const strategyName of walkerSchema.strategies) {
|
|
17052
|
-
|
|
17053
|
-
const { riskName, riskList } =
|
|
17054
|
-
riskName &&
|
|
17055
|
-
|
|
17232
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_RUN);
|
|
17233
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17234
|
+
riskName &&
|
|
17235
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_RUN);
|
|
17236
|
+
riskList &&
|
|
17237
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_RUN));
|
|
17056
17238
|
}
|
|
17057
17239
|
const instance = this._getInstance(symbol, context.walkerName);
|
|
17058
17240
|
return instance.run(symbol, context);
|
|
@@ -17077,15 +17259,17 @@ class WalkerUtils {
|
|
|
17077
17259
|
* ```
|
|
17078
17260
|
*/
|
|
17079
17261
|
this.background = (symbol, context) => {
|
|
17080
|
-
|
|
17081
|
-
const walkerSchema =
|
|
17082
|
-
|
|
17083
|
-
|
|
17262
|
+
bt.walkerValidationService.validate(context.walkerName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17263
|
+
const walkerSchema = bt.walkerSchemaService.get(context.walkerName);
|
|
17264
|
+
bt.exchangeValidationService.validate(walkerSchema.exchangeName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17265
|
+
bt.frameValidationService.validate(walkerSchema.frameName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17084
17266
|
for (const strategyName of walkerSchema.strategies) {
|
|
17085
|
-
|
|
17086
|
-
const { riskName, riskList } =
|
|
17087
|
-
riskName &&
|
|
17088
|
-
|
|
17267
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17268
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17269
|
+
riskName &&
|
|
17270
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_BACKGROUND);
|
|
17271
|
+
riskList &&
|
|
17272
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_BACKGROUND));
|
|
17089
17273
|
}
|
|
17090
17274
|
const instance = this._getInstance(symbol, context.walkerName);
|
|
17091
17275
|
return instance.background(symbol, context);
|
|
@@ -17114,13 +17298,15 @@ class WalkerUtils {
|
|
|
17114
17298
|
* ```
|
|
17115
17299
|
*/
|
|
17116
17300
|
this.stop = async (symbol, walkerName) => {
|
|
17117
|
-
|
|
17118
|
-
const walkerSchema =
|
|
17301
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_STOP);
|
|
17302
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17119
17303
|
for (const strategyName of walkerSchema.strategies) {
|
|
17120
|
-
|
|
17121
|
-
const { riskName, riskList } =
|
|
17122
|
-
riskName &&
|
|
17123
|
-
|
|
17304
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_STOP);
|
|
17305
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17306
|
+
riskName &&
|
|
17307
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_STOP);
|
|
17308
|
+
riskList &&
|
|
17309
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_STOP));
|
|
17124
17310
|
}
|
|
17125
17311
|
const instance = this._getInstance(symbol, walkerName);
|
|
17126
17312
|
return await instance.stop(symbol, walkerName);
|
|
@@ -17139,13 +17325,15 @@ class WalkerUtils {
|
|
|
17139
17325
|
* ```
|
|
17140
17326
|
*/
|
|
17141
17327
|
this.getData = async (symbol, walkerName) => {
|
|
17142
|
-
|
|
17143
|
-
const walkerSchema =
|
|
17328
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_GET_DATA);
|
|
17329
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17144
17330
|
for (const strategyName of walkerSchema.strategies) {
|
|
17145
|
-
|
|
17146
|
-
const { riskName, riskList } =
|
|
17147
|
-
riskName &&
|
|
17148
|
-
|
|
17331
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_GET_DATA);
|
|
17332
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17333
|
+
riskName &&
|
|
17334
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_DATA);
|
|
17335
|
+
riskList &&
|
|
17336
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_DATA));
|
|
17149
17337
|
}
|
|
17150
17338
|
const instance = this._getInstance(symbol, walkerName);
|
|
17151
17339
|
return await instance.getData(symbol, walkerName);
|
|
@@ -17166,13 +17354,15 @@ class WalkerUtils {
|
|
|
17166
17354
|
* ```
|
|
17167
17355
|
*/
|
|
17168
17356
|
this.getReport = async (symbol, walkerName, strategyColumns, pnlColumns) => {
|
|
17169
|
-
|
|
17170
|
-
const walkerSchema =
|
|
17357
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_GET_REPORT);
|
|
17358
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17171
17359
|
for (const strategyName of walkerSchema.strategies) {
|
|
17172
|
-
|
|
17173
|
-
const { riskName, riskList } =
|
|
17174
|
-
riskName &&
|
|
17175
|
-
|
|
17360
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_GET_REPORT);
|
|
17361
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17362
|
+
riskName &&
|
|
17363
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_REPORT);
|
|
17364
|
+
riskList &&
|
|
17365
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_GET_REPORT));
|
|
17176
17366
|
}
|
|
17177
17367
|
const instance = this._getInstance(symbol, walkerName);
|
|
17178
17368
|
return await instance.getReport(symbol, walkerName, strategyColumns, pnlColumns);
|
|
@@ -17196,13 +17386,15 @@ class WalkerUtils {
|
|
|
17196
17386
|
* ```
|
|
17197
17387
|
*/
|
|
17198
17388
|
this.dump = async (symbol, walkerName, path, strategyColumns, pnlColumns) => {
|
|
17199
|
-
|
|
17200
|
-
const walkerSchema =
|
|
17389
|
+
bt.walkerValidationService.validate(walkerName, WALKER_METHOD_NAME_DUMP);
|
|
17390
|
+
const walkerSchema = bt.walkerSchemaService.get(walkerName);
|
|
17201
17391
|
for (const strategyName of walkerSchema.strategies) {
|
|
17202
|
-
|
|
17203
|
-
const { riskName, riskList } =
|
|
17204
|
-
riskName &&
|
|
17205
|
-
|
|
17392
|
+
bt.strategyValidationService.validate(strategyName, WALKER_METHOD_NAME_DUMP);
|
|
17393
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17394
|
+
riskName &&
|
|
17395
|
+
bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_DUMP);
|
|
17396
|
+
riskList &&
|
|
17397
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, WALKER_METHOD_NAME_DUMP));
|
|
17206
17398
|
}
|
|
17207
17399
|
const instance = this._getInstance(symbol, walkerName);
|
|
17208
17400
|
return await instance.dump(symbol, walkerName, path, strategyColumns, pnlColumns);
|
|
@@ -17294,15 +17486,15 @@ class HeatUtils {
|
|
|
17294
17486
|
* });
|
|
17295
17487
|
* ```
|
|
17296
17488
|
*/
|
|
17297
|
-
this.getData = async (strategyName) => {
|
|
17298
|
-
|
|
17299
|
-
|
|
17489
|
+
this.getData = async (strategyName, backtest) => {
|
|
17490
|
+
bt.loggerService.info(HEAT_METHOD_NAME_GET_DATA, { strategyName });
|
|
17491
|
+
bt.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_DATA);
|
|
17300
17492
|
{
|
|
17301
|
-
const { riskName, riskList } =
|
|
17302
|
-
riskName &&
|
|
17303
|
-
riskList && riskList.forEach((riskName) =>
|
|
17493
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17494
|
+
riskName && bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_DATA);
|
|
17495
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_DATA));
|
|
17304
17496
|
}
|
|
17305
|
-
return await
|
|
17497
|
+
return await bt.heatMarkdownService.getData(strategyName, backtest);
|
|
17306
17498
|
};
|
|
17307
17499
|
/**
|
|
17308
17500
|
* Generates markdown report with portfolio heatmap table for a strategy.
|
|
@@ -17330,15 +17522,15 @@ class HeatUtils {
|
|
|
17330
17522
|
* // ...
|
|
17331
17523
|
* ```
|
|
17332
17524
|
*/
|
|
17333
|
-
this.getReport = async (strategyName, columns) => {
|
|
17334
|
-
|
|
17335
|
-
|
|
17525
|
+
this.getReport = async (strategyName, backtest, columns) => {
|
|
17526
|
+
bt.loggerService.info(HEAT_METHOD_NAME_GET_REPORT, { strategyName });
|
|
17527
|
+
bt.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_GET_REPORT);
|
|
17336
17528
|
{
|
|
17337
|
-
const { riskName, riskList } =
|
|
17338
|
-
riskName &&
|
|
17339
|
-
riskList && riskList.forEach((riskName) =>
|
|
17529
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17530
|
+
riskName && bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_REPORT);
|
|
17531
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_GET_REPORT));
|
|
17340
17532
|
}
|
|
17341
|
-
return await
|
|
17533
|
+
return await bt.heatMarkdownService.getReport(strategyName, backtest, columns);
|
|
17342
17534
|
};
|
|
17343
17535
|
/**
|
|
17344
17536
|
* Saves heatmap report to disk for a strategy.
|
|
@@ -17359,15 +17551,15 @@ class HeatUtils {
|
|
|
17359
17551
|
* await Heat.dump("my-strategy", "./reports");
|
|
17360
17552
|
* ```
|
|
17361
17553
|
*/
|
|
17362
|
-
this.dump = async (strategyName, path, columns) => {
|
|
17363
|
-
|
|
17364
|
-
|
|
17554
|
+
this.dump = async (strategyName, backtest, path, columns) => {
|
|
17555
|
+
bt.loggerService.info(HEAT_METHOD_NAME_DUMP, { strategyName, path });
|
|
17556
|
+
bt.strategyValidationService.validate(strategyName, HEAT_METHOD_NAME_DUMP);
|
|
17365
17557
|
{
|
|
17366
|
-
const { riskName, riskList } =
|
|
17367
|
-
riskName &&
|
|
17368
|
-
riskList && riskList.forEach((riskName) =>
|
|
17558
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17559
|
+
riskName && bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_DUMP);
|
|
17560
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, HEAT_METHOD_NAME_DUMP));
|
|
17369
17561
|
}
|
|
17370
|
-
await
|
|
17562
|
+
await bt.heatMarkdownService.dump(strategyName, backtest, path, columns);
|
|
17371
17563
|
};
|
|
17372
17564
|
}
|
|
17373
17565
|
}
|
|
@@ -17454,12 +17646,12 @@ class PositionSizeUtils {
|
|
|
17454
17646
|
* @throws Error if sizing schema method is not "fixed-percentage"
|
|
17455
17647
|
*/
|
|
17456
17648
|
PositionSizeUtils.fixedPercentage = async (symbol, accountBalance, priceOpen, priceStopLoss, context) => {
|
|
17457
|
-
|
|
17649
|
+
bt.loggerService.info(POSITION_SIZE_METHOD_NAME_FIXED, {
|
|
17458
17650
|
context,
|
|
17459
17651
|
symbol,
|
|
17460
17652
|
});
|
|
17461
|
-
|
|
17462
|
-
return await
|
|
17653
|
+
bt.sizingValidationService.validate(context.sizingName, POSITION_SIZE_METHOD_NAME_FIXED, "fixed-percentage");
|
|
17654
|
+
return await bt.sizingGlobalService.calculate({
|
|
17463
17655
|
symbol,
|
|
17464
17656
|
accountBalance,
|
|
17465
17657
|
priceOpen,
|
|
@@ -17480,12 +17672,12 @@ PositionSizeUtils.fixedPercentage = async (symbol, accountBalance, priceOpen, pr
|
|
|
17480
17672
|
* @throws Error if sizing schema method is not "kelly-criterion"
|
|
17481
17673
|
*/
|
|
17482
17674
|
PositionSizeUtils.kellyCriterion = async (symbol, accountBalance, priceOpen, winRate, winLossRatio, context) => {
|
|
17483
|
-
|
|
17675
|
+
bt.loggerService.info(POSITION_SIZE_METHOD_NAME_KELLY, {
|
|
17484
17676
|
context,
|
|
17485
17677
|
symbol,
|
|
17486
17678
|
});
|
|
17487
|
-
|
|
17488
|
-
return await
|
|
17679
|
+
bt.sizingValidationService.validate(context.sizingName, POSITION_SIZE_METHOD_NAME_KELLY, "kelly-criterion");
|
|
17680
|
+
return await bt.sizingGlobalService.calculate({
|
|
17489
17681
|
symbol,
|
|
17490
17682
|
accountBalance,
|
|
17491
17683
|
priceOpen,
|
|
@@ -17506,12 +17698,12 @@ PositionSizeUtils.kellyCriterion = async (symbol, accountBalance, priceOpen, win
|
|
|
17506
17698
|
* @throws Error if sizing schema method is not "atr-based"
|
|
17507
17699
|
*/
|
|
17508
17700
|
PositionSizeUtils.atrBased = async (symbol, accountBalance, priceOpen, atr, context) => {
|
|
17509
|
-
|
|
17701
|
+
bt.loggerService.info(POSITION_SIZE_METHOD_NAME_ATR, {
|
|
17510
17702
|
context,
|
|
17511
17703
|
symbol,
|
|
17512
17704
|
});
|
|
17513
|
-
|
|
17514
|
-
return await
|
|
17705
|
+
bt.sizingValidationService.validate(context.sizingName, POSITION_SIZE_METHOD_NAME_ATR, "atr-based");
|
|
17706
|
+
return await bt.sizingGlobalService.calculate({
|
|
17515
17707
|
symbol,
|
|
17516
17708
|
accountBalance,
|
|
17517
17709
|
priceOpen,
|
|
@@ -17560,12 +17752,12 @@ class OptimizerUtils {
|
|
|
17560
17752
|
* @throws Error if optimizer not found
|
|
17561
17753
|
*/
|
|
17562
17754
|
this.getData = async (symbol, context) => {
|
|
17563
|
-
|
|
17755
|
+
bt.loggerService.info(OPTIMIZER_METHOD_NAME_GET_DATA, {
|
|
17564
17756
|
symbol,
|
|
17565
17757
|
context,
|
|
17566
17758
|
});
|
|
17567
|
-
|
|
17568
|
-
return await
|
|
17759
|
+
bt.optimizerValidationService.validate(context.optimizerName, OPTIMIZER_METHOD_NAME_GET_DATA);
|
|
17760
|
+
return await bt.optimizerGlobalService.getData(symbol, context.optimizerName);
|
|
17569
17761
|
};
|
|
17570
17762
|
/**
|
|
17571
17763
|
* Generates complete executable strategy code.
|
|
@@ -17577,12 +17769,12 @@ class OptimizerUtils {
|
|
|
17577
17769
|
* @throws Error if optimizer not found
|
|
17578
17770
|
*/
|
|
17579
17771
|
this.getCode = async (symbol, context) => {
|
|
17580
|
-
|
|
17772
|
+
bt.loggerService.info(OPTIMIZER_METHOD_NAME_GET_CODE, {
|
|
17581
17773
|
symbol,
|
|
17582
17774
|
context,
|
|
17583
17775
|
});
|
|
17584
|
-
|
|
17585
|
-
return await
|
|
17776
|
+
bt.optimizerValidationService.validate(context.optimizerName, OPTIMIZER_METHOD_NAME_GET_CODE);
|
|
17777
|
+
return await bt.optimizerGlobalService.getCode(symbol, context.optimizerName);
|
|
17586
17778
|
};
|
|
17587
17779
|
/**
|
|
17588
17780
|
* Generates and saves strategy code to file.
|
|
@@ -17596,13 +17788,13 @@ class OptimizerUtils {
|
|
|
17596
17788
|
* @throws Error if optimizer not found or file write fails
|
|
17597
17789
|
*/
|
|
17598
17790
|
this.dump = async (symbol, context, path) => {
|
|
17599
|
-
|
|
17791
|
+
bt.loggerService.info(OPTIMIZER_METHOD_NAME_DUMP, {
|
|
17600
17792
|
symbol,
|
|
17601
17793
|
context,
|
|
17602
17794
|
path,
|
|
17603
17795
|
});
|
|
17604
|
-
|
|
17605
|
-
await
|
|
17796
|
+
bt.optimizerValidationService.validate(context.optimizerName, OPTIMIZER_METHOD_NAME_DUMP);
|
|
17797
|
+
await bt.optimizerGlobalService.dump(symbol, context.optimizerName, path);
|
|
17606
17798
|
};
|
|
17607
17799
|
}
|
|
17608
17800
|
}
|
|
@@ -17683,15 +17875,15 @@ class PartialUtils {
|
|
|
17683
17875
|
* }
|
|
17684
17876
|
* ```
|
|
17685
17877
|
*/
|
|
17686
|
-
this.getData = async (symbol, strategyName) => {
|
|
17687
|
-
|
|
17688
|
-
|
|
17878
|
+
this.getData = async (symbol, strategyName, backtest) => {
|
|
17879
|
+
bt.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol, strategyName });
|
|
17880
|
+
bt.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_DATA);
|
|
17689
17881
|
{
|
|
17690
|
-
const { riskName, riskList } =
|
|
17691
|
-
riskName &&
|
|
17692
|
-
riskList && riskList.forEach((riskName) =>
|
|
17882
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17883
|
+
riskName && bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_DATA);
|
|
17884
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_DATA));
|
|
17693
17885
|
}
|
|
17694
|
-
return await
|
|
17886
|
+
return await bt.partialMarkdownService.getData(symbol, strategyName, backtest);
|
|
17695
17887
|
};
|
|
17696
17888
|
/**
|
|
17697
17889
|
* Generates markdown report with all partial profit/loss events for a symbol-strategy pair.
|
|
@@ -17732,15 +17924,15 @@ class PartialUtils {
|
|
|
17732
17924
|
* // **Loss events:** 1
|
|
17733
17925
|
* ```
|
|
17734
17926
|
*/
|
|
17735
|
-
this.getReport = async (symbol, strategyName, columns) => {
|
|
17736
|
-
|
|
17737
|
-
|
|
17927
|
+
this.getReport = async (symbol, strategyName, backtest, columns) => {
|
|
17928
|
+
bt.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol, strategyName });
|
|
17929
|
+
bt.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_GET_REPORT);
|
|
17738
17930
|
{
|
|
17739
|
-
const { riskName, riskList } =
|
|
17740
|
-
riskName &&
|
|
17741
|
-
riskList && riskList.forEach((riskName) =>
|
|
17931
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17932
|
+
riskName && bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_REPORT);
|
|
17933
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_GET_REPORT));
|
|
17742
17934
|
}
|
|
17743
|
-
return await
|
|
17935
|
+
return await bt.partialMarkdownService.getReport(symbol, strategyName, backtest, columns);
|
|
17744
17936
|
};
|
|
17745
17937
|
/**
|
|
17746
17938
|
* Generates and saves markdown report to file.
|
|
@@ -17774,15 +17966,15 @@ class PartialUtils {
|
|
|
17774
17966
|
* }
|
|
17775
17967
|
* ```
|
|
17776
17968
|
*/
|
|
17777
|
-
this.dump = async (symbol, strategyName, path, columns) => {
|
|
17778
|
-
|
|
17779
|
-
|
|
17969
|
+
this.dump = async (symbol, strategyName, backtest, path, columns) => {
|
|
17970
|
+
bt.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, strategyName, path });
|
|
17971
|
+
bt.strategyValidationService.validate(strategyName, PARTIAL_METHOD_NAME_DUMP);
|
|
17780
17972
|
{
|
|
17781
|
-
const { riskName, riskList } =
|
|
17782
|
-
riskName &&
|
|
17783
|
-
riskList && riskList.forEach((riskName) =>
|
|
17973
|
+
const { riskName, riskList } = bt.strategySchemaService.get(strategyName);
|
|
17974
|
+
riskName && bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_DUMP);
|
|
17975
|
+
riskList && riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, PARTIAL_METHOD_NAME_DUMP));
|
|
17784
17976
|
}
|
|
17785
|
-
await
|
|
17977
|
+
await bt.partialMarkdownService.dump(symbol, strategyName, backtest, path, columns);
|
|
17786
17978
|
};
|
|
17787
17979
|
}
|
|
17788
17980
|
}
|