backtest-kit 9.7.0 → 9.8.1
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/LICENSE +21 -21
- package/README.md +1871 -1871
- package/build/index.cjs +283 -180
- package/build/index.mjs +284 -181
- package/package.json +86 -86
- package/types.d.ts +100 -28
package/build/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { scoped } from 'di-scoped';
|
|
|
3
3
|
import { singleton } from 'di-singleton';
|
|
4
4
|
import { Subject, makeExtendable, singleshot, getErrorMessage, memoize, not, errorData, trycatch, retry, queued, sleep, randomString, str, isObject, ToolRegistry, typo, and, Source, resolveDocuments, timeout, TIMEOUT_SYMBOL as TIMEOUT_SYMBOL$1, compose, BehaviorSubject, waitForNext, singlerun } from 'functools-kit';
|
|
5
5
|
import * as fs from 'fs/promises';
|
|
6
|
-
import fs__default
|
|
6
|
+
import fs__default from 'fs/promises';
|
|
7
7
|
import path, { join, dirname } from 'path';
|
|
8
8
|
import crypto from 'crypto';
|
|
9
9
|
import os from 'os';
|
|
@@ -36107,72 +36107,41 @@ const PRINT_PROGRESS_FN = (fetched, total, symbol, interval) => {
|
|
|
36107
36107
|
}
|
|
36108
36108
|
};
|
|
36109
36109
|
/**
|
|
36110
|
-
* Checks cached candle
|
|
36111
|
-
*
|
|
36110
|
+
* Checks cached candle presence via the persist adapter.
|
|
36111
|
+
* Issues one ranged read; adapter-side `hasValue` covers each expected timestamp,
|
|
36112
|
+
* so a single missing or unaligned candle yields a miss without loading the whole dataset.
|
|
36112
36113
|
*
|
|
36113
36114
|
* @param params - Validation parameters
|
|
36114
36115
|
*/
|
|
36115
36116
|
async function checkCandles(params) {
|
|
36116
|
-
const { symbol, exchangeName, interval, from, to
|
|
36117
|
+
const { symbol, exchangeName, interval, from, to } = params;
|
|
36117
36118
|
backtest.loggerService.info(CHECK_CANDLES_METHOD_NAME, params);
|
|
36118
36119
|
const step = INTERVAL_MINUTES$3[interval];
|
|
36119
36120
|
if (!step) {
|
|
36120
36121
|
throw new Error(`checkCandles: unsupported interval=${interval}`);
|
|
36121
36122
|
}
|
|
36122
36123
|
const stepMs = step * MS_PER_MINUTE$3;
|
|
36123
|
-
const dir = join(baseDir, exchangeName, symbol, interval);
|
|
36124
36124
|
const fromTs = ALIGN_TO_INTERVAL_FN(from.getTime(), step);
|
|
36125
36125
|
const toTs = ALIGN_TO_INTERVAL_FN(to.getTime(), step);
|
|
36126
|
-
|
|
36127
|
-
|
|
36128
|
-
|
|
36129
|
-
catch {
|
|
36130
|
-
throw new Error(`checkCandles: cache directory not found: ${dir}`);
|
|
36131
|
-
}
|
|
36132
|
-
// Collect only filenames (strings) in range via async iterator — no full readdir in memory
|
|
36133
|
-
const files = [];
|
|
36134
|
-
for await (const entry of await opendir(dir)) {
|
|
36135
|
-
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
36136
|
-
continue;
|
|
36137
|
-
}
|
|
36138
|
-
const ts = Number(entry.name.replace(".json", ""));
|
|
36139
|
-
if (ts >= fromTs && ts < toTs) {
|
|
36140
|
-
files.push(entry.name);
|
|
36141
|
-
}
|
|
36142
|
-
}
|
|
36143
|
-
if (files.length === 0) {
|
|
36144
|
-
throw new Error(`checkCandles: no cached candles in range [${fromTs}, ${toTs}) in ${dir}`);
|
|
36126
|
+
const totalCandles = Math.floor((toTs - fromTs) / stepMs);
|
|
36127
|
+
if (totalCandles <= 0) {
|
|
36128
|
+
throw new Error(`checkCandles: empty range [${fromTs}, ${toTs}) for ${symbol} ${interval}`);
|
|
36145
36129
|
}
|
|
36146
|
-
|
|
36147
|
-
let
|
|
36148
|
-
|
|
36149
|
-
|
|
36150
|
-
|
|
36151
|
-
const
|
|
36152
|
-
const
|
|
36153
|
-
|
|
36154
|
-
|
|
36155
|
-
candle = JSON.parse(raw);
|
|
36156
|
-
}
|
|
36157
|
-
catch {
|
|
36158
|
-
throw new Error(`checkCandles: ${files[i]} contains invalid JSON`);
|
|
36159
|
-
}
|
|
36160
|
-
const { timestamp } = candle;
|
|
36161
|
-
const aligned = ALIGN_TO_INTERVAL_FN(timestamp, step);
|
|
36162
|
-
if (timestamp !== aligned) {
|
|
36163
|
-
throw new Error(`checkCandles: ${files[i]} timestamp not aligned to ${interval} boundary (actual=${timestamp}, expected=${aligned})`);
|
|
36164
|
-
}
|
|
36165
|
-
if (prevTimestamp !== null) {
|
|
36166
|
-
const gap = timestamp - prevTimestamp;
|
|
36167
|
-
if (gap !== stepMs) {
|
|
36168
|
-
throw new Error(`checkCandles: gap between ${prevName} and ${files[i]} (actual=${gap}ms, expected=${stepMs}ms)`);
|
|
36169
|
-
}
|
|
36130
|
+
let checked = 0;
|
|
36131
|
+
let currentSince = fromTs;
|
|
36132
|
+
PRINT_PROGRESS_FN(checked, totalCandles, symbol, interval);
|
|
36133
|
+
while (checked < totalCandles) {
|
|
36134
|
+
const chunkLimit = Math.min(totalCandles - checked, GLOBAL_CONFIG.CC_MAX_CANDLES_PER_REQUEST);
|
|
36135
|
+
const chunkUntil = currentSince + chunkLimit * stepMs;
|
|
36136
|
+
const candles = await PersistCandleAdapter.readCandlesData(symbol, interval, exchangeName, chunkLimit, currentSince, chunkUntil);
|
|
36137
|
+
if (!candles) {
|
|
36138
|
+
throw new Error(`checkCandles: cache miss for ${symbol} ${interval} [${currentSince}, ${chunkUntil})`);
|
|
36170
36139
|
}
|
|
36171
|
-
|
|
36172
|
-
|
|
36173
|
-
PRINT_PROGRESS_FN(
|
|
36140
|
+
checked += chunkLimit;
|
|
36141
|
+
currentSince = chunkUntil;
|
|
36142
|
+
PRINT_PROGRESS_FN(checked, totalCandles, symbol, interval);
|
|
36174
36143
|
}
|
|
36175
|
-
console.log(`checkCandles: OK ${
|
|
36144
|
+
console.log(`checkCandles: OK ${totalCandles} candles ${symbol} ${interval}`);
|
|
36176
36145
|
}
|
|
36177
36146
|
/**
|
|
36178
36147
|
* Pre-caches candles for a date range into persist storage.
|
|
@@ -37423,7 +37392,19 @@ class BrokerProxy {
|
|
|
37423
37392
|
*/
|
|
37424
37393
|
class BrokerAdapter {
|
|
37425
37394
|
constructor() {
|
|
37426
|
-
|
|
37395
|
+
/** Factory producing the active `BrokerProxy` instance */
|
|
37396
|
+
this._brokerFactory = () => null;
|
|
37397
|
+
/**
|
|
37398
|
+
* Lazily constructs the `BrokerProxy` from the registered factory and
|
|
37399
|
+
* memoizes the result via `singleshot`.
|
|
37400
|
+
*
|
|
37401
|
+
* The proxy is built on the first call and cached for all subsequent calls.
|
|
37402
|
+
* Returns `null` when no adapter has been registered via `useBrokerAdapter()`.
|
|
37403
|
+
*
|
|
37404
|
+
* Reset via `clear()` so the next call rebuilds from the current factory
|
|
37405
|
+
* (e.g. when `process.cwd()` changes between strategy iterations).
|
|
37406
|
+
*/
|
|
37407
|
+
this.getInstance = singleshot(() => this._brokerFactory());
|
|
37427
37408
|
/**
|
|
37428
37409
|
* Forwards a signal-open event to the registered broker adapter.
|
|
37429
37410
|
*
|
|
@@ -37457,7 +37438,10 @@ class BrokerAdapter {
|
|
|
37457
37438
|
if (payload.backtest) {
|
|
37458
37439
|
return;
|
|
37459
37440
|
}
|
|
37460
|
-
|
|
37441
|
+
const instance = this.getInstance();
|
|
37442
|
+
if (instance) {
|
|
37443
|
+
await instance.onSignalOpenCommit(payload);
|
|
37444
|
+
}
|
|
37461
37445
|
};
|
|
37462
37446
|
/**
|
|
37463
37447
|
* Forwards a signal-close event to the registered broker adapter.
|
|
@@ -37495,7 +37479,10 @@ class BrokerAdapter {
|
|
|
37495
37479
|
if (payload.backtest) {
|
|
37496
37480
|
return;
|
|
37497
37481
|
}
|
|
37498
|
-
|
|
37482
|
+
const instance = this.getInstance();
|
|
37483
|
+
if (instance) {
|
|
37484
|
+
await instance.onSignalCloseCommit(payload);
|
|
37485
|
+
}
|
|
37499
37486
|
};
|
|
37500
37487
|
/**
|
|
37501
37488
|
* Intercepts a partial-profit close before DI-core mutation.
|
|
@@ -37531,7 +37518,10 @@ class BrokerAdapter {
|
|
|
37531
37518
|
if (payload.backtest) {
|
|
37532
37519
|
return;
|
|
37533
37520
|
}
|
|
37534
|
-
|
|
37521
|
+
const instance = this.getInstance();
|
|
37522
|
+
if (instance) {
|
|
37523
|
+
await instance.onPartialProfitCommit(payload);
|
|
37524
|
+
}
|
|
37535
37525
|
};
|
|
37536
37526
|
/**
|
|
37537
37527
|
* Intercepts a partial-loss close before DI-core mutation.
|
|
@@ -37567,7 +37557,10 @@ class BrokerAdapter {
|
|
|
37567
37557
|
if (payload.backtest) {
|
|
37568
37558
|
return;
|
|
37569
37559
|
}
|
|
37570
|
-
|
|
37560
|
+
const instance = this.getInstance();
|
|
37561
|
+
if (instance) {
|
|
37562
|
+
await instance.onPartialLossCommit(payload);
|
|
37563
|
+
}
|
|
37571
37564
|
};
|
|
37572
37565
|
/**
|
|
37573
37566
|
* Intercepts a trailing stop-loss update before DI-core mutation.
|
|
@@ -37603,7 +37596,10 @@ class BrokerAdapter {
|
|
|
37603
37596
|
if (payload.backtest) {
|
|
37604
37597
|
return;
|
|
37605
37598
|
}
|
|
37606
|
-
|
|
37599
|
+
const instance = this.getInstance();
|
|
37600
|
+
if (instance) {
|
|
37601
|
+
await instance.onTrailingStopCommit(payload);
|
|
37602
|
+
}
|
|
37607
37603
|
};
|
|
37608
37604
|
/**
|
|
37609
37605
|
* Intercepts a trailing take-profit update before DI-core mutation.
|
|
@@ -37639,7 +37635,10 @@ class BrokerAdapter {
|
|
|
37639
37635
|
if (payload.backtest) {
|
|
37640
37636
|
return;
|
|
37641
37637
|
}
|
|
37642
|
-
|
|
37638
|
+
const instance = this.getInstance();
|
|
37639
|
+
if (instance) {
|
|
37640
|
+
await instance.onTrailingTakeCommit(payload);
|
|
37641
|
+
}
|
|
37643
37642
|
};
|
|
37644
37643
|
/**
|
|
37645
37644
|
* Intercepts a breakeven operation before DI-core mutation.
|
|
@@ -37676,7 +37675,10 @@ class BrokerAdapter {
|
|
|
37676
37675
|
if (payload.backtest) {
|
|
37677
37676
|
return;
|
|
37678
37677
|
}
|
|
37679
|
-
|
|
37678
|
+
const instance = this.getInstance();
|
|
37679
|
+
if (instance) {
|
|
37680
|
+
await instance.onBreakevenCommit(payload);
|
|
37681
|
+
}
|
|
37680
37682
|
};
|
|
37681
37683
|
/**
|
|
37682
37684
|
* Intercepts a DCA average-buy entry before DI-core mutation.
|
|
@@ -37712,7 +37714,10 @@ class BrokerAdapter {
|
|
|
37712
37714
|
if (payload.backtest) {
|
|
37713
37715
|
return;
|
|
37714
37716
|
}
|
|
37715
|
-
|
|
37717
|
+
const instance = this.getInstance();
|
|
37718
|
+
if (instance) {
|
|
37719
|
+
await instance.onAverageBuyCommit(payload);
|
|
37720
|
+
}
|
|
37716
37721
|
};
|
|
37717
37722
|
/**
|
|
37718
37723
|
* Registers a broker adapter instance or constructor to receive commit* callbacks.
|
|
@@ -37736,11 +37741,12 @@ class BrokerAdapter {
|
|
|
37736
37741
|
this.useBrokerAdapter = (broker) => {
|
|
37737
37742
|
backtest.loggerService.info(BROKER_METHOD_NAME_USE_BROKER_ADAPTER, {});
|
|
37738
37743
|
if (typeof broker === "function") {
|
|
37739
|
-
|
|
37740
|
-
|
|
37741
|
-
|
|
37744
|
+
this._brokerFactory = () => new BrokerProxy(Reflect.construct(broker, []));
|
|
37745
|
+
}
|
|
37746
|
+
else {
|
|
37747
|
+
this._brokerFactory = () => new BrokerProxy(broker);
|
|
37742
37748
|
}
|
|
37743
|
-
this.
|
|
37749
|
+
this.getInstance.clear();
|
|
37744
37750
|
};
|
|
37745
37751
|
/**
|
|
37746
37752
|
* Activates the broker: subscribes to syncSubject for signal-open / signal-close routing.
|
|
@@ -37767,7 +37773,8 @@ class BrokerAdapter {
|
|
|
37767
37773
|
*/
|
|
37768
37774
|
this.enable = singleshot(() => {
|
|
37769
37775
|
backtest.loggerService.info(BROKER_METHOD_NAME_ENABLE, {});
|
|
37770
|
-
|
|
37776
|
+
const instance = this.getInstance();
|
|
37777
|
+
if (!instance) {
|
|
37771
37778
|
this.enable.clear();
|
|
37772
37779
|
throw new Error("No broker instance provided. Call Broker.useBrokerAdapter first.");
|
|
37773
37780
|
}
|
|
@@ -37855,7 +37862,7 @@ class BrokerAdapter {
|
|
|
37855
37862
|
*/
|
|
37856
37863
|
this.clear = () => {
|
|
37857
37864
|
backtest.loggerService.info(BROKER_METHOD_NAME_CLEAR, {});
|
|
37858
|
-
this.
|
|
37865
|
+
this.getInstance.clear();
|
|
37859
37866
|
this.enable.clear();
|
|
37860
37867
|
};
|
|
37861
37868
|
}
|
|
@@ -48875,8 +48882,16 @@ class RecentMemoryLiveUtils {
|
|
|
48875
48882
|
*/
|
|
48876
48883
|
class RecentBacktestAdapter {
|
|
48877
48884
|
constructor() {
|
|
48878
|
-
/**
|
|
48879
|
-
this.
|
|
48885
|
+
/** Factory producing the active storage utils instance */
|
|
48886
|
+
this._recentBacktestFactory = () => new RecentMemoryBacktestUtils();
|
|
48887
|
+
/**
|
|
48888
|
+
* Lazily constructs the storage utils from the registered factory and memoizes
|
|
48889
|
+
* the result via `singleshot`.
|
|
48890
|
+
*
|
|
48891
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
48892
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
48893
|
+
*/
|
|
48894
|
+
this.getInstance = singleshot(() => this._recentBacktestFactory());
|
|
48880
48895
|
/**
|
|
48881
48896
|
* Handles active ping event.
|
|
48882
48897
|
* Proxies call to the underlying storage adapter.
|
|
@@ -48886,7 +48901,7 @@ class RecentBacktestAdapter {
|
|
|
48886
48901
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_HANDLE_ACTIVE_PING, {
|
|
48887
48902
|
signalId: event.data.id,
|
|
48888
48903
|
});
|
|
48889
|
-
return await this.
|
|
48904
|
+
return await this.getInstance().handleActivePing(event);
|
|
48890
48905
|
};
|
|
48891
48906
|
/**
|
|
48892
48907
|
* Retrieves the latest signal for the given context.
|
|
@@ -48907,7 +48922,7 @@ class RecentBacktestAdapter {
|
|
|
48907
48922
|
frameName,
|
|
48908
48923
|
backtest: backtest$1,
|
|
48909
48924
|
});
|
|
48910
|
-
return await this.
|
|
48925
|
+
return await this.getInstance().getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1, when);
|
|
48911
48926
|
};
|
|
48912
48927
|
/**
|
|
48913
48928
|
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
@@ -48931,7 +48946,7 @@ class RecentBacktestAdapter {
|
|
|
48931
48946
|
backtest: backtest$1,
|
|
48932
48947
|
timestamp,
|
|
48933
48948
|
});
|
|
48934
|
-
const signal = await this.
|
|
48949
|
+
const signal = await this.getInstance().getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1, new Date(timestamp));
|
|
48935
48950
|
if (!signal) {
|
|
48936
48951
|
return null;
|
|
48937
48952
|
}
|
|
@@ -48944,7 +48959,8 @@ class RecentBacktestAdapter {
|
|
|
48944
48959
|
*/
|
|
48945
48960
|
this.useRecentAdapter = (Ctor) => {
|
|
48946
48961
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
48947
|
-
this.
|
|
48962
|
+
this._recentBacktestFactory = () => Reflect.construct(Ctor, []);
|
|
48963
|
+
this.getInstance.clear();
|
|
48948
48964
|
};
|
|
48949
48965
|
/**
|
|
48950
48966
|
* Switches to persistent storage adapter.
|
|
@@ -48952,7 +48968,8 @@ class RecentBacktestAdapter {
|
|
|
48952
48968
|
*/
|
|
48953
48969
|
this.usePersist = () => {
|
|
48954
48970
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
48955
|
-
this.
|
|
48971
|
+
this._recentBacktestFactory = () => new RecentPersistBacktestUtils();
|
|
48972
|
+
this.getInstance.clear();
|
|
48956
48973
|
};
|
|
48957
48974
|
/**
|
|
48958
48975
|
* Switches to in-memory storage adapter (default).
|
|
@@ -48960,14 +48977,17 @@ class RecentBacktestAdapter {
|
|
|
48960
48977
|
*/
|
|
48961
48978
|
this.useMemory = () => {
|
|
48962
48979
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
48963
|
-
this.
|
|
48980
|
+
this._recentBacktestFactory = () => new RecentMemoryBacktestUtils();
|
|
48981
|
+
this.getInstance.clear();
|
|
48964
48982
|
};
|
|
48965
48983
|
/**
|
|
48966
|
-
* Clears the
|
|
48984
|
+
* Clears the memoized utils instance.
|
|
48985
|
+
* Call this when process.cwd() changes between strategy iterations
|
|
48986
|
+
* so a new instance is created with the updated base path.
|
|
48967
48987
|
*/
|
|
48968
48988
|
this.clear = () => {
|
|
48969
48989
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_CLEAR);
|
|
48970
|
-
this.
|
|
48990
|
+
this.getInstance.clear();
|
|
48971
48991
|
};
|
|
48972
48992
|
}
|
|
48973
48993
|
}
|
|
@@ -48982,8 +49002,16 @@ class RecentBacktestAdapter {
|
|
|
48982
49002
|
*/
|
|
48983
49003
|
class RecentLiveAdapter {
|
|
48984
49004
|
constructor() {
|
|
48985
|
-
/**
|
|
48986
|
-
this.
|
|
49005
|
+
/** Factory producing the active storage utils instance */
|
|
49006
|
+
this._recentLiveFactory = () => new RecentPersistLiveUtils();
|
|
49007
|
+
/**
|
|
49008
|
+
* Lazily constructs the storage utils from the registered factory and memoizes
|
|
49009
|
+
* the result via `singleshot`.
|
|
49010
|
+
*
|
|
49011
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
49012
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
49013
|
+
*/
|
|
49014
|
+
this.getInstance = singleshot(() => this._recentLiveFactory());
|
|
48987
49015
|
/**
|
|
48988
49016
|
* Handles active ping event.
|
|
48989
49017
|
* Proxies call to the underlying storage adapter.
|
|
@@ -48993,7 +49021,7 @@ class RecentLiveAdapter {
|
|
|
48993
49021
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_HANDLE_ACTIVE_PING, {
|
|
48994
49022
|
signalId: event.data.id,
|
|
48995
49023
|
});
|
|
48996
|
-
return await this.
|
|
49024
|
+
return await this.getInstance().handleActivePing(event);
|
|
48997
49025
|
};
|
|
48998
49026
|
/**
|
|
48999
49027
|
* Retrieves the latest signal for the given context.
|
|
@@ -49014,7 +49042,7 @@ class RecentLiveAdapter {
|
|
|
49014
49042
|
frameName,
|
|
49015
49043
|
backtest: backtest$1,
|
|
49016
49044
|
});
|
|
49017
|
-
return await this.
|
|
49045
|
+
return await this.getInstance().getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1, when);
|
|
49018
49046
|
};
|
|
49019
49047
|
/**
|
|
49020
49048
|
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
@@ -49038,7 +49066,7 @@ class RecentLiveAdapter {
|
|
|
49038
49066
|
backtest: backtest$1,
|
|
49039
49067
|
timestamp,
|
|
49040
49068
|
});
|
|
49041
|
-
const signal = await this.
|
|
49069
|
+
const signal = await this.getInstance().getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1, new Date(timestamp));
|
|
49042
49070
|
if (!signal) {
|
|
49043
49071
|
return null;
|
|
49044
49072
|
}
|
|
@@ -49051,7 +49079,8 @@ class RecentLiveAdapter {
|
|
|
49051
49079
|
*/
|
|
49052
49080
|
this.useRecentAdapter = (Ctor) => {
|
|
49053
49081
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
49054
|
-
this.
|
|
49082
|
+
this._recentLiveFactory = () => Reflect.construct(Ctor, []);
|
|
49083
|
+
this.getInstance.clear();
|
|
49055
49084
|
};
|
|
49056
49085
|
/**
|
|
49057
49086
|
* Switches to persistent storage adapter (default).
|
|
@@ -49059,7 +49088,8 @@ class RecentLiveAdapter {
|
|
|
49059
49088
|
*/
|
|
49060
49089
|
this.usePersist = () => {
|
|
49061
49090
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
49062
|
-
this.
|
|
49091
|
+
this._recentLiveFactory = () => new RecentPersistLiveUtils();
|
|
49092
|
+
this.getInstance.clear();
|
|
49063
49093
|
};
|
|
49064
49094
|
/**
|
|
49065
49095
|
* Switches to in-memory storage adapter.
|
|
@@ -49067,14 +49097,17 @@ class RecentLiveAdapter {
|
|
|
49067
49097
|
*/
|
|
49068
49098
|
this.useMemory = () => {
|
|
49069
49099
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
49070
|
-
this.
|
|
49100
|
+
this._recentLiveFactory = () => new RecentMemoryLiveUtils();
|
|
49101
|
+
this.getInstance.clear();
|
|
49071
49102
|
};
|
|
49072
49103
|
/**
|
|
49073
|
-
* Clears the
|
|
49104
|
+
* Clears the memoized utils instance.
|
|
49105
|
+
* Call this when process.cwd() changes between strategy iterations
|
|
49106
|
+
* so a new instance is created with the updated base path.
|
|
49074
49107
|
*/
|
|
49075
49108
|
this.clear = () => {
|
|
49076
49109
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_CLEAR);
|
|
49077
|
-
this.
|
|
49110
|
+
this.getInstance.clear();
|
|
49078
49111
|
};
|
|
49079
49112
|
}
|
|
49080
49113
|
}
|
|
@@ -54399,16 +54432,26 @@ class LogDummyUtils {
|
|
|
54399
54432
|
*/
|
|
54400
54433
|
class LogAdapter {
|
|
54401
54434
|
constructor() {
|
|
54402
|
-
/**
|
|
54403
|
-
this.
|
|
54435
|
+
/** Factory producing the active log utils instance */
|
|
54436
|
+
this._logFactory = () => new LogMemoryUtils();
|
|
54437
|
+
/**
|
|
54438
|
+
* Lazily constructs the log utils from the registered factory and memoizes
|
|
54439
|
+
* the result via `singleshot`.
|
|
54440
|
+
*
|
|
54441
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
54442
|
+
* Reset via `clear()` so the next call rebuilds from the current factory
|
|
54443
|
+
* (e.g. when `process.cwd()` changes between strategy iterations).
|
|
54444
|
+
*/
|
|
54445
|
+
this.getInstance = singleshot(() => this._logFactory());
|
|
54404
54446
|
/**
|
|
54405
54447
|
* Lists all stored log entries.
|
|
54406
54448
|
* Proxies call to the underlying log adapter.
|
|
54407
54449
|
* @returns Array of all log entries
|
|
54408
54450
|
*/
|
|
54409
54451
|
this.getList = async () => {
|
|
54410
|
-
|
|
54411
|
-
|
|
54452
|
+
const log = this.getInstance();
|
|
54453
|
+
if (log.getList) {
|
|
54454
|
+
return await log.getList();
|
|
54412
54455
|
}
|
|
54413
54456
|
return [];
|
|
54414
54457
|
};
|
|
@@ -54419,8 +54462,9 @@ class LogAdapter {
|
|
|
54419
54462
|
* @param args - Additional arguments
|
|
54420
54463
|
*/
|
|
54421
54464
|
this.log = (topic, ...args) => {
|
|
54422
|
-
|
|
54423
|
-
|
|
54465
|
+
const log = this.getInstance();
|
|
54466
|
+
if (log.log) {
|
|
54467
|
+
log.log(topic, ...args);
|
|
54424
54468
|
}
|
|
54425
54469
|
};
|
|
54426
54470
|
/**
|
|
@@ -54430,8 +54474,9 @@ class LogAdapter {
|
|
|
54430
54474
|
* @param args - Additional arguments
|
|
54431
54475
|
*/
|
|
54432
54476
|
this.debug = (topic, ...args) => {
|
|
54433
|
-
|
|
54434
|
-
|
|
54477
|
+
const log = this.getInstance();
|
|
54478
|
+
if (log.debug) {
|
|
54479
|
+
log.debug(topic, ...args);
|
|
54435
54480
|
}
|
|
54436
54481
|
};
|
|
54437
54482
|
/**
|
|
@@ -54441,8 +54486,9 @@ class LogAdapter {
|
|
|
54441
54486
|
* @param args - Additional arguments
|
|
54442
54487
|
*/
|
|
54443
54488
|
this.info = (topic, ...args) => {
|
|
54444
|
-
|
|
54445
|
-
|
|
54489
|
+
const log = this.getInstance();
|
|
54490
|
+
if (log.info) {
|
|
54491
|
+
log.info(topic, ...args);
|
|
54446
54492
|
}
|
|
54447
54493
|
};
|
|
54448
54494
|
/**
|
|
@@ -54452,8 +54498,9 @@ class LogAdapter {
|
|
|
54452
54498
|
* @param args - Additional arguments
|
|
54453
54499
|
*/
|
|
54454
54500
|
this.warn = (topic, ...args) => {
|
|
54455
|
-
|
|
54456
|
-
|
|
54501
|
+
const log = this.getInstance();
|
|
54502
|
+
if (log.warn) {
|
|
54503
|
+
log.warn(topic, ...args);
|
|
54457
54504
|
}
|
|
54458
54505
|
};
|
|
54459
54506
|
/**
|
|
@@ -54463,7 +54510,8 @@ class LogAdapter {
|
|
|
54463
54510
|
*/
|
|
54464
54511
|
this.useLogger = (Ctor) => {
|
|
54465
54512
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_LOGGER);
|
|
54466
|
-
this.
|
|
54513
|
+
this._logFactory = () => Reflect.construct(Ctor, []);
|
|
54514
|
+
this.getInstance.clear();
|
|
54467
54515
|
};
|
|
54468
54516
|
/**
|
|
54469
54517
|
* Switches to persistent log adapter.
|
|
@@ -54471,7 +54519,8 @@ class LogAdapter {
|
|
|
54471
54519
|
*/
|
|
54472
54520
|
this.usePersist = () => {
|
|
54473
54521
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
54474
|
-
this.
|
|
54522
|
+
this._logFactory = () => new LogPersistUtils();
|
|
54523
|
+
this.getInstance.clear();
|
|
54475
54524
|
};
|
|
54476
54525
|
/**
|
|
54477
54526
|
* Switches to in-memory log adapter (default).
|
|
@@ -54479,7 +54528,8 @@ class LogAdapter {
|
|
|
54479
54528
|
*/
|
|
54480
54529
|
this.useMemory = () => {
|
|
54481
54530
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
54482
|
-
this.
|
|
54531
|
+
this._logFactory = () => new LogMemoryUtils();
|
|
54532
|
+
this.getInstance.clear();
|
|
54483
54533
|
};
|
|
54484
54534
|
/**
|
|
54485
54535
|
* Switches to dummy log adapter.
|
|
@@ -54487,7 +54537,8 @@ class LogAdapter {
|
|
|
54487
54537
|
*/
|
|
54488
54538
|
this.useDummy = () => {
|
|
54489
54539
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
54490
|
-
this.
|
|
54540
|
+
this._logFactory = () => new LogDummyUtils();
|
|
54541
|
+
this.getInstance.clear();
|
|
54491
54542
|
};
|
|
54492
54543
|
/**
|
|
54493
54544
|
* Switches to JSONL file log adapter.
|
|
@@ -54497,18 +54548,22 @@ class LogAdapter {
|
|
|
54497
54548
|
* @param fileName - Base file name without extension (default: "log")
|
|
54498
54549
|
* @param dirName - Directory for the JSONL file (default: ./dump/log)
|
|
54499
54550
|
*/
|
|
54500
|
-
this.useJsonl = (fileName = "log.jsonl", dirName
|
|
54551
|
+
this.useJsonl = (fileName = "log.jsonl", dirName) => {
|
|
54501
54552
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_JSONL);
|
|
54502
|
-
this.
|
|
54553
|
+
this._logFactory = () => {
|
|
54554
|
+
const dir = dirName || join(process.cwd(), "./dump/log");
|
|
54555
|
+
return new LogJsonlUtils(fileName, dir);
|
|
54556
|
+
};
|
|
54557
|
+
this.getInstance.clear();
|
|
54503
54558
|
};
|
|
54504
54559
|
/**
|
|
54505
|
-
* Clears the
|
|
54560
|
+
* Clears the memoized log instance.
|
|
54506
54561
|
* Call this when process.cwd() changes between strategy iterations
|
|
54507
54562
|
* so a new adapter instance is created with the updated base path.
|
|
54508
54563
|
*/
|
|
54509
54564
|
this.clear = () => {
|
|
54510
54565
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_CLEAR);
|
|
54511
|
-
this.
|
|
54566
|
+
this.getInstance.clear();
|
|
54512
54567
|
};
|
|
54513
54568
|
}
|
|
54514
54569
|
}
|
|
@@ -58400,15 +58455,23 @@ class StorageDummyLiveUtils {
|
|
|
58400
58455
|
*/
|
|
58401
58456
|
class StorageBacktestAdapter {
|
|
58402
58457
|
constructor() {
|
|
58403
|
-
/**
|
|
58404
|
-
this.
|
|
58458
|
+
/** Factory producing the active storage utils instance */
|
|
58459
|
+
this._signalBacktestFactory = () => new StorageMemoryBacktestUtils();
|
|
58460
|
+
/**
|
|
58461
|
+
* Lazily constructs the storage utils from the registered factory and memoizes
|
|
58462
|
+
* the result via `singleshot`.
|
|
58463
|
+
*
|
|
58464
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
58465
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
58466
|
+
*/
|
|
58467
|
+
this.getInstance = singleshot(() => this._signalBacktestFactory());
|
|
58405
58468
|
/**
|
|
58406
58469
|
* Handles signal opened event.
|
|
58407
58470
|
* Proxies call to the underlying storage adapter.
|
|
58408
58471
|
* @param tick - The opened signal tick data
|
|
58409
58472
|
*/
|
|
58410
58473
|
this.handleOpened = async (tick) => {
|
|
58411
|
-
return await this.
|
|
58474
|
+
return await this.getInstance().handleOpened(tick);
|
|
58412
58475
|
};
|
|
58413
58476
|
/**
|
|
58414
58477
|
* Handles signal closed event.
|
|
@@ -58416,7 +58479,7 @@ class StorageBacktestAdapter {
|
|
|
58416
58479
|
* @param tick - The closed signal tick data
|
|
58417
58480
|
*/
|
|
58418
58481
|
this.handleClosed = async (tick) => {
|
|
58419
|
-
return await this.
|
|
58482
|
+
return await this.getInstance().handleClosed(tick);
|
|
58420
58483
|
};
|
|
58421
58484
|
/**
|
|
58422
58485
|
* Handles signal scheduled event.
|
|
@@ -58424,7 +58487,7 @@ class StorageBacktestAdapter {
|
|
|
58424
58487
|
* @param tick - The scheduled signal tick data
|
|
58425
58488
|
*/
|
|
58426
58489
|
this.handleScheduled = async (tick) => {
|
|
58427
|
-
return await this.
|
|
58490
|
+
return await this.getInstance().handleScheduled(tick);
|
|
58428
58491
|
};
|
|
58429
58492
|
/**
|
|
58430
58493
|
* Handles signal cancelled event.
|
|
@@ -58432,7 +58495,7 @@ class StorageBacktestAdapter {
|
|
|
58432
58495
|
* @param tick - The cancelled signal tick data
|
|
58433
58496
|
*/
|
|
58434
58497
|
this.handleCancelled = async (tick) => {
|
|
58435
|
-
return await this.
|
|
58498
|
+
return await this.getInstance().handleCancelled(tick);
|
|
58436
58499
|
};
|
|
58437
58500
|
/**
|
|
58438
58501
|
* Finds a signal by its ID.
|
|
@@ -58441,7 +58504,7 @@ class StorageBacktestAdapter {
|
|
|
58441
58504
|
* @returns The signal row or null if not found
|
|
58442
58505
|
*/
|
|
58443
58506
|
this.findById = async (id) => {
|
|
58444
|
-
return await this.
|
|
58507
|
+
return await this.getInstance().findById(id);
|
|
58445
58508
|
};
|
|
58446
58509
|
/**
|
|
58447
58510
|
* Lists all stored signals.
|
|
@@ -58449,13 +58512,13 @@ class StorageBacktestAdapter {
|
|
|
58449
58512
|
* @returns Array of all signal rows
|
|
58450
58513
|
*/
|
|
58451
58514
|
this.list = async () => {
|
|
58452
|
-
return await this.
|
|
58515
|
+
return await this.getInstance().list();
|
|
58453
58516
|
};
|
|
58454
58517
|
this.handleActivePing = async (event) => {
|
|
58455
|
-
return await this.
|
|
58518
|
+
return await this.getInstance().handleActivePing(event);
|
|
58456
58519
|
};
|
|
58457
58520
|
this.handleSchedulePing = async (event) => {
|
|
58458
|
-
return await this.
|
|
58521
|
+
return await this.getInstance().handleSchedulePing(event);
|
|
58459
58522
|
};
|
|
58460
58523
|
/**
|
|
58461
58524
|
* Sets the storage adapter constructor.
|
|
@@ -58465,7 +58528,8 @@ class StorageBacktestAdapter {
|
|
|
58465
58528
|
*/
|
|
58466
58529
|
this.useStorageAdapter = (Ctor) => {
|
|
58467
58530
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
58468
|
-
this.
|
|
58531
|
+
this._signalBacktestFactory = () => Reflect.construct(Ctor, []);
|
|
58532
|
+
this.getInstance.clear();
|
|
58469
58533
|
};
|
|
58470
58534
|
/**
|
|
58471
58535
|
* Switches to dummy storage adapter.
|
|
@@ -58473,7 +58537,8 @@ class StorageBacktestAdapter {
|
|
|
58473
58537
|
*/
|
|
58474
58538
|
this.useDummy = () => {
|
|
58475
58539
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
58476
|
-
this.
|
|
58540
|
+
this._signalBacktestFactory = () => new StorageDummyBacktestUtils();
|
|
58541
|
+
this.getInstance.clear();
|
|
58477
58542
|
};
|
|
58478
58543
|
/**
|
|
58479
58544
|
* Switches to persistent storage adapter (default).
|
|
@@ -58481,7 +58546,8 @@ class StorageBacktestAdapter {
|
|
|
58481
58546
|
*/
|
|
58482
58547
|
this.usePersist = () => {
|
|
58483
58548
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
58484
|
-
this.
|
|
58549
|
+
this._signalBacktestFactory = () => new StoragePersistBacktestUtils();
|
|
58550
|
+
this.getInstance.clear();
|
|
58485
58551
|
};
|
|
58486
58552
|
/**
|
|
58487
58553
|
* Switches to in-memory storage adapter.
|
|
@@ -58489,16 +58555,17 @@ class StorageBacktestAdapter {
|
|
|
58489
58555
|
*/
|
|
58490
58556
|
this.useMemory = () => {
|
|
58491
58557
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
58492
|
-
this.
|
|
58558
|
+
this._signalBacktestFactory = () => new StorageMemoryBacktestUtils();
|
|
58559
|
+
this.getInstance.clear();
|
|
58493
58560
|
};
|
|
58494
58561
|
/**
|
|
58495
|
-
* Clears the
|
|
58562
|
+
* Clears the memoized utils instance.
|
|
58496
58563
|
* Call this when process.cwd() changes between strategy iterations
|
|
58497
58564
|
* so a new instance is created with the updated base path.
|
|
58498
58565
|
*/
|
|
58499
58566
|
this.clear = () => {
|
|
58500
58567
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_CLEAR);
|
|
58501
|
-
this.
|
|
58568
|
+
this.getInstance.clear();
|
|
58502
58569
|
};
|
|
58503
58570
|
}
|
|
58504
58571
|
}
|
|
@@ -58513,15 +58580,23 @@ class StorageBacktestAdapter {
|
|
|
58513
58580
|
*/
|
|
58514
58581
|
class StorageLiveAdapter {
|
|
58515
58582
|
constructor() {
|
|
58516
|
-
/**
|
|
58517
|
-
this.
|
|
58583
|
+
/** Factory producing the active storage utils instance */
|
|
58584
|
+
this._signalLiveFactory = () => new StoragePersistLiveUtils();
|
|
58585
|
+
/**
|
|
58586
|
+
* Lazily constructs the storage utils from the registered factory and memoizes
|
|
58587
|
+
* the result via `singleshot`.
|
|
58588
|
+
*
|
|
58589
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
58590
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
58591
|
+
*/
|
|
58592
|
+
this.getInstance = singleshot(() => this._signalLiveFactory());
|
|
58518
58593
|
/**
|
|
58519
58594
|
* Handles signal opened event.
|
|
58520
58595
|
* Proxies call to the underlying storage adapter.
|
|
58521
58596
|
* @param tick - The opened signal tick data
|
|
58522
58597
|
*/
|
|
58523
58598
|
this.handleOpened = async (tick) => {
|
|
58524
|
-
return await this.
|
|
58599
|
+
return await this.getInstance().handleOpened(tick);
|
|
58525
58600
|
};
|
|
58526
58601
|
/**
|
|
58527
58602
|
* Handles signal closed event.
|
|
@@ -58529,7 +58604,7 @@ class StorageLiveAdapter {
|
|
|
58529
58604
|
* @param tick - The closed signal tick data
|
|
58530
58605
|
*/
|
|
58531
58606
|
this.handleClosed = async (tick) => {
|
|
58532
|
-
return await this.
|
|
58607
|
+
return await this.getInstance().handleClosed(tick);
|
|
58533
58608
|
};
|
|
58534
58609
|
/**
|
|
58535
58610
|
* Handles signal scheduled event.
|
|
@@ -58537,7 +58612,7 @@ class StorageLiveAdapter {
|
|
|
58537
58612
|
* @param tick - The scheduled signal tick data
|
|
58538
58613
|
*/
|
|
58539
58614
|
this.handleScheduled = async (tick) => {
|
|
58540
|
-
return await this.
|
|
58615
|
+
return await this.getInstance().handleScheduled(tick);
|
|
58541
58616
|
};
|
|
58542
58617
|
/**
|
|
58543
58618
|
* Handles signal cancelled event.
|
|
@@ -58545,7 +58620,7 @@ class StorageLiveAdapter {
|
|
|
58545
58620
|
* @param tick - The cancelled signal tick data
|
|
58546
58621
|
*/
|
|
58547
58622
|
this.handleCancelled = async (tick) => {
|
|
58548
|
-
return await this.
|
|
58623
|
+
return await this.getInstance().handleCancelled(tick);
|
|
58549
58624
|
};
|
|
58550
58625
|
/**
|
|
58551
58626
|
* Finds a signal by its ID.
|
|
@@ -58554,7 +58629,7 @@ class StorageLiveAdapter {
|
|
|
58554
58629
|
* @returns The signal row or null if not found
|
|
58555
58630
|
*/
|
|
58556
58631
|
this.findById = async (id) => {
|
|
58557
|
-
return await this.
|
|
58632
|
+
return await this.getInstance().findById(id);
|
|
58558
58633
|
};
|
|
58559
58634
|
/**
|
|
58560
58635
|
* Lists all stored signals.
|
|
@@ -58562,13 +58637,13 @@ class StorageLiveAdapter {
|
|
|
58562
58637
|
* @returns Array of all signal rows
|
|
58563
58638
|
*/
|
|
58564
58639
|
this.list = async () => {
|
|
58565
|
-
return await this.
|
|
58640
|
+
return await this.getInstance().list();
|
|
58566
58641
|
};
|
|
58567
58642
|
this.handleActivePing = async (event) => {
|
|
58568
|
-
return await this.
|
|
58643
|
+
return await this.getInstance().handleActivePing(event);
|
|
58569
58644
|
};
|
|
58570
58645
|
this.handleSchedulePing = async (event) => {
|
|
58571
|
-
return await this.
|
|
58646
|
+
return await this.getInstance().handleSchedulePing(event);
|
|
58572
58647
|
};
|
|
58573
58648
|
/**
|
|
58574
58649
|
* Sets the storage adapter constructor.
|
|
@@ -58578,7 +58653,8 @@ class StorageLiveAdapter {
|
|
|
58578
58653
|
*/
|
|
58579
58654
|
this.useStorageAdapter = (Ctor) => {
|
|
58580
58655
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
58581
|
-
this.
|
|
58656
|
+
this._signalLiveFactory = () => Reflect.construct(Ctor, []);
|
|
58657
|
+
this.getInstance.clear();
|
|
58582
58658
|
};
|
|
58583
58659
|
/**
|
|
58584
58660
|
* Switches to dummy storage adapter.
|
|
@@ -58586,7 +58662,8 @@ class StorageLiveAdapter {
|
|
|
58586
58662
|
*/
|
|
58587
58663
|
this.useDummy = () => {
|
|
58588
58664
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
58589
|
-
this.
|
|
58665
|
+
this._signalLiveFactory = () => new StorageDummyLiveUtils();
|
|
58666
|
+
this.getInstance.clear();
|
|
58590
58667
|
};
|
|
58591
58668
|
/**
|
|
58592
58669
|
* Switches to persistent storage adapter (default).
|
|
@@ -58594,7 +58671,8 @@ class StorageLiveAdapter {
|
|
|
58594
58671
|
*/
|
|
58595
58672
|
this.usePersist = () => {
|
|
58596
58673
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
58597
|
-
this.
|
|
58674
|
+
this._signalLiveFactory = () => new StoragePersistLiveUtils();
|
|
58675
|
+
this.getInstance.clear();
|
|
58598
58676
|
};
|
|
58599
58677
|
/**
|
|
58600
58678
|
* Switches to in-memory storage adapter.
|
|
@@ -58602,16 +58680,17 @@ class StorageLiveAdapter {
|
|
|
58602
58680
|
*/
|
|
58603
58681
|
this.useMemory = () => {
|
|
58604
58682
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
58605
|
-
this.
|
|
58683
|
+
this._signalLiveFactory = () => new StorageMemoryLiveUtils();
|
|
58684
|
+
this.getInstance.clear();
|
|
58606
58685
|
};
|
|
58607
58686
|
/**
|
|
58608
|
-
* Clears the
|
|
58687
|
+
* Clears the memoized utils instance.
|
|
58609
58688
|
* Call this when process.cwd() changes between strategy iterations
|
|
58610
58689
|
* so a new instance is created with the updated base path.
|
|
58611
58690
|
*/
|
|
58612
58691
|
this.clear = () => {
|
|
58613
58692
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_CLEAR);
|
|
58614
|
-
this.
|
|
58693
|
+
this.getInstance.clear();
|
|
58615
58694
|
};
|
|
58616
58695
|
}
|
|
58617
58696
|
}
|
|
@@ -60727,18 +60806,26 @@ class NotificationPersistLiveUtils {
|
|
|
60727
60806
|
*/
|
|
60728
60807
|
class NotificationBacktestAdapter {
|
|
60729
60808
|
constructor() {
|
|
60730
|
-
/**
|
|
60731
|
-
this.
|
|
60809
|
+
/** Factory producing the active notification utils instance */
|
|
60810
|
+
this._notificationBacktestFactory = () => new NotificationMemoryBacktestUtils();
|
|
60811
|
+
/**
|
|
60812
|
+
* Lazily constructs the notification utils from the registered factory and
|
|
60813
|
+
* memoizes the result via `singleshot`.
|
|
60814
|
+
*
|
|
60815
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
60816
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
60817
|
+
*/
|
|
60818
|
+
this.getInstance = singleshot(() => this._notificationBacktestFactory());
|
|
60732
60819
|
/**
|
|
60733
60820
|
* Handles signal events.
|
|
60734
60821
|
* Proxies call to the underlying notification adapter.
|
|
60735
60822
|
* @param data - The strategy tick result data
|
|
60736
60823
|
*/
|
|
60737
60824
|
this.handleSignal = async (data) => {
|
|
60738
|
-
return await this.
|
|
60825
|
+
return await this.getInstance().handleSignal(data);
|
|
60739
60826
|
};
|
|
60740
60827
|
this.handleSignalNotify = async (data) => {
|
|
60741
|
-
return await this.
|
|
60828
|
+
return await this.getInstance().handleSignalNotify(data);
|
|
60742
60829
|
};
|
|
60743
60830
|
/**
|
|
60744
60831
|
* Handles partial profit availability event.
|
|
@@ -60746,7 +60833,7 @@ class NotificationBacktestAdapter {
|
|
|
60746
60833
|
* @param data - The partial profit contract data
|
|
60747
60834
|
*/
|
|
60748
60835
|
this.handlePartialProfit = async (data) => {
|
|
60749
|
-
return await this.
|
|
60836
|
+
return await this.getInstance().handlePartialProfit(data);
|
|
60750
60837
|
};
|
|
60751
60838
|
/**
|
|
60752
60839
|
* Handles partial loss availability event.
|
|
@@ -60754,7 +60841,7 @@ class NotificationBacktestAdapter {
|
|
|
60754
60841
|
* @param data - The partial loss contract data
|
|
60755
60842
|
*/
|
|
60756
60843
|
this.handlePartialLoss = async (data) => {
|
|
60757
|
-
return await this.
|
|
60844
|
+
return await this.getInstance().handlePartialLoss(data);
|
|
60758
60845
|
};
|
|
60759
60846
|
/**
|
|
60760
60847
|
* Handles breakeven availability event.
|
|
@@ -60762,7 +60849,7 @@ class NotificationBacktestAdapter {
|
|
|
60762
60849
|
* @param data - The breakeven contract data
|
|
60763
60850
|
*/
|
|
60764
60851
|
this.handleBreakeven = async (data) => {
|
|
60765
|
-
return await this.
|
|
60852
|
+
return await this.getInstance().handleBreakeven(data);
|
|
60766
60853
|
};
|
|
60767
60854
|
/**
|
|
60768
60855
|
* Handles strategy commit events.
|
|
@@ -60770,7 +60857,7 @@ class NotificationBacktestAdapter {
|
|
|
60770
60857
|
* @param data - The strategy commit contract data
|
|
60771
60858
|
*/
|
|
60772
60859
|
this.handleStrategyCommit = async (data) => {
|
|
60773
|
-
return await this.
|
|
60860
|
+
return await this.getInstance().handleStrategyCommit(data);
|
|
60774
60861
|
};
|
|
60775
60862
|
/**
|
|
60776
60863
|
* Handles signal sync events (signal-open, signal-close).
|
|
@@ -60778,7 +60865,7 @@ class NotificationBacktestAdapter {
|
|
|
60778
60865
|
* @param data - The signal sync contract data
|
|
60779
60866
|
*/
|
|
60780
60867
|
this.handleSync = trycatch(async (data) => {
|
|
60781
|
-
return await this.
|
|
60868
|
+
return await this.getInstance().handleSync(data);
|
|
60782
60869
|
}, {
|
|
60783
60870
|
defaultValue: null,
|
|
60784
60871
|
});
|
|
@@ -60788,7 +60875,7 @@ class NotificationBacktestAdapter {
|
|
|
60788
60875
|
* @param data - The risk contract data
|
|
60789
60876
|
*/
|
|
60790
60877
|
this.handleRisk = async (data) => {
|
|
60791
|
-
return await this.
|
|
60878
|
+
return await this.getInstance().handleRisk(data);
|
|
60792
60879
|
};
|
|
60793
60880
|
/**
|
|
60794
60881
|
* Handles error event.
|
|
@@ -60796,7 +60883,7 @@ class NotificationBacktestAdapter {
|
|
|
60796
60883
|
* @param error - The error object
|
|
60797
60884
|
*/
|
|
60798
60885
|
this.handleError = async (error) => {
|
|
60799
|
-
return await this.
|
|
60886
|
+
return await this.getInstance().handleError(error);
|
|
60800
60887
|
};
|
|
60801
60888
|
/**
|
|
60802
60889
|
* Handles critical error event.
|
|
@@ -60804,7 +60891,7 @@ class NotificationBacktestAdapter {
|
|
|
60804
60891
|
* @param error - The error object
|
|
60805
60892
|
*/
|
|
60806
60893
|
this.handleCriticalError = async (error) => {
|
|
60807
|
-
return await this.
|
|
60894
|
+
return await this.getInstance().handleCriticalError(error);
|
|
60808
60895
|
};
|
|
60809
60896
|
/**
|
|
60810
60897
|
* Handles validation error event.
|
|
@@ -60812,7 +60899,7 @@ class NotificationBacktestAdapter {
|
|
|
60812
60899
|
* @param error - The error object
|
|
60813
60900
|
*/
|
|
60814
60901
|
this.handleValidationError = async (error) => {
|
|
60815
|
-
return await this.
|
|
60902
|
+
return await this.getInstance().handleValidationError(error);
|
|
60816
60903
|
};
|
|
60817
60904
|
/**
|
|
60818
60905
|
* Gets all stored notifications.
|
|
@@ -60820,14 +60907,14 @@ class NotificationBacktestAdapter {
|
|
|
60820
60907
|
* @returns Array of all notification models
|
|
60821
60908
|
*/
|
|
60822
60909
|
this.getData = async () => {
|
|
60823
|
-
return await this.
|
|
60910
|
+
return await this.getInstance().getData();
|
|
60824
60911
|
};
|
|
60825
60912
|
/**
|
|
60826
60913
|
* Clears all stored notifications.
|
|
60827
60914
|
* Proxies call to the underlying notification adapter.
|
|
60828
60915
|
*/
|
|
60829
60916
|
this.dispose = async () => {
|
|
60830
|
-
return await this.
|
|
60917
|
+
return await this.getInstance().dispose();
|
|
60831
60918
|
};
|
|
60832
60919
|
/**
|
|
60833
60920
|
* Sets the notification adapter constructor.
|
|
@@ -60837,7 +60924,8 @@ class NotificationBacktestAdapter {
|
|
|
60837
60924
|
*/
|
|
60838
60925
|
this.useNotificationAdapter = (Ctor) => {
|
|
60839
60926
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
60840
|
-
this.
|
|
60927
|
+
this._notificationBacktestFactory = () => Reflect.construct(Ctor, []);
|
|
60928
|
+
this.getInstance.clear();
|
|
60841
60929
|
};
|
|
60842
60930
|
/**
|
|
60843
60931
|
* Switches to dummy notification adapter.
|
|
@@ -60845,7 +60933,8 @@ class NotificationBacktestAdapter {
|
|
|
60845
60933
|
*/
|
|
60846
60934
|
this.useDummy = () => {
|
|
60847
60935
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
60848
|
-
this.
|
|
60936
|
+
this._notificationBacktestFactory = () => new NotificationDummyBacktestUtils();
|
|
60937
|
+
this.getInstance.clear();
|
|
60849
60938
|
};
|
|
60850
60939
|
/**
|
|
60851
60940
|
* Switches to in-memory notification adapter (default).
|
|
@@ -60853,7 +60942,8 @@ class NotificationBacktestAdapter {
|
|
|
60853
60942
|
*/
|
|
60854
60943
|
this.useMemory = () => {
|
|
60855
60944
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
60856
|
-
this.
|
|
60945
|
+
this._notificationBacktestFactory = () => new NotificationMemoryBacktestUtils();
|
|
60946
|
+
this.getInstance.clear();
|
|
60857
60947
|
};
|
|
60858
60948
|
/**
|
|
60859
60949
|
* Switches to persistent notification adapter.
|
|
@@ -60861,16 +60951,17 @@ class NotificationBacktestAdapter {
|
|
|
60861
60951
|
*/
|
|
60862
60952
|
this.usePersist = () => {
|
|
60863
60953
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
60864
|
-
this.
|
|
60954
|
+
this._notificationBacktestFactory = () => new NotificationPersistBacktestUtils();
|
|
60955
|
+
this.getInstance.clear();
|
|
60865
60956
|
};
|
|
60866
60957
|
/**
|
|
60867
|
-
*
|
|
60958
|
+
* Clears the memoized utils instance.
|
|
60868
60959
|
* Call this when process.cwd() changes between strategy iterations
|
|
60869
60960
|
* so a new instance is created with the updated base path.
|
|
60870
60961
|
*/
|
|
60871
60962
|
this.clear = () => {
|
|
60872
60963
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_CLEAR);
|
|
60873
|
-
this.
|
|
60964
|
+
this.getInstance.clear();
|
|
60874
60965
|
};
|
|
60875
60966
|
}
|
|
60876
60967
|
}
|
|
@@ -60885,18 +60976,26 @@ class NotificationBacktestAdapter {
|
|
|
60885
60976
|
*/
|
|
60886
60977
|
class NotificationLiveAdapter {
|
|
60887
60978
|
constructor() {
|
|
60888
|
-
/**
|
|
60889
|
-
this.
|
|
60979
|
+
/** Factory producing the active notification utils instance */
|
|
60980
|
+
this._notificationLiveFactory = () => new NotificationMemoryLiveUtils();
|
|
60981
|
+
/**
|
|
60982
|
+
* Lazily constructs the notification utils from the registered factory and
|
|
60983
|
+
* memoizes the result via `singleshot`.
|
|
60984
|
+
*
|
|
60985
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
60986
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
60987
|
+
*/
|
|
60988
|
+
this.getInstance = singleshot(() => this._notificationLiveFactory());
|
|
60890
60989
|
/**
|
|
60891
60990
|
* Handles signal events.
|
|
60892
60991
|
* Proxies call to the underlying notification adapter.
|
|
60893
60992
|
* @param data - The strategy tick result data
|
|
60894
60993
|
*/
|
|
60895
60994
|
this.handleSignal = async (data) => {
|
|
60896
|
-
return await this.
|
|
60995
|
+
return await this.getInstance().handleSignal(data);
|
|
60897
60996
|
};
|
|
60898
60997
|
this.handleSignalNotify = async (data) => {
|
|
60899
|
-
return await this.
|
|
60998
|
+
return await this.getInstance().handleSignalNotify(data);
|
|
60900
60999
|
};
|
|
60901
61000
|
/**
|
|
60902
61001
|
* Handles partial profit availability event.
|
|
@@ -60904,7 +61003,7 @@ class NotificationLiveAdapter {
|
|
|
60904
61003
|
* @param data - The partial profit contract data
|
|
60905
61004
|
*/
|
|
60906
61005
|
this.handlePartialProfit = async (data) => {
|
|
60907
|
-
return await this.
|
|
61006
|
+
return await this.getInstance().handlePartialProfit(data);
|
|
60908
61007
|
};
|
|
60909
61008
|
/**
|
|
60910
61009
|
* Handles partial loss availability event.
|
|
@@ -60912,7 +61011,7 @@ class NotificationLiveAdapter {
|
|
|
60912
61011
|
* @param data - The partial loss contract data
|
|
60913
61012
|
*/
|
|
60914
61013
|
this.handlePartialLoss = async (data) => {
|
|
60915
|
-
return await this.
|
|
61014
|
+
return await this.getInstance().handlePartialLoss(data);
|
|
60916
61015
|
};
|
|
60917
61016
|
/**
|
|
60918
61017
|
* Handles breakeven availability event.
|
|
@@ -60920,7 +61019,7 @@ class NotificationLiveAdapter {
|
|
|
60920
61019
|
* @param data - The breakeven contract data
|
|
60921
61020
|
*/
|
|
60922
61021
|
this.handleBreakeven = async (data) => {
|
|
60923
|
-
return await this.
|
|
61022
|
+
return await this.getInstance().handleBreakeven(data);
|
|
60924
61023
|
};
|
|
60925
61024
|
/**
|
|
60926
61025
|
* Handles strategy commit events.
|
|
@@ -60928,7 +61027,7 @@ class NotificationLiveAdapter {
|
|
|
60928
61027
|
* @param data - The strategy commit contract data
|
|
60929
61028
|
*/
|
|
60930
61029
|
this.handleStrategyCommit = async (data) => {
|
|
60931
|
-
return await this.
|
|
61030
|
+
return await this.getInstance().handleStrategyCommit(data);
|
|
60932
61031
|
};
|
|
60933
61032
|
/**
|
|
60934
61033
|
* Handles signal sync events (signal-open, signal-close).
|
|
@@ -60936,7 +61035,7 @@ class NotificationLiveAdapter {
|
|
|
60936
61035
|
* @param data - The signal sync contract data
|
|
60937
61036
|
*/
|
|
60938
61037
|
this.handleSync = trycatch(async (data) => {
|
|
60939
|
-
return await this.
|
|
61038
|
+
return await this.getInstance().handleSync(data);
|
|
60940
61039
|
}, {
|
|
60941
61040
|
defaultValue: null,
|
|
60942
61041
|
});
|
|
@@ -60946,7 +61045,7 @@ class NotificationLiveAdapter {
|
|
|
60946
61045
|
* @param data - The risk contract data
|
|
60947
61046
|
*/
|
|
60948
61047
|
this.handleRisk = async (data) => {
|
|
60949
|
-
return await this.
|
|
61048
|
+
return await this.getInstance().handleRisk(data);
|
|
60950
61049
|
};
|
|
60951
61050
|
/**
|
|
60952
61051
|
* Handles error event.
|
|
@@ -60954,7 +61053,7 @@ class NotificationLiveAdapter {
|
|
|
60954
61053
|
* @param error - The error object
|
|
60955
61054
|
*/
|
|
60956
61055
|
this.handleError = async (error) => {
|
|
60957
|
-
return await this.
|
|
61056
|
+
return await this.getInstance().handleError(error);
|
|
60958
61057
|
};
|
|
60959
61058
|
/**
|
|
60960
61059
|
* Handles critical error event.
|
|
@@ -60962,7 +61061,7 @@ class NotificationLiveAdapter {
|
|
|
60962
61061
|
* @param error - The error object
|
|
60963
61062
|
*/
|
|
60964
61063
|
this.handleCriticalError = async (error) => {
|
|
60965
|
-
return await this.
|
|
61064
|
+
return await this.getInstance().handleCriticalError(error);
|
|
60966
61065
|
};
|
|
60967
61066
|
/**
|
|
60968
61067
|
* Handles validation error event.
|
|
@@ -60970,7 +61069,7 @@ class NotificationLiveAdapter {
|
|
|
60970
61069
|
* @param error - The error object
|
|
60971
61070
|
*/
|
|
60972
61071
|
this.handleValidationError = async (error) => {
|
|
60973
|
-
return await this.
|
|
61072
|
+
return await this.getInstance().handleValidationError(error);
|
|
60974
61073
|
};
|
|
60975
61074
|
/**
|
|
60976
61075
|
* Gets all stored notifications.
|
|
@@ -60978,14 +61077,14 @@ class NotificationLiveAdapter {
|
|
|
60978
61077
|
* @returns Array of all notification models
|
|
60979
61078
|
*/
|
|
60980
61079
|
this.getData = async () => {
|
|
60981
|
-
return await this.
|
|
61080
|
+
return await this.getInstance().getData();
|
|
60982
61081
|
};
|
|
60983
61082
|
/**
|
|
60984
61083
|
* Clears all stored notifications.
|
|
60985
61084
|
* Proxies call to the underlying notification adapter.
|
|
60986
61085
|
*/
|
|
60987
61086
|
this.dispose = async () => {
|
|
60988
|
-
return await this.
|
|
61087
|
+
return await this.getInstance().dispose();
|
|
60989
61088
|
};
|
|
60990
61089
|
/**
|
|
60991
61090
|
* Sets the notification adapter constructor.
|
|
@@ -60995,7 +61094,8 @@ class NotificationLiveAdapter {
|
|
|
60995
61094
|
*/
|
|
60996
61095
|
this.useNotificationAdapter = (Ctor) => {
|
|
60997
61096
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
60998
|
-
this.
|
|
61097
|
+
this._notificationLiveFactory = () => Reflect.construct(Ctor, []);
|
|
61098
|
+
this.getInstance.clear();
|
|
60999
61099
|
};
|
|
61000
61100
|
/**
|
|
61001
61101
|
* Switches to dummy notification adapter.
|
|
@@ -61003,7 +61103,8 @@ class NotificationLiveAdapter {
|
|
|
61003
61103
|
*/
|
|
61004
61104
|
this.useDummy = () => {
|
|
61005
61105
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
61006
|
-
this.
|
|
61106
|
+
this._notificationLiveFactory = () => new NotificationDummyLiveUtils();
|
|
61107
|
+
this.getInstance.clear();
|
|
61007
61108
|
};
|
|
61008
61109
|
/**
|
|
61009
61110
|
* Switches to in-memory notification adapter (default).
|
|
@@ -61011,7 +61112,8 @@ class NotificationLiveAdapter {
|
|
|
61011
61112
|
*/
|
|
61012
61113
|
this.useMemory = () => {
|
|
61013
61114
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
61014
|
-
this.
|
|
61115
|
+
this._notificationLiveFactory = () => new NotificationMemoryLiveUtils();
|
|
61116
|
+
this.getInstance.clear();
|
|
61015
61117
|
};
|
|
61016
61118
|
/**
|
|
61017
61119
|
* Switches to persistent notification adapter.
|
|
@@ -61019,16 +61121,17 @@ class NotificationLiveAdapter {
|
|
|
61019
61121
|
*/
|
|
61020
61122
|
this.usePersist = () => {
|
|
61021
61123
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
61022
|
-
this.
|
|
61124
|
+
this._notificationLiveFactory = () => new NotificationPersistLiveUtils();
|
|
61125
|
+
this.getInstance.clear();
|
|
61023
61126
|
};
|
|
61024
61127
|
/**
|
|
61025
|
-
*
|
|
61128
|
+
* Clears the memoized utils instance.
|
|
61026
61129
|
* Call this when process.cwd() changes between strategy iterations
|
|
61027
61130
|
* so a new instance is created with the updated base path.
|
|
61028
61131
|
*/
|
|
61029
61132
|
this.clear = () => {
|
|
61030
61133
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_CLEAR);
|
|
61031
|
-
this.
|
|
61134
|
+
this.getInstance.clear();
|
|
61032
61135
|
};
|
|
61033
61136
|
}
|
|
61034
61137
|
}
|