backtest-kit 9.8.0 → 9.8.2
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 +1893 -1871
- package/build/index.cjs +740 -259
- package/build/index.mjs +739 -260
- package/package.json +86 -86
- package/types.d.ts +218 -25
package/build/index.cjs
CHANGED
|
@@ -574,6 +574,22 @@ const GLOBAL_CONFIG = {
|
|
|
574
574
|
* Default: true (mutex locking enabled for candle fetching)
|
|
575
575
|
*/
|
|
576
576
|
CC_ENABLE_CANDLE_FETCH_MUTEX: true,
|
|
577
|
+
/**
|
|
578
|
+
* Enables cooperative interleaving of concurrently running backtests after each candle fetch.
|
|
579
|
+
*
|
|
580
|
+
* Mechanism (implemented in `Candle.spinLock`):
|
|
581
|
+
* - After `getNextCandles` resolves, the current backtest awaits
|
|
582
|
+
* `Promise.race([_spin.toPromise(), sleep(50)])`, where `_spin` is emitted whenever
|
|
583
|
+
* another caller acquires the candle-fetch mutex.
|
|
584
|
+
* - This hands the event loop to a peer backtest waiting on the same mutex, so multiple
|
|
585
|
+
* parallel `Backtest.run` / `Walker` workloads progress in round-robin fashion instead
|
|
586
|
+
* of one monopolizing the event loop until completion.
|
|
587
|
+
* - The spin is skipped entirely when `Lookup.isParallel` is `false` (single active workload —
|
|
588
|
+
* no peer to yield to) or when `CC_ENABLE_CANDLE_FETCH_MUTEX` is disabled.
|
|
589
|
+
*
|
|
590
|
+
* Default: true (parallel backtests are interleaved on each candle fetch boundary)
|
|
591
|
+
*/
|
|
592
|
+
CC_ENABLE_BACKTEST_PARALLEL_SPIN: true,
|
|
577
593
|
/**
|
|
578
594
|
* Enables DCA (Dollar-Cost Averaging) logic even if antirecord is not broken.
|
|
579
595
|
* Allows to commitAverageBuy if currentPrice is not the lowest price since entry, but still lower than priceOpen.
|
|
@@ -934,7 +950,7 @@ async function writeFileAtomic(file, data, options = {}) {
|
|
|
934
950
|
|
|
935
951
|
var _a$3;
|
|
936
952
|
/** Logger service injected as DI singleton */
|
|
937
|
-
const LOGGER_SERVICE$
|
|
953
|
+
const LOGGER_SERVICE$8 = new LoggerService();
|
|
938
954
|
/** Symbol key for the singleshot waitForInit function on PersistBase instances. */
|
|
939
955
|
const BASE_WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
|
|
940
956
|
// Calculate step in milliseconds for candle close time validation
|
|
@@ -1057,7 +1073,7 @@ const BASE_WAIT_FOR_INIT_FN_METHOD_NAME = "PersistBase.waitForInitFn";
|
|
|
1057
1073
|
const BASE_UNLINK_RETRY_COUNT = 5;
|
|
1058
1074
|
const BASE_UNLINK_RETRY_DELAY = 1000;
|
|
1059
1075
|
const BASE_WAIT_FOR_INIT_FN = async (self) => {
|
|
1060
|
-
LOGGER_SERVICE$
|
|
1076
|
+
LOGGER_SERVICE$8.debug(BASE_WAIT_FOR_INIT_FN_METHOD_NAME, {
|
|
1061
1077
|
entityName: self.entityName,
|
|
1062
1078
|
directory: self._directory,
|
|
1063
1079
|
});
|
|
@@ -1115,7 +1131,7 @@ class PersistBase {
|
|
|
1115
1131
|
this.entityName = entityName;
|
|
1116
1132
|
this.baseDir = baseDir;
|
|
1117
1133
|
this[_a$3] = functoolsKit.singleshot(async () => await BASE_WAIT_FOR_INIT_FN(this));
|
|
1118
|
-
LOGGER_SERVICE$
|
|
1134
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_CTOR, {
|
|
1119
1135
|
entityName: this.entityName,
|
|
1120
1136
|
baseDir,
|
|
1121
1137
|
});
|
|
@@ -1131,14 +1147,14 @@ class PersistBase {
|
|
|
1131
1147
|
return path.join(this.baseDir, this.entityName, `${entityId}.json`);
|
|
1132
1148
|
}
|
|
1133
1149
|
async waitForInit(initial) {
|
|
1134
|
-
LOGGER_SERVICE$
|
|
1150
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_WAIT_FOR_INIT, {
|
|
1135
1151
|
entityName: this.entityName,
|
|
1136
1152
|
initial,
|
|
1137
1153
|
});
|
|
1138
1154
|
await this[BASE_WAIT_FOR_INIT_SYMBOL]();
|
|
1139
1155
|
}
|
|
1140
1156
|
async readValue(entityId) {
|
|
1141
|
-
LOGGER_SERVICE$
|
|
1157
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_READ_VALUE, {
|
|
1142
1158
|
entityName: this.entityName,
|
|
1143
1159
|
entityId,
|
|
1144
1160
|
});
|
|
@@ -1155,7 +1171,7 @@ class PersistBase {
|
|
|
1155
1171
|
}
|
|
1156
1172
|
}
|
|
1157
1173
|
async hasValue(entityId) {
|
|
1158
|
-
LOGGER_SERVICE$
|
|
1174
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_HAS_VALUE, {
|
|
1159
1175
|
entityName: this.entityName,
|
|
1160
1176
|
entityId,
|
|
1161
1177
|
});
|
|
@@ -1172,7 +1188,7 @@ class PersistBase {
|
|
|
1172
1188
|
}
|
|
1173
1189
|
}
|
|
1174
1190
|
async writeValue(entityId, entity) {
|
|
1175
|
-
LOGGER_SERVICE$
|
|
1191
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_WRITE_VALUE, {
|
|
1176
1192
|
entityName: this.entityName,
|
|
1177
1193
|
entityId,
|
|
1178
1194
|
});
|
|
@@ -1194,7 +1210,7 @@ class PersistBase {
|
|
|
1194
1210
|
* @throws Error if reading fails
|
|
1195
1211
|
*/
|
|
1196
1212
|
async *keys() {
|
|
1197
|
-
LOGGER_SERVICE$
|
|
1213
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_KEYS, {
|
|
1198
1214
|
entityName: this.entityName,
|
|
1199
1215
|
});
|
|
1200
1216
|
try {
|
|
@@ -1339,7 +1355,7 @@ class PersistSignalUtils {
|
|
|
1339
1355
|
* @returns Promise resolving to signal or null if none persisted
|
|
1340
1356
|
*/
|
|
1341
1357
|
this.readSignalData = async (symbol, strategyName, exchangeName) => {
|
|
1342
|
-
LOGGER_SERVICE$
|
|
1358
|
+
LOGGER_SERVICE$8.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_READ_DATA);
|
|
1343
1359
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1344
1360
|
const isInitial = !this.getStorage.has(key);
|
|
1345
1361
|
const instance = this.getStorage(symbol, strategyName, exchangeName);
|
|
@@ -1357,7 +1373,7 @@ class PersistSignalUtils {
|
|
|
1357
1373
|
* @returns Promise that resolves when write is complete
|
|
1358
1374
|
*/
|
|
1359
1375
|
this.writeSignalData = async (signalRow, symbol, strategyName, exchangeName) => {
|
|
1360
|
-
LOGGER_SERVICE$
|
|
1376
|
+
LOGGER_SERVICE$8.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1361
1377
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1362
1378
|
const isInitial = !this.getStorage.has(key);
|
|
1363
1379
|
const instance = this.getStorage(symbol, strategyName, exchangeName);
|
|
@@ -1372,7 +1388,7 @@ class PersistSignalUtils {
|
|
|
1372
1388
|
* @param Ctor - Custom IPersistSignalInstance constructor
|
|
1373
1389
|
*/
|
|
1374
1390
|
usePersistSignalAdapter(Ctor) {
|
|
1375
|
-
LOGGER_SERVICE$
|
|
1391
|
+
LOGGER_SERVICE$8.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_PERSIST_SIGNAL_ADAPTER);
|
|
1376
1392
|
this.PersistSignalInstanceCtor = Ctor;
|
|
1377
1393
|
this.getStorage.clear();
|
|
1378
1394
|
}
|
|
@@ -1381,21 +1397,21 @@ class PersistSignalUtils {
|
|
|
1381
1397
|
* Call when process.cwd() changes between strategy iterations.
|
|
1382
1398
|
*/
|
|
1383
1399
|
clear() {
|
|
1384
|
-
LOGGER_SERVICE$
|
|
1400
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_CLEAR);
|
|
1385
1401
|
this.getStorage.clear();
|
|
1386
1402
|
}
|
|
1387
1403
|
/**
|
|
1388
1404
|
* Switches to the default file-based PersistSignalInstance.
|
|
1389
1405
|
*/
|
|
1390
1406
|
useJson() {
|
|
1391
|
-
LOGGER_SERVICE$
|
|
1407
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_JSON);
|
|
1392
1408
|
this.usePersistSignalAdapter(PersistSignalInstance);
|
|
1393
1409
|
}
|
|
1394
1410
|
/**
|
|
1395
1411
|
* Switches to PersistSignalDummyInstance (all operations are no-ops).
|
|
1396
1412
|
*/
|
|
1397
1413
|
useDummy() {
|
|
1398
|
-
LOGGER_SERVICE$
|
|
1414
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1399
1415
|
this.usePersistSignalAdapter(PersistSignalDummyInstance);
|
|
1400
1416
|
}
|
|
1401
1417
|
}
|
|
@@ -1535,7 +1551,7 @@ class PersistRiskUtils {
|
|
|
1535
1551
|
* @returns Promise resolving to position entries (empty array if none)
|
|
1536
1552
|
*/
|
|
1537
1553
|
this.readPositionData = async (riskName, exchangeName, when) => {
|
|
1538
|
-
LOGGER_SERVICE$
|
|
1554
|
+
LOGGER_SERVICE$8.info(PERSIST_RISK_UTILS_METHOD_NAME_READ_DATA);
|
|
1539
1555
|
const key = `${riskName}:${exchangeName}`;
|
|
1540
1556
|
const isInitial = !this.getRiskStorage.has(key);
|
|
1541
1557
|
const instance = this.getRiskStorage(riskName, exchangeName);
|
|
@@ -1553,7 +1569,7 @@ class PersistRiskUtils {
|
|
|
1553
1569
|
* @returns Promise that resolves when write is complete
|
|
1554
1570
|
*/
|
|
1555
1571
|
this.writePositionData = async (riskRow, riskName, exchangeName, when) => {
|
|
1556
|
-
LOGGER_SERVICE$
|
|
1572
|
+
LOGGER_SERVICE$8.info(PERSIST_RISK_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1557
1573
|
const key = `${riskName}:${exchangeName}`;
|
|
1558
1574
|
const isInitial = !this.getRiskStorage.has(key);
|
|
1559
1575
|
const instance = this.getRiskStorage(riskName, exchangeName);
|
|
@@ -1568,7 +1584,7 @@ class PersistRiskUtils {
|
|
|
1568
1584
|
* @param Ctor - Custom IPersistRiskInstance constructor
|
|
1569
1585
|
*/
|
|
1570
1586
|
usePersistRiskAdapter(Ctor) {
|
|
1571
|
-
LOGGER_SERVICE$
|
|
1587
|
+
LOGGER_SERVICE$8.info(PERSIST_RISK_UTILS_METHOD_NAME_USE_PERSIST_RISK_ADAPTER);
|
|
1572
1588
|
this.PersistRiskInstanceCtor = Ctor;
|
|
1573
1589
|
this.getRiskStorage.clear();
|
|
1574
1590
|
}
|
|
@@ -1577,21 +1593,21 @@ class PersistRiskUtils {
|
|
|
1577
1593
|
* Call when process.cwd() changes between strategy iterations.
|
|
1578
1594
|
*/
|
|
1579
1595
|
clear() {
|
|
1580
|
-
LOGGER_SERVICE$
|
|
1596
|
+
LOGGER_SERVICE$8.log(PERSIST_RISK_UTILS_METHOD_NAME_CLEAR);
|
|
1581
1597
|
this.getRiskStorage.clear();
|
|
1582
1598
|
}
|
|
1583
1599
|
/**
|
|
1584
1600
|
* Switches to the default file-based PersistRiskInstance.
|
|
1585
1601
|
*/
|
|
1586
1602
|
useJson() {
|
|
1587
|
-
LOGGER_SERVICE$
|
|
1603
|
+
LOGGER_SERVICE$8.log(PERSIST_RISK_UTILS_METHOD_NAME_USE_JSON);
|
|
1588
1604
|
this.usePersistRiskAdapter(PersistRiskInstance);
|
|
1589
1605
|
}
|
|
1590
1606
|
/**
|
|
1591
1607
|
* Switches to PersistRiskDummyInstance (all operations are no-ops).
|
|
1592
1608
|
*/
|
|
1593
1609
|
useDummy() {
|
|
1594
|
-
LOGGER_SERVICE$
|
|
1610
|
+
LOGGER_SERVICE$8.log(PERSIST_RISK_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1595
1611
|
this.usePersistRiskAdapter(PersistRiskDummyInstance);
|
|
1596
1612
|
}
|
|
1597
1613
|
}
|
|
@@ -1730,7 +1746,7 @@ class PersistScheduleUtils {
|
|
|
1730
1746
|
* @returns Promise resolving to scheduled signal or null if none persisted
|
|
1731
1747
|
*/
|
|
1732
1748
|
this.readScheduleData = async (symbol, strategyName, exchangeName) => {
|
|
1733
|
-
LOGGER_SERVICE$
|
|
1749
|
+
LOGGER_SERVICE$8.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_READ_DATA);
|
|
1734
1750
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1735
1751
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
1736
1752
|
const instance = this.getScheduleStorage(symbol, strategyName, exchangeName);
|
|
@@ -1748,7 +1764,7 @@ class PersistScheduleUtils {
|
|
|
1748
1764
|
* @returns Promise that resolves when write is complete
|
|
1749
1765
|
*/
|
|
1750
1766
|
this.writeScheduleData = async (scheduledSignalRow, symbol, strategyName, exchangeName) => {
|
|
1751
|
-
LOGGER_SERVICE$
|
|
1767
|
+
LOGGER_SERVICE$8.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1752
1768
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1753
1769
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
1754
1770
|
const instance = this.getScheduleStorage(symbol, strategyName, exchangeName);
|
|
@@ -1763,7 +1779,7 @@ class PersistScheduleUtils {
|
|
|
1763
1779
|
* @param Ctor - Custom IPersistScheduleInstance constructor
|
|
1764
1780
|
*/
|
|
1765
1781
|
usePersistScheduleAdapter(Ctor) {
|
|
1766
|
-
LOGGER_SERVICE$
|
|
1782
|
+
LOGGER_SERVICE$8.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_PERSIST_SCHEDULE_ADAPTER);
|
|
1767
1783
|
this.PersistScheduleInstanceCtor = Ctor;
|
|
1768
1784
|
this.getScheduleStorage.clear();
|
|
1769
1785
|
}
|
|
@@ -1772,21 +1788,21 @@ class PersistScheduleUtils {
|
|
|
1772
1788
|
* Call when process.cwd() changes between strategy iterations.
|
|
1773
1789
|
*/
|
|
1774
1790
|
clear() {
|
|
1775
|
-
LOGGER_SERVICE$
|
|
1791
|
+
LOGGER_SERVICE$8.log(PERSIST_SCHEDULE_UTILS_METHOD_NAME_CLEAR);
|
|
1776
1792
|
this.getScheduleStorage.clear();
|
|
1777
1793
|
}
|
|
1778
1794
|
/**
|
|
1779
1795
|
* Switches to the default file-based PersistScheduleInstance.
|
|
1780
1796
|
*/
|
|
1781
1797
|
useJson() {
|
|
1782
|
-
LOGGER_SERVICE$
|
|
1798
|
+
LOGGER_SERVICE$8.log(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_JSON);
|
|
1783
1799
|
this.usePersistScheduleAdapter(PersistScheduleInstance);
|
|
1784
1800
|
}
|
|
1785
1801
|
/**
|
|
1786
1802
|
* Switches to PersistScheduleDummyInstance (all operations are no-ops).
|
|
1787
1803
|
*/
|
|
1788
1804
|
useDummy() {
|
|
1789
|
-
LOGGER_SERVICE$
|
|
1805
|
+
LOGGER_SERVICE$8.log(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1790
1806
|
this.usePersistScheduleAdapter(PersistScheduleDummyInstance);
|
|
1791
1807
|
}
|
|
1792
1808
|
}
|
|
@@ -1931,7 +1947,7 @@ class PersistPartialUtils {
|
|
|
1931
1947
|
* @returns Promise resolving to partial data record (empty object if none)
|
|
1932
1948
|
*/
|
|
1933
1949
|
this.readPartialData = async (symbol, strategyName, signalId, exchangeName, when) => {
|
|
1934
|
-
LOGGER_SERVICE$
|
|
1950
|
+
LOGGER_SERVICE$8.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_READ_DATA);
|
|
1935
1951
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1936
1952
|
const isInitial = !this.getPartialStorage.has(key);
|
|
1937
1953
|
const instance = this.getPartialStorage(symbol, strategyName, exchangeName);
|
|
@@ -1951,7 +1967,7 @@ class PersistPartialUtils {
|
|
|
1951
1967
|
* @returns Promise that resolves when write is complete
|
|
1952
1968
|
*/
|
|
1953
1969
|
this.writePartialData = async (partialData, symbol, strategyName, signalId, exchangeName, when) => {
|
|
1954
|
-
LOGGER_SERVICE$
|
|
1970
|
+
LOGGER_SERVICE$8.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1955
1971
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1956
1972
|
const isInitial = !this.getPartialStorage.has(key);
|
|
1957
1973
|
const instance = this.getPartialStorage(symbol, strategyName, exchangeName);
|
|
@@ -1966,7 +1982,7 @@ class PersistPartialUtils {
|
|
|
1966
1982
|
* @param Ctor - Custom IPersistPartialInstance constructor
|
|
1967
1983
|
*/
|
|
1968
1984
|
usePersistPartialAdapter(Ctor) {
|
|
1969
|
-
LOGGER_SERVICE$
|
|
1985
|
+
LOGGER_SERVICE$8.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_PERSIST_PARTIAL_ADAPTER);
|
|
1970
1986
|
this.PersistPartialInstanceCtor = Ctor;
|
|
1971
1987
|
this.getPartialStorage.clear();
|
|
1972
1988
|
}
|
|
@@ -1975,21 +1991,21 @@ class PersistPartialUtils {
|
|
|
1975
1991
|
* Call when process.cwd() changes between strategy iterations.
|
|
1976
1992
|
*/
|
|
1977
1993
|
clear() {
|
|
1978
|
-
LOGGER_SERVICE$
|
|
1994
|
+
LOGGER_SERVICE$8.log(PERSIST_PARTIAL_UTILS_METHOD_NAME_CLEAR);
|
|
1979
1995
|
this.getPartialStorage.clear();
|
|
1980
1996
|
}
|
|
1981
1997
|
/**
|
|
1982
1998
|
* Switches to the default file-based PersistPartialInstance.
|
|
1983
1999
|
*/
|
|
1984
2000
|
useJson() {
|
|
1985
|
-
LOGGER_SERVICE$
|
|
2001
|
+
LOGGER_SERVICE$8.log(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_JSON);
|
|
1986
2002
|
this.usePersistPartialAdapter(PersistPartialInstance);
|
|
1987
2003
|
}
|
|
1988
2004
|
/**
|
|
1989
2005
|
* Switches to PersistPartialDummyInstance (all operations are no-ops).
|
|
1990
2006
|
*/
|
|
1991
2007
|
useDummy() {
|
|
1992
|
-
LOGGER_SERVICE$
|
|
2008
|
+
LOGGER_SERVICE$8.log(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1993
2009
|
this.usePersistPartialAdapter(PersistPartialDummyInstance);
|
|
1994
2010
|
}
|
|
1995
2011
|
}
|
|
@@ -2154,7 +2170,7 @@ class PersistBreakevenUtils {
|
|
|
2154
2170
|
* @returns Promise resolving to breakeven data record (empty object if none)
|
|
2155
2171
|
*/
|
|
2156
2172
|
this.readBreakevenData = async (symbol, strategyName, signalId, exchangeName, when) => {
|
|
2157
|
-
LOGGER_SERVICE$
|
|
2173
|
+
LOGGER_SERVICE$8.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_READ_DATA);
|
|
2158
2174
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
2159
2175
|
const isInitial = !this.getBreakevenStorage.has(key);
|
|
2160
2176
|
const instance = this.getBreakevenStorage(symbol, strategyName, exchangeName);
|
|
@@ -2174,7 +2190,7 @@ class PersistBreakevenUtils {
|
|
|
2174
2190
|
* @returns Promise that resolves when write is complete
|
|
2175
2191
|
*/
|
|
2176
2192
|
this.writeBreakevenData = async (breakevenData, symbol, strategyName, signalId, exchangeName, when) => {
|
|
2177
|
-
LOGGER_SERVICE$
|
|
2193
|
+
LOGGER_SERVICE$8.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2178
2194
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
2179
2195
|
const isInitial = !this.getBreakevenStorage.has(key);
|
|
2180
2196
|
const instance = this.getBreakevenStorage(symbol, strategyName, exchangeName);
|
|
@@ -2189,7 +2205,7 @@ class PersistBreakevenUtils {
|
|
|
2189
2205
|
* @param Ctor - Custom IPersistBreakevenInstance constructor
|
|
2190
2206
|
*/
|
|
2191
2207
|
usePersistBreakevenAdapter(Ctor) {
|
|
2192
|
-
LOGGER_SERVICE$
|
|
2208
|
+
LOGGER_SERVICE$8.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_USE_PERSIST_BREAKEVEN_ADAPTER);
|
|
2193
2209
|
this.PersistBreakevenInstanceCtor = Ctor;
|
|
2194
2210
|
this.getBreakevenStorage.clear();
|
|
2195
2211
|
}
|
|
@@ -2198,21 +2214,21 @@ class PersistBreakevenUtils {
|
|
|
2198
2214
|
* Call when process.cwd() changes between strategy iterations.
|
|
2199
2215
|
*/
|
|
2200
2216
|
clear() {
|
|
2201
|
-
LOGGER_SERVICE$
|
|
2217
|
+
LOGGER_SERVICE$8.log(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_CLEAR);
|
|
2202
2218
|
this.getBreakevenStorage.clear();
|
|
2203
2219
|
}
|
|
2204
2220
|
/**
|
|
2205
2221
|
* Switches to the default file-based PersistBreakevenInstance.
|
|
2206
2222
|
*/
|
|
2207
2223
|
useJson() {
|
|
2208
|
-
LOGGER_SERVICE$
|
|
2224
|
+
LOGGER_SERVICE$8.log(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_USE_JSON);
|
|
2209
2225
|
this.usePersistBreakevenAdapter(PersistBreakevenInstance);
|
|
2210
2226
|
}
|
|
2211
2227
|
/**
|
|
2212
2228
|
* Switches to PersistBreakevenDummyInstance (all operations are no-ops).
|
|
2213
2229
|
*/
|
|
2214
2230
|
useDummy() {
|
|
2215
|
-
LOGGER_SERVICE$
|
|
2231
|
+
LOGGER_SERVICE$8.log(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2216
2232
|
this.usePersistBreakevenAdapter(PersistBreakevenDummyInstance);
|
|
2217
2233
|
}
|
|
2218
2234
|
}
|
|
@@ -2303,7 +2319,7 @@ class PersistCandleInstance {
|
|
|
2303
2319
|
error: functoolsKit.errorData(error),
|
|
2304
2320
|
message: functoolsKit.getErrorMessage(error),
|
|
2305
2321
|
};
|
|
2306
|
-
LOGGER_SERVICE$
|
|
2322
|
+
LOGGER_SERVICE$8.warn(message, payload);
|
|
2307
2323
|
console.warn(message, payload);
|
|
2308
2324
|
errorEmitter.next(error);
|
|
2309
2325
|
return null;
|
|
@@ -2325,7 +2341,7 @@ class PersistCandleInstance {
|
|
|
2325
2341
|
for (const candle of candles) {
|
|
2326
2342
|
const candleCloseTime = candle.timestamp + stepMs;
|
|
2327
2343
|
if (candleCloseTime > now) {
|
|
2328
|
-
LOGGER_SERVICE$
|
|
2344
|
+
LOGGER_SERVICE$8.debug("PersistCandleInstance.writeCandlesData: skipping incomplete candle", {
|
|
2329
2345
|
symbol: this.symbol,
|
|
2330
2346
|
interval: this.interval,
|
|
2331
2347
|
exchangeName: this.exchangeName,
|
|
@@ -2402,7 +2418,7 @@ class PersistCandleUtils {
|
|
|
2402
2418
|
* @returns Promise resolving to candles in order, or null on cache miss
|
|
2403
2419
|
*/
|
|
2404
2420
|
this.readCandlesData = async (symbol, interval, exchangeName, limit, sinceTimestamp, untilTimestamp) => {
|
|
2405
|
-
LOGGER_SERVICE$
|
|
2421
|
+
LOGGER_SERVICE$8.info("PersistCandleUtils.readCandlesData", {
|
|
2406
2422
|
symbol,
|
|
2407
2423
|
interval,
|
|
2408
2424
|
exchangeName,
|
|
@@ -2426,7 +2442,7 @@ class PersistCandleUtils {
|
|
|
2426
2442
|
* @returns Promise that resolves when all writes are complete
|
|
2427
2443
|
*/
|
|
2428
2444
|
this.writeCandlesData = async (candles, symbol, interval, exchangeName) => {
|
|
2429
|
-
LOGGER_SERVICE$
|
|
2445
|
+
LOGGER_SERVICE$8.info("PersistCandleUtils.writeCandlesData", {
|
|
2430
2446
|
symbol,
|
|
2431
2447
|
interval,
|
|
2432
2448
|
exchangeName,
|
|
@@ -2446,7 +2462,7 @@ class PersistCandleUtils {
|
|
|
2446
2462
|
* @param Ctor - Custom IPersistCandleInstance constructor
|
|
2447
2463
|
*/
|
|
2448
2464
|
usePersistCandleAdapter(Ctor) {
|
|
2449
|
-
LOGGER_SERVICE$
|
|
2465
|
+
LOGGER_SERVICE$8.info("PersistCandleUtils.usePersistCandleAdapter");
|
|
2450
2466
|
this.PersistCandleInstanceCtor = Ctor;
|
|
2451
2467
|
this.getCandlesStorage.clear();
|
|
2452
2468
|
}
|
|
@@ -2455,21 +2471,21 @@ class PersistCandleUtils {
|
|
|
2455
2471
|
* Call when process.cwd() changes between strategy iterations.
|
|
2456
2472
|
*/
|
|
2457
2473
|
clear() {
|
|
2458
|
-
LOGGER_SERVICE$
|
|
2474
|
+
LOGGER_SERVICE$8.log(PERSIST_CANDLE_UTILS_METHOD_NAME_CLEAR);
|
|
2459
2475
|
this.getCandlesStorage.clear();
|
|
2460
2476
|
}
|
|
2461
2477
|
/**
|
|
2462
2478
|
* Switches to the default file-based PersistCandleInstance.
|
|
2463
2479
|
*/
|
|
2464
2480
|
useJson() {
|
|
2465
|
-
LOGGER_SERVICE$
|
|
2481
|
+
LOGGER_SERVICE$8.log("PersistCandleUtils.useJson");
|
|
2466
2482
|
this.usePersistCandleAdapter(PersistCandleInstance);
|
|
2467
2483
|
}
|
|
2468
2484
|
/**
|
|
2469
2485
|
* Switches to PersistCandleDummyInstance (always returns null on read, discards writes).
|
|
2470
2486
|
*/
|
|
2471
2487
|
useDummy() {
|
|
2472
|
-
LOGGER_SERVICE$
|
|
2488
|
+
LOGGER_SERVICE$8.log("PersistCandleUtils.useDummy");
|
|
2473
2489
|
this.usePersistCandleAdapter(PersistCandleDummyInstance);
|
|
2474
2490
|
}
|
|
2475
2491
|
}
|
|
@@ -2607,7 +2623,7 @@ class PersistStorageUtils {
|
|
|
2607
2623
|
* @returns Promise resolving to array of signal entries
|
|
2608
2624
|
*/
|
|
2609
2625
|
this.readStorageData = async (backtest) => {
|
|
2610
|
-
LOGGER_SERVICE$
|
|
2626
|
+
LOGGER_SERVICE$8.info(PERSIST_STORAGE_UTILS_METHOD_NAME_READ_DATA);
|
|
2611
2627
|
const key = backtest ? `backtest` : `live`;
|
|
2612
2628
|
const isInitial = !this.getStorage.has(key);
|
|
2613
2629
|
const instance = this.getStorage(backtest);
|
|
@@ -2623,7 +2639,7 @@ class PersistStorageUtils {
|
|
|
2623
2639
|
* @returns Promise that resolves when write is complete
|
|
2624
2640
|
*/
|
|
2625
2641
|
this.writeStorageData = async (signalData, backtest) => {
|
|
2626
|
-
LOGGER_SERVICE$
|
|
2642
|
+
LOGGER_SERVICE$8.info(PERSIST_STORAGE_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2627
2643
|
const key = backtest ? `backtest` : `live`;
|
|
2628
2644
|
const isInitial = !this.getStorage.has(key);
|
|
2629
2645
|
const instance = this.getStorage(backtest);
|
|
@@ -2638,7 +2654,7 @@ class PersistStorageUtils {
|
|
|
2638
2654
|
* @param Ctor - Custom IPersistStorageInstance constructor
|
|
2639
2655
|
*/
|
|
2640
2656
|
usePersistStorageAdapter(Ctor) {
|
|
2641
|
-
LOGGER_SERVICE$
|
|
2657
|
+
LOGGER_SERVICE$8.info(PERSIST_STORAGE_UTILS_METHOD_NAME_USE_PERSIST_STORAGE_ADAPTER);
|
|
2642
2658
|
this.PersistStorageInstanceCtor = Ctor;
|
|
2643
2659
|
this.getStorage.clear();
|
|
2644
2660
|
}
|
|
@@ -2647,21 +2663,21 @@ class PersistStorageUtils {
|
|
|
2647
2663
|
* Call when process.cwd() changes between strategy iterations.
|
|
2648
2664
|
*/
|
|
2649
2665
|
clear() {
|
|
2650
|
-
LOGGER_SERVICE$
|
|
2666
|
+
LOGGER_SERVICE$8.log(PERSIST_STORAGE_UTILS_METHOD_NAME_CLEAR);
|
|
2651
2667
|
this.getStorage.clear();
|
|
2652
2668
|
}
|
|
2653
2669
|
/**
|
|
2654
2670
|
* Switches to the default file-based PersistStorageInstance.
|
|
2655
2671
|
*/
|
|
2656
2672
|
useJson() {
|
|
2657
|
-
LOGGER_SERVICE$
|
|
2673
|
+
LOGGER_SERVICE$8.log(PERSIST_STORAGE_UTILS_METHOD_NAME_USE_JSON);
|
|
2658
2674
|
this.usePersistStorageAdapter(PersistStorageInstance);
|
|
2659
2675
|
}
|
|
2660
2676
|
/**
|
|
2661
2677
|
* Switches to PersistStorageDummyInstance (all operations are no-ops).
|
|
2662
2678
|
*/
|
|
2663
2679
|
useDummy() {
|
|
2664
|
-
LOGGER_SERVICE$
|
|
2680
|
+
LOGGER_SERVICE$8.log(PERSIST_STORAGE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2665
2681
|
this.usePersistStorageAdapter(PersistStorageDummyInstance);
|
|
2666
2682
|
}
|
|
2667
2683
|
}
|
|
@@ -2788,7 +2804,7 @@ class PersistNotificationUtils {
|
|
|
2788
2804
|
* @returns Promise resolving to array of notification entries
|
|
2789
2805
|
*/
|
|
2790
2806
|
this.readNotificationData = async (backtest) => {
|
|
2791
|
-
LOGGER_SERVICE$
|
|
2807
|
+
LOGGER_SERVICE$8.info(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_READ_DATA);
|
|
2792
2808
|
const key = backtest ? `backtest` : `live`;
|
|
2793
2809
|
const isInitial = !this.getNotificationStorage.has(key);
|
|
2794
2810
|
const instance = this.getNotificationStorage(backtest);
|
|
@@ -2804,7 +2820,7 @@ class PersistNotificationUtils {
|
|
|
2804
2820
|
* @returns Promise that resolves when write is complete
|
|
2805
2821
|
*/
|
|
2806
2822
|
this.writeNotificationData = async (notificationData, backtest) => {
|
|
2807
|
-
LOGGER_SERVICE$
|
|
2823
|
+
LOGGER_SERVICE$8.info(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2808
2824
|
const key = backtest ? `backtest` : `live`;
|
|
2809
2825
|
const isInitial = !this.getNotificationStorage.has(key);
|
|
2810
2826
|
const instance = this.getNotificationStorage(backtest);
|
|
@@ -2819,7 +2835,7 @@ class PersistNotificationUtils {
|
|
|
2819
2835
|
* @param Ctor - Custom IPersistNotificationInstance constructor
|
|
2820
2836
|
*/
|
|
2821
2837
|
usePersistNotificationAdapter(Ctor) {
|
|
2822
|
-
LOGGER_SERVICE$
|
|
2838
|
+
LOGGER_SERVICE$8.info(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_USE_PERSIST_NOTIFICATION_ADAPTER);
|
|
2823
2839
|
this.PersistNotificationInstanceCtor = Ctor;
|
|
2824
2840
|
this.getNotificationStorage.clear();
|
|
2825
2841
|
}
|
|
@@ -2829,21 +2845,21 @@ class PersistNotificationUtils {
|
|
|
2829
2845
|
* instances are created with the updated base path.
|
|
2830
2846
|
*/
|
|
2831
2847
|
clear() {
|
|
2832
|
-
LOGGER_SERVICE$
|
|
2848
|
+
LOGGER_SERVICE$8.log(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_CLEAR);
|
|
2833
2849
|
this.getNotificationStorage.clear();
|
|
2834
2850
|
}
|
|
2835
2851
|
/**
|
|
2836
2852
|
* Switches to the default file-based PersistNotificationInstance.
|
|
2837
2853
|
*/
|
|
2838
2854
|
useJson() {
|
|
2839
|
-
LOGGER_SERVICE$
|
|
2855
|
+
LOGGER_SERVICE$8.log(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_USE_JSON);
|
|
2840
2856
|
this.usePersistNotificationAdapter(PersistNotificationInstance);
|
|
2841
2857
|
}
|
|
2842
2858
|
/**
|
|
2843
2859
|
* Switches to PersistNotificationDummyInstance (all operations are no-ops).
|
|
2844
2860
|
*/
|
|
2845
2861
|
useDummy() {
|
|
2846
|
-
LOGGER_SERVICE$
|
|
2862
|
+
LOGGER_SERVICE$8.log(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2847
2863
|
this.usePersistNotificationAdapter(PersistNotificationDummyInstance);
|
|
2848
2864
|
}
|
|
2849
2865
|
}
|
|
@@ -2967,7 +2983,7 @@ class PersistLogUtils {
|
|
|
2967
2983
|
* @returns Promise resolving to array of log entries
|
|
2968
2984
|
*/
|
|
2969
2985
|
this.readLogData = async () => {
|
|
2970
|
-
LOGGER_SERVICE$
|
|
2986
|
+
LOGGER_SERVICE$8.info(PERSIST_LOG_UTILS_METHOD_NAME_READ_DATA);
|
|
2971
2987
|
const isInitial = !this._logInstance;
|
|
2972
2988
|
const instance = this.getLogInstance();
|
|
2973
2989
|
await instance.waitForInit(isInitial);
|
|
@@ -2981,7 +2997,7 @@ class PersistLogUtils {
|
|
|
2981
2997
|
* @returns Promise that resolves when write is complete
|
|
2982
2998
|
*/
|
|
2983
2999
|
this.writeLogData = async (logData) => {
|
|
2984
|
-
LOGGER_SERVICE$
|
|
3000
|
+
LOGGER_SERVICE$8.info(PERSIST_LOG_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2985
3001
|
const isInitial = !this._logInstance;
|
|
2986
3002
|
const instance = this.getLogInstance();
|
|
2987
3003
|
await instance.waitForInit(isInitial);
|
|
@@ -3006,7 +3022,7 @@ class PersistLogUtils {
|
|
|
3006
3022
|
* @param Ctor - Custom IPersistLogInstance constructor
|
|
3007
3023
|
*/
|
|
3008
3024
|
usePersistLogAdapter(Ctor) {
|
|
3009
|
-
LOGGER_SERVICE$
|
|
3025
|
+
LOGGER_SERVICE$8.info(PERSIST_LOG_UTILS_METHOD_NAME_USE_PERSIST_LOG_ADAPTER);
|
|
3010
3026
|
this.PersistLogInstanceCtor = Ctor;
|
|
3011
3027
|
this._logInstance = null;
|
|
3012
3028
|
}
|
|
@@ -3015,21 +3031,21 @@ class PersistLogUtils {
|
|
|
3015
3031
|
* Call when process.cwd() changes between strategy iterations.
|
|
3016
3032
|
*/
|
|
3017
3033
|
clear() {
|
|
3018
|
-
LOGGER_SERVICE$
|
|
3034
|
+
LOGGER_SERVICE$8.log(PERSIST_LOG_UTILS_METHOD_NAME_CLEAR);
|
|
3019
3035
|
this._logInstance = null;
|
|
3020
3036
|
}
|
|
3021
3037
|
/**
|
|
3022
3038
|
* Switches to the default file-based PersistLogInstance.
|
|
3023
3039
|
*/
|
|
3024
3040
|
useJson() {
|
|
3025
|
-
LOGGER_SERVICE$
|
|
3041
|
+
LOGGER_SERVICE$8.log(PERSIST_LOG_UTILS_METHOD_NAME_USE_JSON);
|
|
3026
3042
|
this.usePersistLogAdapter(PersistLogInstance);
|
|
3027
3043
|
}
|
|
3028
3044
|
/**
|
|
3029
3045
|
* Switches to PersistLogDummyInstance (all operations are no-ops).
|
|
3030
3046
|
*/
|
|
3031
3047
|
useDummy() {
|
|
3032
|
-
LOGGER_SERVICE$
|
|
3048
|
+
LOGGER_SERVICE$8.log(PERSIST_LOG_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3033
3049
|
this.usePersistLogAdapter(PersistLogDummyInstance);
|
|
3034
3050
|
}
|
|
3035
3051
|
}
|
|
@@ -3191,7 +3207,7 @@ class PersistMeasureUtils {
|
|
|
3191
3207
|
* @returns Promise resolving to cached value, or null if not found / soft-deleted
|
|
3192
3208
|
*/
|
|
3193
3209
|
this.readMeasureData = async (bucket, key) => {
|
|
3194
|
-
LOGGER_SERVICE$
|
|
3210
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_READ_DATA, { bucket, key });
|
|
3195
3211
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3196
3212
|
const instance = this.getMeasureStorage(bucket);
|
|
3197
3213
|
await instance.waitForInit(isInitial);
|
|
@@ -3207,7 +3223,7 @@ class PersistMeasureUtils {
|
|
|
3207
3223
|
* @returns Promise that resolves when write is complete
|
|
3208
3224
|
*/
|
|
3209
3225
|
this.writeMeasureData = async (data, bucket, key, when) => {
|
|
3210
|
-
LOGGER_SERVICE$
|
|
3226
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_WRITE_DATA, { bucket, key });
|
|
3211
3227
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3212
3228
|
const instance = this.getMeasureStorage(bucket);
|
|
3213
3229
|
await instance.waitForInit(isInitial);
|
|
@@ -3222,7 +3238,7 @@ class PersistMeasureUtils {
|
|
|
3222
3238
|
* @returns Promise that resolves when removal is complete
|
|
3223
3239
|
*/
|
|
3224
3240
|
this.removeMeasureData = async (bucket, key) => {
|
|
3225
|
-
LOGGER_SERVICE$
|
|
3241
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_REMOVE_DATA, { bucket, key });
|
|
3226
3242
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3227
3243
|
const instance = this.getMeasureStorage(bucket);
|
|
3228
3244
|
await instance.waitForInit(isInitial);
|
|
@@ -3236,7 +3252,7 @@ class PersistMeasureUtils {
|
|
|
3236
3252
|
* @param Ctor - Custom IPersistMeasureInstance constructor
|
|
3237
3253
|
*/
|
|
3238
3254
|
usePersistMeasureAdapter(Ctor) {
|
|
3239
|
-
LOGGER_SERVICE$
|
|
3255
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_USE_PERSIST_MEASURE_ADAPTER);
|
|
3240
3256
|
this.PersistMeasureInstanceCtor = Ctor;
|
|
3241
3257
|
this.getMeasureStorage.clear();
|
|
3242
3258
|
}
|
|
@@ -3248,7 +3264,7 @@ class PersistMeasureUtils {
|
|
|
3248
3264
|
* @returns AsyncGenerator yielding entry keys
|
|
3249
3265
|
*/
|
|
3250
3266
|
async *listMeasureData(bucket) {
|
|
3251
|
-
LOGGER_SERVICE$
|
|
3267
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_LIST_DATA, { bucket });
|
|
3252
3268
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3253
3269
|
const instance = this.getMeasureStorage(bucket);
|
|
3254
3270
|
await instance.waitForInit(isInitial);
|
|
@@ -3259,21 +3275,21 @@ class PersistMeasureUtils {
|
|
|
3259
3275
|
* Call when process.cwd() changes between strategy iterations.
|
|
3260
3276
|
*/
|
|
3261
3277
|
clear() {
|
|
3262
|
-
LOGGER_SERVICE$
|
|
3278
|
+
LOGGER_SERVICE$8.log(PERSIST_MEASURE_UTILS_METHOD_NAME_CLEAR);
|
|
3263
3279
|
this.getMeasureStorage.clear();
|
|
3264
3280
|
}
|
|
3265
3281
|
/**
|
|
3266
3282
|
* Switches to the default file-based PersistMeasureInstance.
|
|
3267
3283
|
*/
|
|
3268
3284
|
useJson() {
|
|
3269
|
-
LOGGER_SERVICE$
|
|
3285
|
+
LOGGER_SERVICE$8.log(PERSIST_MEASURE_UTILS_METHOD_NAME_USE_JSON);
|
|
3270
3286
|
this.usePersistMeasureAdapter(PersistMeasureInstance);
|
|
3271
3287
|
}
|
|
3272
3288
|
/**
|
|
3273
3289
|
* Switches to PersistMeasureDummyInstance (all operations are no-ops).
|
|
3274
3290
|
*/
|
|
3275
3291
|
useDummy() {
|
|
3276
|
-
LOGGER_SERVICE$
|
|
3292
|
+
LOGGER_SERVICE$8.log(PERSIST_MEASURE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3277
3293
|
this.usePersistMeasureAdapter(PersistMeasureDummyInstance);
|
|
3278
3294
|
}
|
|
3279
3295
|
}
|
|
@@ -3432,7 +3448,7 @@ class PersistIntervalUtils {
|
|
|
3432
3448
|
* @returns Promise resolving to marker data, or null if not found / soft-deleted
|
|
3433
3449
|
*/
|
|
3434
3450
|
this.readIntervalData = async (bucket, key) => {
|
|
3435
|
-
LOGGER_SERVICE$
|
|
3451
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_READ_DATA, { bucket, key });
|
|
3436
3452
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3437
3453
|
const instance = this.getIntervalStorage(bucket);
|
|
3438
3454
|
await instance.waitForInit(isInitial);
|
|
@@ -3448,7 +3464,7 @@ class PersistIntervalUtils {
|
|
|
3448
3464
|
* @returns Promise that resolves when write is complete
|
|
3449
3465
|
*/
|
|
3450
3466
|
this.writeIntervalData = async (data, bucket, key, when) => {
|
|
3451
|
-
LOGGER_SERVICE$
|
|
3467
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_WRITE_DATA, { bucket, key });
|
|
3452
3468
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3453
3469
|
const instance = this.getIntervalStorage(bucket);
|
|
3454
3470
|
await instance.waitForInit(isInitial);
|
|
@@ -3463,7 +3479,7 @@ class PersistIntervalUtils {
|
|
|
3463
3479
|
* @returns Promise that resolves when removal is complete
|
|
3464
3480
|
*/
|
|
3465
3481
|
this.removeIntervalData = async (bucket, key) => {
|
|
3466
|
-
LOGGER_SERVICE$
|
|
3482
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_REMOVE_DATA, { bucket, key });
|
|
3467
3483
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3468
3484
|
const instance = this.getIntervalStorage(bucket);
|
|
3469
3485
|
await instance.waitForInit(isInitial);
|
|
@@ -3477,7 +3493,7 @@ class PersistIntervalUtils {
|
|
|
3477
3493
|
* @param Ctor - Custom IPersistIntervalInstance constructor
|
|
3478
3494
|
*/
|
|
3479
3495
|
usePersistIntervalAdapter(Ctor) {
|
|
3480
|
-
LOGGER_SERVICE$
|
|
3496
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_USE_PERSIST_INTERVAL_ADAPTER);
|
|
3481
3497
|
this.PersistIntervalInstanceCtor = Ctor;
|
|
3482
3498
|
this.getIntervalStorage.clear();
|
|
3483
3499
|
}
|
|
@@ -3489,7 +3505,7 @@ class PersistIntervalUtils {
|
|
|
3489
3505
|
* @returns AsyncGenerator yielding marker keys
|
|
3490
3506
|
*/
|
|
3491
3507
|
async *listIntervalData(bucket) {
|
|
3492
|
-
LOGGER_SERVICE$
|
|
3508
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_LIST_DATA, { bucket });
|
|
3493
3509
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3494
3510
|
const instance = this.getIntervalStorage(bucket);
|
|
3495
3511
|
await instance.waitForInit(isInitial);
|
|
@@ -3500,21 +3516,21 @@ class PersistIntervalUtils {
|
|
|
3500
3516
|
* Call when process.cwd() changes between strategy iterations.
|
|
3501
3517
|
*/
|
|
3502
3518
|
clear() {
|
|
3503
|
-
LOGGER_SERVICE$
|
|
3519
|
+
LOGGER_SERVICE$8.log(PERSIST_INTERVAL_UTILS_METHOD_NAME_CLEAR);
|
|
3504
3520
|
this.getIntervalStorage.clear();
|
|
3505
3521
|
}
|
|
3506
3522
|
/**
|
|
3507
3523
|
* Switches to the default file-based PersistIntervalInstance.
|
|
3508
3524
|
*/
|
|
3509
3525
|
useJson() {
|
|
3510
|
-
LOGGER_SERVICE$
|
|
3526
|
+
LOGGER_SERVICE$8.log(PERSIST_INTERVAL_UTILS_METHOD_NAME_USE_JSON);
|
|
3511
3527
|
this.usePersistIntervalAdapter(PersistIntervalInstance);
|
|
3512
3528
|
}
|
|
3513
3529
|
/**
|
|
3514
3530
|
* Switches to PersistIntervalDummyInstance (all operations are no-ops).
|
|
3515
3531
|
*/
|
|
3516
3532
|
useDummy() {
|
|
3517
|
-
LOGGER_SERVICE$
|
|
3533
|
+
LOGGER_SERVICE$8.log(PERSIST_INTERVAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3518
3534
|
this.usePersistIntervalAdapter(PersistIntervalDummyInstance);
|
|
3519
3535
|
}
|
|
3520
3536
|
}
|
|
@@ -3720,7 +3736,7 @@ class PersistMemoryUtils {
|
|
|
3720
3736
|
* @returns Promise resolving to entry data, or null if not found / soft-deleted
|
|
3721
3737
|
*/
|
|
3722
3738
|
this.readMemoryData = async (signalId, bucketName, memoryId) => {
|
|
3723
|
-
LOGGER_SERVICE$
|
|
3739
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_READ_DATA, { signalId, bucketName, memoryId });
|
|
3724
3740
|
const key = `${signalId}:${bucketName}`;
|
|
3725
3741
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3726
3742
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3737,7 +3753,7 @@ class PersistMemoryUtils {
|
|
|
3737
3753
|
* @returns Promise resolving to true if entry exists
|
|
3738
3754
|
*/
|
|
3739
3755
|
this.hasMemoryData = async (signalId, bucketName, memoryId) => {
|
|
3740
|
-
LOGGER_SERVICE$
|
|
3756
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_HAS_DATA, { signalId, bucketName, memoryId });
|
|
3741
3757
|
const key = `${signalId}:${bucketName}`;
|
|
3742
3758
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3743
3759
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3756,7 +3772,7 @@ class PersistMemoryUtils {
|
|
|
3756
3772
|
* @returns Promise that resolves when write is complete
|
|
3757
3773
|
*/
|
|
3758
3774
|
this.writeMemoryData = async (data, signalId, bucketName, memoryId, when) => {
|
|
3759
|
-
LOGGER_SERVICE$
|
|
3775
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName, memoryId });
|
|
3760
3776
|
const key = `${signalId}:${bucketName}`;
|
|
3761
3777
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3762
3778
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3773,7 +3789,7 @@ class PersistMemoryUtils {
|
|
|
3773
3789
|
* @returns Promise that resolves when removal is complete
|
|
3774
3790
|
*/
|
|
3775
3791
|
this.removeMemoryData = async (signalId, bucketName, memoryId) => {
|
|
3776
|
-
LOGGER_SERVICE$
|
|
3792
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_REMOVE_DATA, { signalId, bucketName, memoryId });
|
|
3777
3793
|
const key = `${signalId}:${bucketName}`;
|
|
3778
3794
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3779
3795
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3785,7 +3801,7 @@ class PersistMemoryUtils {
|
|
|
3785
3801
|
* Call when process.cwd() changes between strategy iterations.
|
|
3786
3802
|
*/
|
|
3787
3803
|
this.clear = () => {
|
|
3788
|
-
LOGGER_SERVICE$
|
|
3804
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_CLEAR);
|
|
3789
3805
|
this.getMemoryStorage.clear();
|
|
3790
3806
|
};
|
|
3791
3807
|
/**
|
|
@@ -3796,7 +3812,7 @@ class PersistMemoryUtils {
|
|
|
3796
3812
|
* @param bucketName - Bucket name
|
|
3797
3813
|
*/
|
|
3798
3814
|
this.dispose = (signalId, bucketName) => {
|
|
3799
|
-
LOGGER_SERVICE$
|
|
3815
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_DISPOSE);
|
|
3800
3816
|
const key = `${signalId}:${bucketName}`;
|
|
3801
3817
|
this.getMemoryStorage.clear(key);
|
|
3802
3818
|
};
|
|
@@ -3808,7 +3824,7 @@ class PersistMemoryUtils {
|
|
|
3808
3824
|
* @param Ctor - Custom IPersistMemoryInstance constructor
|
|
3809
3825
|
*/
|
|
3810
3826
|
usePersistMemoryAdapter(Ctor) {
|
|
3811
|
-
LOGGER_SERVICE$
|
|
3827
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_USE_PERSIST_MEMORY_ADAPTER);
|
|
3812
3828
|
this.PersistMemoryInstanceCtor = Ctor;
|
|
3813
3829
|
this.getMemoryStorage.clear();
|
|
3814
3830
|
}
|
|
@@ -3822,7 +3838,7 @@ class PersistMemoryUtils {
|
|
|
3822
3838
|
* @returns AsyncGenerator yielding `{ memoryId, data }` tuples
|
|
3823
3839
|
*/
|
|
3824
3840
|
async *listMemoryData(signalId, bucketName) {
|
|
3825
|
-
LOGGER_SERVICE$
|
|
3841
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_LIST_DATA, { signalId, bucketName });
|
|
3826
3842
|
const key = `${signalId}:${bucketName}`;
|
|
3827
3843
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3828
3844
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3833,14 +3849,14 @@ class PersistMemoryUtils {
|
|
|
3833
3849
|
* Switches to the default file-based PersistMemoryInstance.
|
|
3834
3850
|
*/
|
|
3835
3851
|
useJson() {
|
|
3836
|
-
LOGGER_SERVICE$
|
|
3852
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_JSON);
|
|
3837
3853
|
this.usePersistMemoryAdapter(PersistMemoryInstance);
|
|
3838
3854
|
}
|
|
3839
3855
|
/**
|
|
3840
3856
|
* Switches to PersistMemoryDummyInstance (all operations are no-ops).
|
|
3841
3857
|
*/
|
|
3842
3858
|
useDummy() {
|
|
3843
|
-
LOGGER_SERVICE$
|
|
3859
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3844
3860
|
this.usePersistMemoryAdapter(PersistMemoryDummyInstance);
|
|
3845
3861
|
}
|
|
3846
3862
|
}
|
|
@@ -3989,7 +4005,7 @@ class PersistRecentUtils {
|
|
|
3989
4005
|
* @returns Promise resolving to recent signal or null if none persisted
|
|
3990
4006
|
*/
|
|
3991
4007
|
this.readRecentData = async (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
3992
|
-
LOGGER_SERVICE$
|
|
4008
|
+
LOGGER_SERVICE$8.info(PERSIST_RECENT_UTILS_METHOD_NAME_READ_DATA);
|
|
3993
4009
|
const key = this.createKey(symbol, strategyName, exchangeName, frameName, backtest);
|
|
3994
4010
|
const isInitial = !this.getStorage.has(key);
|
|
3995
4011
|
const instance = this.getStorage(symbol, strategyName, exchangeName, frameName, backtest);
|
|
@@ -4010,7 +4026,7 @@ class PersistRecentUtils {
|
|
|
4010
4026
|
* @returns Promise that resolves when write is complete
|
|
4011
4027
|
*/
|
|
4012
4028
|
this.writeRecentData = async (signalRow, symbol, strategyName, exchangeName, frameName, backtest, when) => {
|
|
4013
|
-
LOGGER_SERVICE$
|
|
4029
|
+
LOGGER_SERVICE$8.info(PERSIST_RECENT_UTILS_METHOD_NAME_WRITE_DATA);
|
|
4014
4030
|
const key = this.createKey(symbol, strategyName, exchangeName, frameName, backtest);
|
|
4015
4031
|
const isInitial = !this.getStorage.has(key);
|
|
4016
4032
|
const instance = this.getStorage(symbol, strategyName, exchangeName, frameName, backtest);
|
|
@@ -4043,7 +4059,7 @@ class PersistRecentUtils {
|
|
|
4043
4059
|
* @param Ctor - Custom IPersistRecentInstance constructor
|
|
4044
4060
|
*/
|
|
4045
4061
|
usePersistRecentAdapter(Ctor) {
|
|
4046
|
-
LOGGER_SERVICE$
|
|
4062
|
+
LOGGER_SERVICE$8.info(PERSIST_RECENT_UTILS_METHOD_NAME_USE_PERSIST_RECENT_ADAPTER);
|
|
4047
4063
|
this.PersistRecentInstanceCtor = Ctor;
|
|
4048
4064
|
this.getStorage.clear();
|
|
4049
4065
|
}
|
|
@@ -4052,21 +4068,21 @@ class PersistRecentUtils {
|
|
|
4052
4068
|
* Call when process.cwd() changes between strategy iterations.
|
|
4053
4069
|
*/
|
|
4054
4070
|
clear() {
|
|
4055
|
-
LOGGER_SERVICE$
|
|
4071
|
+
LOGGER_SERVICE$8.log(PERSIST_RECENT_UTILS_METHOD_NAME_CLEAR);
|
|
4056
4072
|
this.getStorage.clear();
|
|
4057
4073
|
}
|
|
4058
4074
|
/**
|
|
4059
4075
|
* Switches to the default file-based PersistRecentInstance.
|
|
4060
4076
|
*/
|
|
4061
4077
|
useJson() {
|
|
4062
|
-
LOGGER_SERVICE$
|
|
4078
|
+
LOGGER_SERVICE$8.log(PERSIST_RECENT_UTILS_METHOD_NAME_USE_JSON);
|
|
4063
4079
|
this.usePersistRecentAdapter(PersistRecentInstance);
|
|
4064
4080
|
}
|
|
4065
4081
|
/**
|
|
4066
4082
|
* Switches to PersistRecentDummyInstance (all operations are no-ops).
|
|
4067
4083
|
*/
|
|
4068
4084
|
useDummy() {
|
|
4069
|
-
LOGGER_SERVICE$
|
|
4085
|
+
LOGGER_SERVICE$8.log(PERSIST_RECENT_UTILS_METHOD_NAME_USE_DUMMY);
|
|
4070
4086
|
this.usePersistRecentAdapter(PersistRecentDummyInstance);
|
|
4071
4087
|
}
|
|
4072
4088
|
}
|
|
@@ -4201,7 +4217,7 @@ class PersistStateUtils {
|
|
|
4201
4217
|
* @returns Promise that resolves when initialization is complete
|
|
4202
4218
|
*/
|
|
4203
4219
|
this.waitForInit = async (signalId, bucketName, initial) => {
|
|
4204
|
-
LOGGER_SERVICE$
|
|
4220
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_WAIT_FOR_INIT, { signalId, bucketName, initial });
|
|
4205
4221
|
const key = `${signalId}:${bucketName}`;
|
|
4206
4222
|
const isInitial = initial && !this.getStateStorage.has(key);
|
|
4207
4223
|
const instance = this.getStateStorage(signalId, bucketName);
|
|
@@ -4216,7 +4232,7 @@ class PersistStateUtils {
|
|
|
4216
4232
|
* @returns Promise resolving to state data or null if none persisted
|
|
4217
4233
|
*/
|
|
4218
4234
|
this.readStateData = async (signalId, bucketName) => {
|
|
4219
|
-
LOGGER_SERVICE$
|
|
4235
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_READ_DATA, { signalId, bucketName });
|
|
4220
4236
|
const key = `${signalId}:${bucketName}`;
|
|
4221
4237
|
const isInitial = !this.getStateStorage.has(key);
|
|
4222
4238
|
const instance = this.getStateStorage(signalId, bucketName);
|
|
@@ -4234,7 +4250,7 @@ class PersistStateUtils {
|
|
|
4234
4250
|
* @returns Promise that resolves when write is complete
|
|
4235
4251
|
*/
|
|
4236
4252
|
this.writeStateData = async (data, signalId, bucketName, when) => {
|
|
4237
|
-
LOGGER_SERVICE$
|
|
4253
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName });
|
|
4238
4254
|
const key = `${signalId}:${bucketName}`;
|
|
4239
4255
|
const isInitial = !this.getStateStorage.has(key);
|
|
4240
4256
|
const instance = this.getStateStorage(signalId, bucketName);
|
|
@@ -4245,14 +4261,14 @@ class PersistStateUtils {
|
|
|
4245
4261
|
* Switches to PersistStateDummyInstance (all operations are no-ops).
|
|
4246
4262
|
*/
|
|
4247
4263
|
this.useDummy = () => {
|
|
4248
|
-
LOGGER_SERVICE$
|
|
4264
|
+
LOGGER_SERVICE$8.log(PERSIST_STATE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
4249
4265
|
this.usePersistStateAdapter(PersistStateDummyInstance);
|
|
4250
4266
|
};
|
|
4251
4267
|
/**
|
|
4252
4268
|
* Switches to the default file-based PersistStateInstance.
|
|
4253
4269
|
*/
|
|
4254
4270
|
this.useJson = () => {
|
|
4255
|
-
LOGGER_SERVICE$
|
|
4271
|
+
LOGGER_SERVICE$8.log(PERSIST_STATE_UTILS_METHOD_NAME_USE_JSON);
|
|
4256
4272
|
this.usePersistStateAdapter(PersistStateInstance);
|
|
4257
4273
|
};
|
|
4258
4274
|
/**
|
|
@@ -4260,7 +4276,7 @@ class PersistStateUtils {
|
|
|
4260
4276
|
* Call when process.cwd() changes between strategy iterations.
|
|
4261
4277
|
*/
|
|
4262
4278
|
this.clear = () => {
|
|
4263
|
-
LOGGER_SERVICE$
|
|
4279
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_CLEAR);
|
|
4264
4280
|
this.getStateStorage.clear();
|
|
4265
4281
|
};
|
|
4266
4282
|
/**
|
|
@@ -4271,7 +4287,7 @@ class PersistStateUtils {
|
|
|
4271
4287
|
* @param bucketName - Bucket name
|
|
4272
4288
|
*/
|
|
4273
4289
|
this.dispose = (signalId, bucketName) => {
|
|
4274
|
-
LOGGER_SERVICE$
|
|
4290
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_DISPOSE);
|
|
4275
4291
|
const key = `${signalId}:${bucketName}`;
|
|
4276
4292
|
this.getStateStorage.clear(key);
|
|
4277
4293
|
};
|
|
@@ -4283,7 +4299,7 @@ class PersistStateUtils {
|
|
|
4283
4299
|
* @param Ctor - Custom IPersistStateInstance constructor
|
|
4284
4300
|
*/
|
|
4285
4301
|
usePersistStateAdapter(Ctor) {
|
|
4286
|
-
LOGGER_SERVICE$
|
|
4302
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_USE_PERSIST_STATE_ADAPTER);
|
|
4287
4303
|
this.PersistStateInstanceCtor = Ctor;
|
|
4288
4304
|
this.getStateStorage.clear();
|
|
4289
4305
|
}
|
|
@@ -4423,7 +4439,7 @@ class PersistSessionUtils {
|
|
|
4423
4439
|
* @returns Promise that resolves when initialization is complete
|
|
4424
4440
|
*/
|
|
4425
4441
|
this.waitForInit = async (strategyName, exchangeName, frameName, initial) => {
|
|
4426
|
-
LOGGER_SERVICE$
|
|
4442
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_WAIT_FOR_INIT, { strategyName, exchangeName, frameName, initial });
|
|
4427
4443
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4428
4444
|
const isInitial = initial && !this.getSessionStorage.has(key);
|
|
4429
4445
|
const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
|
|
@@ -4439,7 +4455,7 @@ class PersistSessionUtils {
|
|
|
4439
4455
|
* @returns Promise resolving to session data or null if none persisted
|
|
4440
4456
|
*/
|
|
4441
4457
|
this.readSessionData = async (strategyName, exchangeName, frameName) => {
|
|
4442
|
-
LOGGER_SERVICE$
|
|
4458
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_READ_DATA, { strategyName, exchangeName, frameName });
|
|
4443
4459
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4444
4460
|
const isInitial = !this.getSessionStorage.has(key);
|
|
4445
4461
|
const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
|
|
@@ -4458,7 +4474,7 @@ class PersistSessionUtils {
|
|
|
4458
4474
|
* @returns Promise that resolves when write is complete
|
|
4459
4475
|
*/
|
|
4460
4476
|
this.writeSessionData = async (data, strategyName, exchangeName, frameName, when) => {
|
|
4461
|
-
LOGGER_SERVICE$
|
|
4477
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_WRITE_DATA, { strategyName, exchangeName, frameName });
|
|
4462
4478
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4463
4479
|
const isInitial = !this.getSessionStorage.has(key);
|
|
4464
4480
|
const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
|
|
@@ -4469,14 +4485,14 @@ class PersistSessionUtils {
|
|
|
4469
4485
|
* Switches to PersistSessionDummyInstance (all operations are no-ops).
|
|
4470
4486
|
*/
|
|
4471
4487
|
this.useDummy = () => {
|
|
4472
|
-
LOGGER_SERVICE$
|
|
4488
|
+
LOGGER_SERVICE$8.log(PERSIST_SESSION_UTILS_METHOD_NAME_USE_DUMMY);
|
|
4473
4489
|
this.usePersistSessionAdapter(PersistSessionDummyInstance);
|
|
4474
4490
|
};
|
|
4475
4491
|
/**
|
|
4476
4492
|
* Switches to the default file-based PersistSessionInstance.
|
|
4477
4493
|
*/
|
|
4478
4494
|
this.useJson = () => {
|
|
4479
|
-
LOGGER_SERVICE$
|
|
4495
|
+
LOGGER_SERVICE$8.log(PERSIST_SESSION_UTILS_METHOD_NAME_USE_JSON);
|
|
4480
4496
|
this.usePersistSessionAdapter(PersistSessionInstance);
|
|
4481
4497
|
};
|
|
4482
4498
|
/**
|
|
@@ -4484,7 +4500,7 @@ class PersistSessionUtils {
|
|
|
4484
4500
|
* Call when process.cwd() changes between strategy iterations.
|
|
4485
4501
|
*/
|
|
4486
4502
|
this.clear = () => {
|
|
4487
|
-
LOGGER_SERVICE$
|
|
4503
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_CLEAR);
|
|
4488
4504
|
this.getSessionStorage.clear();
|
|
4489
4505
|
};
|
|
4490
4506
|
/**
|
|
@@ -4496,7 +4512,7 @@ class PersistSessionUtils {
|
|
|
4496
4512
|
* @param frameName - Frame identifier
|
|
4497
4513
|
*/
|
|
4498
4514
|
this.dispose = (strategyName, exchangeName, frameName) => {
|
|
4499
|
-
LOGGER_SERVICE$
|
|
4515
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_DISPOSE);
|
|
4500
4516
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4501
4517
|
this.getSessionStorage.clear(key);
|
|
4502
4518
|
};
|
|
@@ -4508,7 +4524,7 @@ class PersistSessionUtils {
|
|
|
4508
4524
|
* @param Ctor - Custom IPersistSessionInstance constructor
|
|
4509
4525
|
*/
|
|
4510
4526
|
usePersistSessionAdapter(Ctor) {
|
|
4511
|
-
LOGGER_SERVICE$
|
|
4527
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_USE_PERSIST_SESSION_ADAPTER);
|
|
4512
4528
|
this.PersistSessionInstanceCtor = Ctor;
|
|
4513
4529
|
this.getSessionStorage.clear();
|
|
4514
4530
|
}
|
|
@@ -4520,28 +4536,39 @@ class PersistSessionUtils {
|
|
|
4520
4536
|
const PersistSessionAdapter = new PersistSessionUtils();
|
|
4521
4537
|
|
|
4522
4538
|
var _a$2, _b$2;
|
|
4523
|
-
const BUSY_DELAY = 100;
|
|
4524
4539
|
const SET_BUSY_SYMBOL = Symbol("setBusy");
|
|
4525
4540
|
const GET_BUSY_SYMBOL = Symbol("getBusy");
|
|
4526
4541
|
const ACQUIRE_LOCK_SYMBOL = Symbol("acquireLock");
|
|
4527
4542
|
const RELEASE_LOCK_SYMBOL = Symbol("releaseLock");
|
|
4543
|
+
/**
|
|
4544
|
+
* Body of the queued acquire operation.
|
|
4545
|
+
*
|
|
4546
|
+
* Parks the caller on `self._tick` whenever the lock is already busy: each
|
|
4547
|
+
* `releaseLock` emits on `_tick`, waking exactly the next queued acquirer
|
|
4548
|
+
* instead of polling on a fixed delay. The busy counter is bumped only after
|
|
4549
|
+
* the loop exits, so re-entry checks remain coherent under contention.
|
|
4550
|
+
*
|
|
4551
|
+
* @param self - The owning {@link Lock} instance.
|
|
4552
|
+
*/
|
|
4528
4553
|
const ACQUIRE_LOCK_FN = async (self) => {
|
|
4529
4554
|
while (self[GET_BUSY_SYMBOL]()) {
|
|
4530
|
-
|
|
4555
|
+
// @ts-ignore
|
|
4556
|
+
await self._tick.toPromise();
|
|
4531
4557
|
}
|
|
4532
4558
|
self[SET_BUSY_SYMBOL](true);
|
|
4533
4559
|
};
|
|
4534
4560
|
/**
|
|
4535
4561
|
* Mutual exclusion primitive for async TypeScript code.
|
|
4536
4562
|
*
|
|
4537
|
-
* Provides a
|
|
4538
|
-
*
|
|
4539
|
-
*
|
|
4540
|
-
*
|
|
4563
|
+
* Provides a queued lock that serializes access to a critical section across
|
|
4564
|
+
* concurrent async callers. Wake-ups are event-driven (via an internal
|
|
4565
|
+
* `_tick` subject emitted on every `releaseLock`) rather than polling,
|
|
4566
|
+
* so contention does not incur a fixed delay.
|
|
4541
4567
|
*
|
|
4542
|
-
*
|
|
4568
|
+
* The busy counter detects mis-matched releases and throws immediately on
|
|
4569
|
+
* extra `releaseLock` calls.
|
|
4543
4570
|
*
|
|
4544
|
-
* **
|
|
4571
|
+
* **Usage**
|
|
4545
4572
|
* ```ts
|
|
4546
4573
|
* await lock.acquireLock();
|
|
4547
4574
|
* try {
|
|
@@ -4556,7 +4583,18 @@ const ACQUIRE_LOCK_FN = async (self) => {
|
|
|
4556
4583
|
*/
|
|
4557
4584
|
class Lock {
|
|
4558
4585
|
constructor() {
|
|
4586
|
+
/**
|
|
4587
|
+
* Outstanding acquires that have not yet been released.
|
|
4588
|
+
* Incremented in `[SET_BUSY_SYMBOL](true)`, decremented in `[SET_BUSY_SYMBOL](false)`.
|
|
4589
|
+
* A negative value indicates an extra `releaseLock` and throws on detection.
|
|
4590
|
+
*/
|
|
4559
4591
|
this._isBusy = 0;
|
|
4592
|
+
/**
|
|
4593
|
+
* Wake-up channel for {@link ACQUIRE_LOCK_FN}.
|
|
4594
|
+
* Every {@link releaseLock} emits a single tick that unblocks the next
|
|
4595
|
+
* queued acquirer parked on `toPromise()`.
|
|
4596
|
+
*/
|
|
4597
|
+
this._tick = new functoolsKit.Subject();
|
|
4560
4598
|
this[_a$2] = functoolsKit.queued(ACQUIRE_LOCK_FN);
|
|
4561
4599
|
this[_b$2] = () => this[SET_BUSY_SYMBOL](false);
|
|
4562
4600
|
/**
|
|
@@ -4577,16 +4615,19 @@ class Lock {
|
|
|
4577
4615
|
await this[ACQUIRE_LOCK_SYMBOL](this);
|
|
4578
4616
|
};
|
|
4579
4617
|
/**
|
|
4580
|
-
* Releases the lock previously acquired with {@link acquireLock}
|
|
4618
|
+
* Releases the lock previously acquired with {@link acquireLock} and emits
|
|
4619
|
+
* on the internal `_tick` subject to wake the next queued acquirer.
|
|
4620
|
+
*
|
|
4581
4621
|
* Must be called exactly once per successful {@link acquireLock} call,
|
|
4582
|
-
* typically inside a `finally` block. Throws if called more times
|
|
4583
|
-
*
|
|
4622
|
+
* typically inside a `finally` block. Throws if called more times than
|
|
4623
|
+
* the lock was acquired.
|
|
4584
4624
|
*
|
|
4585
4625
|
* @returns {Promise<void>} Resolves once the lock has been released.
|
|
4586
4626
|
* @throws {Error} If the lock is released more times than it was acquired.
|
|
4587
4627
|
*/
|
|
4588
4628
|
this.releaseLock = async () => {
|
|
4589
4629
|
await this[RELEASE_LOCK_SYMBOL]();
|
|
4630
|
+
await this._tick.next();
|
|
4590
4631
|
};
|
|
4591
4632
|
}
|
|
4592
4633
|
[SET_BUSY_SYMBOL](isBusy) {
|
|
@@ -4601,18 +4642,166 @@ class Lock {
|
|
|
4601
4642
|
}
|
|
4602
4643
|
_a$2 = ACQUIRE_LOCK_SYMBOL, _b$2 = RELEASE_LOCK_SYMBOL;
|
|
4603
4644
|
|
|
4645
|
+
const METHOD_NAME_ADD_ACTIVITY = "LookupUtils.addActivity";
|
|
4646
|
+
const METHOD_NAME_REMOVE_ACTIVITY = "LookupUtils.removeActivity";
|
|
4647
|
+
const METHOD_NAME_LIST_ACTIVITY = "LookupUtils.listActivity";
|
|
4648
|
+
/** Logger service injected as DI singleton */
|
|
4649
|
+
const LOGGER_SERVICE$7 = new LoggerService();
|
|
4650
|
+
/**
|
|
4651
|
+
* Builds the composite {@link Key} used to register an activity in `_lookupMap`.
|
|
4652
|
+
*
|
|
4653
|
+
* Mirrors the {@link Key} type construction: appends `frameName` only when provided
|
|
4654
|
+
* (typical for backtest), then a `"backtest"` / `"live"` discriminator suffix.
|
|
4655
|
+
*
|
|
4656
|
+
* @param symbol - Trading pair symbol.
|
|
4657
|
+
* @param strategyName - Strategy schema name.
|
|
4658
|
+
* @param exchangeName - Exchange schema name.
|
|
4659
|
+
* @param frameName - Frame schema name; omitted from the key when falsy.
|
|
4660
|
+
* @param backtest - `true` for backtest, `false` for live.
|
|
4661
|
+
* @returns Colon-joined composite key.
|
|
4662
|
+
*/
|
|
4663
|
+
const CREATE_KEY_FN$y = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
4664
|
+
const parts = [symbol, strategyName, exchangeName];
|
|
4665
|
+
if (frameName)
|
|
4666
|
+
parts.push(frameName);
|
|
4667
|
+
parts.push(backtest ? "backtest" : "live");
|
|
4668
|
+
return parts.join(":");
|
|
4669
|
+
};
|
|
4670
|
+
/**
|
|
4671
|
+
* In-memory registry of currently running backtest and live activities.
|
|
4672
|
+
*
|
|
4673
|
+
* Purpose:
|
|
4674
|
+
* - Each `Backtest.run` / `Live.run` / per-strategy walker iteration registers an
|
|
4675
|
+
* {@link IActivityEntry} on start and removes it on completion.
|
|
4676
|
+
* - `Candle.spinLock` consults {@link isParallel} to decide whether the event-loop
|
|
4677
|
+
* hand-off (post-candle-fetch spin) is worth performing. With a single active
|
|
4678
|
+
* workload there is no peer to yield to, so the spin is skipped entirely.
|
|
4679
|
+
*
|
|
4680
|
+
* Exposed as the `Lookup` singleton; no constructor parameters.
|
|
4681
|
+
*
|
|
4682
|
+
* @example
|
|
4683
|
+
* ```typescript
|
|
4684
|
+
* Lookup.addActivity({ symbol: "BTCUSDT", context, backtest: true });
|
|
4685
|
+
* try {
|
|
4686
|
+
* for await (const _ of run(symbol, context)) { ... }
|
|
4687
|
+
* } finally {
|
|
4688
|
+
* Lookup.removeActivity({ symbol: "BTCUSDT", context, backtest: true });
|
|
4689
|
+
* }
|
|
4690
|
+
* ```
|
|
4691
|
+
*/
|
|
4692
|
+
class LookupUtils {
|
|
4693
|
+
constructor() {
|
|
4694
|
+
/** Active entries keyed by their composite {@link Key}. */
|
|
4695
|
+
this._lookupMap = new Map();
|
|
4696
|
+
/**
|
|
4697
|
+
* Registers a backtest or live activity in the lookup map.
|
|
4698
|
+
* Idempotent for identical keys — duplicate calls overwrite the existing entry.
|
|
4699
|
+
*
|
|
4700
|
+
* @param activity - Activity descriptor identifying the running workload.
|
|
4701
|
+
*/
|
|
4702
|
+
this.addActivity = (activity) => {
|
|
4703
|
+
LOGGER_SERVICE$7.info(METHOD_NAME_ADD_ACTIVITY, {
|
|
4704
|
+
activity,
|
|
4705
|
+
});
|
|
4706
|
+
const key = CREATE_KEY_FN$y(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
|
|
4707
|
+
this._lookupMap.set(key, activity);
|
|
4708
|
+
};
|
|
4709
|
+
/**
|
|
4710
|
+
* Removes a previously registered activity from the lookup map.
|
|
4711
|
+
* Must be paired with a prior {@link addActivity}, typically in a `finally` block,
|
|
4712
|
+
* so a thrown error in the underlying run does not leave a stale entry behind.
|
|
4713
|
+
*
|
|
4714
|
+
* @param activity - Activity descriptor matching the one passed to {@link addActivity}.
|
|
4715
|
+
*/
|
|
4716
|
+
this.removeActivity = (activity) => {
|
|
4717
|
+
LOGGER_SERVICE$7.info(METHOD_NAME_REMOVE_ACTIVITY, {
|
|
4718
|
+
activity,
|
|
4719
|
+
});
|
|
4720
|
+
const key = CREATE_KEY_FN$y(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
|
|
4721
|
+
this._lookupMap.delete(key);
|
|
4722
|
+
};
|
|
4723
|
+
/**
|
|
4724
|
+
* Returns a snapshot of currently active entries.
|
|
4725
|
+
*
|
|
4726
|
+
* @returns Array of all activities present in the lookup map at call time.
|
|
4727
|
+
*/
|
|
4728
|
+
this.listActivity = () => {
|
|
4729
|
+
LOGGER_SERVICE$7.info(METHOD_NAME_LIST_ACTIVITY);
|
|
4730
|
+
return Array.from(this._lookupMap.values());
|
|
4731
|
+
};
|
|
4732
|
+
}
|
|
4733
|
+
/**
|
|
4734
|
+
* `true` when more than one activity is currently registered.
|
|
4735
|
+
* Used by `Candle.spinLock` to decide whether yielding the event loop is useful.
|
|
4736
|
+
*/
|
|
4737
|
+
get isParallel() {
|
|
4738
|
+
return this._lookupMap.size > 1;
|
|
4739
|
+
}
|
|
4740
|
+
}
|
|
4741
|
+
/**
|
|
4742
|
+
* Process-wide singleton instance of {@link LookupUtils}.
|
|
4743
|
+
* Imported by `Backtest`, `Live`, `WalkerLogicPrivateService` (registration sites)
|
|
4744
|
+
* and by `Candle` (read-only consumer via `isParallel`).
|
|
4745
|
+
*/
|
|
4746
|
+
const Lookup = new LookupUtils();
|
|
4747
|
+
|
|
4604
4748
|
const METHOD_NAME_ACQUIRE_LOCK = "CandleUtils.acquireLock";
|
|
4605
4749
|
const METHOD_NAME_RELEASE_LOCK = "CandleUtils.releaseLock";
|
|
4750
|
+
const METHOD_NAME_SPIN_LOCK = "CandleUtils.spinLock";
|
|
4751
|
+
/**
|
|
4752
|
+
* Upper bound (ms) on how long `spinLock` may park before falling through.
|
|
4753
|
+
* If no peer backtest acquires the candle-fetch mutex within this window,
|
|
4754
|
+
* the spinner proceeds without further yielding.
|
|
4755
|
+
*/
|
|
4756
|
+
const ROTATE_DELAY = 50;
|
|
4606
4757
|
/** Logger service injected as DI singleton */
|
|
4607
4758
|
const LOGGER_SERVICE$6 = new LoggerService();
|
|
4759
|
+
/**
|
|
4760
|
+
* Process-wide coordinator for candle-fetch serialization and cooperative
|
|
4761
|
+
* yielding between parallel backtests.
|
|
4762
|
+
*
|
|
4763
|
+
* Two complementary primitives are exposed:
|
|
4764
|
+
* - **Mutex** via {@link acquireLock} / {@link releaseLock}: prevents concurrent
|
|
4765
|
+
* candle fetches from racing on the same exchange.
|
|
4766
|
+
* - **Spin hand-off** via {@link spinLock}: invoked after a fetch completes to
|
|
4767
|
+
* give peer backtests waiting on the mutex a chance to run, so multiple
|
|
4768
|
+
* `Backtest.run` workloads interleave instead of one monopolizing the loop.
|
|
4769
|
+
*
|
|
4770
|
+
* All three operations are no-ops when `CC_ENABLE_CANDLE_FETCH_MUTEX` is `false`.
|
|
4771
|
+
* The spin additionally requires `CC_ENABLE_BACKTEST_PARALLEL_SPIN` and at least
|
|
4772
|
+
* two registered activities in `Lookup` (see `Lookup.isParallel`).
|
|
4773
|
+
*
|
|
4774
|
+
* @example
|
|
4775
|
+
* ```typescript
|
|
4776
|
+
* await Candle.acquireLock("ClientExchange GET_CANDLES_FN");
|
|
4777
|
+
* try {
|
|
4778
|
+
* const candles = await fetchFromExchange(...);
|
|
4779
|
+
* return candles;
|
|
4780
|
+
* } finally {
|
|
4781
|
+
* await Candle.releaseLock("ClientExchange GET_CANDLES_FN");
|
|
4782
|
+
* }
|
|
4783
|
+
* // Elsewhere, after a fetch completes inside a backtest loop:
|
|
4784
|
+
* await Candle.spinLock("BacktestLogicPrivateService GET_CANDLES_FN");
|
|
4785
|
+
* ```
|
|
4786
|
+
*/
|
|
4608
4787
|
class CandleUtils {
|
|
4609
4788
|
constructor() {
|
|
4789
|
+
/** Underlying mutex serializing candle fetches across concurrent callers. */
|
|
4610
4790
|
this._lock = new Lock();
|
|
4611
4791
|
/**
|
|
4612
|
-
*
|
|
4792
|
+
* Emits whenever {@link acquireLock} successfully takes the mutex.
|
|
4793
|
+
* Awaited by {@link spinLock} to detect that a peer backtest has just
|
|
4794
|
+
* started its own fetch — the signal that yielding now will be productive.
|
|
4795
|
+
*/
|
|
4796
|
+
this._spin = new functoolsKit.Subject();
|
|
4797
|
+
/**
|
|
4798
|
+
* Acquires the candle fetch mutex if `CC_ENABLE_CANDLE_FETCH_MUTEX` is enabled.
|
|
4613
4799
|
* Prevents concurrent candle fetches from the same exchange.
|
|
4614
4800
|
*
|
|
4615
|
-
*
|
|
4801
|
+
* On successful acquisition, emits on the internal spin subject so any
|
|
4802
|
+
* peer parked inside {@link spinLock} can wake up and proceed.
|
|
4803
|
+
*
|
|
4804
|
+
* @param source - Caller identifier for logging.
|
|
4616
4805
|
*/
|
|
4617
4806
|
this.acquireLock = async (source) => {
|
|
4618
4807
|
LOGGER_SERVICE$6.info(METHOD_NAME_ACQUIRE_LOCK, {
|
|
@@ -4621,13 +4810,14 @@ class CandleUtils {
|
|
|
4621
4810
|
if (!GLOBAL_CONFIG.CC_ENABLE_CANDLE_FETCH_MUTEX) {
|
|
4622
4811
|
return;
|
|
4623
4812
|
}
|
|
4624
|
-
|
|
4813
|
+
await this._lock.acquireLock();
|
|
4814
|
+
await this._spin.next();
|
|
4625
4815
|
};
|
|
4626
4816
|
/**
|
|
4627
|
-
* Releases the candle fetch mutex if CC_ENABLE_CANDLE_FETCH_MUTEX is enabled.
|
|
4628
|
-
* Must be called after acquireLock, typically in a finally block.
|
|
4817
|
+
* Releases the candle fetch mutex if `CC_ENABLE_CANDLE_FETCH_MUTEX` is enabled.
|
|
4818
|
+
* Must be called after {@link acquireLock}, typically in a `finally` block.
|
|
4629
4819
|
*
|
|
4630
|
-
* @param source - Caller identifier for logging
|
|
4820
|
+
* @param source - Caller identifier for logging.
|
|
4631
4821
|
*/
|
|
4632
4822
|
this.releaseLock = async (source) => {
|
|
4633
4823
|
LOGGER_SERVICE$6.info(METHOD_NAME_RELEASE_LOCK, {
|
|
@@ -4638,8 +4828,47 @@ class CandleUtils {
|
|
|
4638
4828
|
}
|
|
4639
4829
|
return await this._lock.releaseLock();
|
|
4640
4830
|
};
|
|
4831
|
+
/**
|
|
4832
|
+
* Cooperative event-loop hand-off invoked by `BacktestLogicPrivateService`
|
|
4833
|
+
* after a successful `getNextCandles`. Allows peer backtests waiting on the
|
|
4834
|
+
* candle-fetch mutex to run before the current backtest fetches the next chunk.
|
|
4835
|
+
*
|
|
4836
|
+
* Waits for one of:
|
|
4837
|
+
* - a peer calling {@link acquireLock} (signalled via the spin subject), or
|
|
4838
|
+
* - a `ROTATE_DELAY` ms timeout, so the caller never parks indefinitely.
|
|
4839
|
+
*
|
|
4840
|
+
* Returns immediately as a no-op when any of these is true:
|
|
4841
|
+
* - `CC_ENABLE_CANDLE_FETCH_MUTEX` is disabled (mutex is off entirely),
|
|
4842
|
+
* - `CC_ENABLE_BACKTEST_PARALLEL_SPIN` is disabled (cooperative yielding off),
|
|
4843
|
+
* - `Lookup.isParallel` is `false` (only one active workload — no peer to yield to).
|
|
4844
|
+
*
|
|
4845
|
+
* @param source - Caller identifier for logging.
|
|
4846
|
+
*/
|
|
4847
|
+
this.spinLock = async (source) => {
|
|
4848
|
+
LOGGER_SERVICE$6.info(METHOD_NAME_SPIN_LOCK, {
|
|
4849
|
+
source,
|
|
4850
|
+
});
|
|
4851
|
+
if (!GLOBAL_CONFIG.CC_ENABLE_CANDLE_FETCH_MUTEX) {
|
|
4852
|
+
return;
|
|
4853
|
+
}
|
|
4854
|
+
if (!GLOBAL_CONFIG.CC_ENABLE_BACKTEST_PARALLEL_SPIN) {
|
|
4855
|
+
return;
|
|
4856
|
+
}
|
|
4857
|
+
if (!Lookup.isParallel) {
|
|
4858
|
+
return;
|
|
4859
|
+
}
|
|
4860
|
+
await Promise.race([
|
|
4861
|
+
this._spin.toPromise(),
|
|
4862
|
+
functoolsKit.sleep(ROTATE_DELAY),
|
|
4863
|
+
]);
|
|
4864
|
+
};
|
|
4641
4865
|
}
|
|
4642
4866
|
}
|
|
4867
|
+
/**
|
|
4868
|
+
* Process-wide singleton instance of {@link CandleUtils}.
|
|
4869
|
+
* Imported by `ClientExchange` (mutex around exchange fetches) and by
|
|
4870
|
+
* `BacktestLogicPrivateService` (spin hand-off between parallel backtests).
|
|
4871
|
+
*/
|
|
4643
4872
|
const Candle = new CandleUtils();
|
|
4644
4873
|
|
|
4645
4874
|
const MS_PER_MINUTE$7 = 60000;
|
|
@@ -19173,9 +19402,28 @@ const TICK_FN = async (self, symbol, when) => {
|
|
|
19173
19402
|
return { type: "error", __error__: SYMBOL_FN_ERROR, reason: "TICK_FN", message: functoolsKit.getErrorMessage(error) };
|
|
19174
19403
|
}
|
|
19175
19404
|
};
|
|
19405
|
+
/**
|
|
19406
|
+
* Wraps `exchangeCoreService.getNextCandles` with error capture and a cooperative
|
|
19407
|
+
* event-loop hand-off after a successful fetch.
|
|
19408
|
+
*
|
|
19409
|
+
* Calls `Candle.spinLock(...)` on success: when multiple backtests run in parallel
|
|
19410
|
+
* (`Lookup.isParallel === true`), this yields the event loop so a peer waiting on
|
|
19411
|
+
* the candle-fetch mutex can take its turn, producing round-robin interleaving
|
|
19412
|
+
* instead of one backtest monopolizing the loop until completion. The spin is a
|
|
19413
|
+
* no-op for single-workload runs.
|
|
19414
|
+
*
|
|
19415
|
+
* @param self - Owning service instance, used for logging and exchange access.
|
|
19416
|
+
* @param symbol - Trading pair symbol.
|
|
19417
|
+
* @param candlesNeeded - Number of 1m candles to request.
|
|
19418
|
+
* @param bufferStartTime - Inclusive start time for the fetch window.
|
|
19419
|
+
* @param logMeta - Extra structured fields appended to the warn log on failure.
|
|
19420
|
+
* @returns Fetched candles, or a {@link TFnError} discriminated union on failure.
|
|
19421
|
+
*/
|
|
19176
19422
|
const GET_CANDLES_FN = async (self, symbol, candlesNeeded, bufferStartTime, logMeta) => {
|
|
19177
19423
|
try {
|
|
19178
|
-
|
|
19424
|
+
const result = await self.exchangeCoreService.getNextCandles(symbol, "1m", candlesNeeded, bufferStartTime, true);
|
|
19425
|
+
await Candle.spinLock("BacktestLogicPrivateService GET_CANDLES_FN");
|
|
19426
|
+
return result;
|
|
19179
19427
|
}
|
|
19180
19428
|
catch (error) {
|
|
19181
19429
|
console.error(`backtestLogicPrivateService getNextCandles failed symbol=${symbol} strategyName=${self.methodContextService.context.strategyName} exchangeName=${self.methodContextService.context.exchangeName}`);
|
|
@@ -20061,6 +20309,15 @@ class WalkerLogicPrivateService {
|
|
|
20061
20309
|
exchangeName: context.exchangeName,
|
|
20062
20310
|
frameName: context.frameName,
|
|
20063
20311
|
});
|
|
20312
|
+
Lookup.addActivity({
|
|
20313
|
+
symbol,
|
|
20314
|
+
context: {
|
|
20315
|
+
strategyName,
|
|
20316
|
+
exchangeName: context.exchangeName,
|
|
20317
|
+
frameName: context.frameName,
|
|
20318
|
+
},
|
|
20319
|
+
backtest: true,
|
|
20320
|
+
});
|
|
20064
20321
|
try {
|
|
20065
20322
|
await functoolsKit.resolveDocuments(iterator);
|
|
20066
20323
|
}
|
|
@@ -20076,6 +20333,17 @@ class WalkerLogicPrivateService {
|
|
|
20076
20333
|
await CALL_STRATEGY_ERROR_CALLBACKS_FN(this, walkerSchema, strategyName, symbol, error);
|
|
20077
20334
|
continue;
|
|
20078
20335
|
}
|
|
20336
|
+
finally {
|
|
20337
|
+
Lookup.removeActivity({
|
|
20338
|
+
symbol,
|
|
20339
|
+
context: {
|
|
20340
|
+
strategyName,
|
|
20341
|
+
exchangeName: context.exchangeName,
|
|
20342
|
+
frameName: context.frameName,
|
|
20343
|
+
},
|
|
20344
|
+
backtest: true,
|
|
20345
|
+
});
|
|
20346
|
+
}
|
|
20079
20347
|
this.loggerService.info("walkerLogicPrivateService backtest complete", {
|
|
20080
20348
|
strategyName,
|
|
20081
20349
|
symbol,
|
|
@@ -36095,6 +36363,7 @@ const Exchange = new ExchangeUtils();
|
|
|
36095
36363
|
|
|
36096
36364
|
const WARM_CANDLES_METHOD_NAME = "cache.warmCandles";
|
|
36097
36365
|
const CHECK_CANDLES_METHOD_NAME = "cache.checkCandles";
|
|
36366
|
+
const CACHE_CANDLES_METHOD_NAME = "cache.cacheCandles";
|
|
36098
36367
|
const MS_PER_MINUTE$3 = 60000;
|
|
36099
36368
|
const INTERVAL_MINUTES$3 = {
|
|
36100
36369
|
"1m": 1,
|
|
@@ -36126,6 +36395,34 @@ const PRINT_PROGRESS_FN = (fetched, total, symbol, interval) => {
|
|
|
36126
36395
|
process.stdout.write("\n");
|
|
36127
36396
|
}
|
|
36128
36397
|
};
|
|
36398
|
+
/**
|
|
36399
|
+
* Retry-wrapped pipeline: validates the cache via `checkCandles` and, on miss,
|
|
36400
|
+
* fills it via `warmCandles` and rethrows to trigger a retry pass that
|
|
36401
|
+
* re-validates the freshly cached range. Limited to 2 attempts.
|
|
36402
|
+
*/
|
|
36403
|
+
const CACHE_CANDLES_FN = functoolsKit.retry(async (interval, dto, onWarmStart, onCheckStart) => {
|
|
36404
|
+
try {
|
|
36405
|
+
onWarmStart && onWarmStart(dto.symbol, interval, dto.from, dto.to);
|
|
36406
|
+
await checkCandles({
|
|
36407
|
+
exchangeName: dto.exchangeName,
|
|
36408
|
+
from: dto.from,
|
|
36409
|
+
to: dto.to,
|
|
36410
|
+
symbol: dto.symbol,
|
|
36411
|
+
interval: interval,
|
|
36412
|
+
});
|
|
36413
|
+
}
|
|
36414
|
+
catch (error) {
|
|
36415
|
+
onCheckStart && onCheckStart(dto.symbol, interval, dto.from, dto.to);
|
|
36416
|
+
await warmCandles({
|
|
36417
|
+
symbol: dto.symbol,
|
|
36418
|
+
exchangeName: dto.exchangeName,
|
|
36419
|
+
from: dto.from,
|
|
36420
|
+
to: dto.to,
|
|
36421
|
+
interval: interval,
|
|
36422
|
+
});
|
|
36423
|
+
throw error;
|
|
36424
|
+
}
|
|
36425
|
+
}, 2);
|
|
36129
36426
|
/**
|
|
36130
36427
|
* Checks cached candle presence via the persist adapter.
|
|
36131
36428
|
* Issues one ranged read; adapter-side `hasValue` covers each expected timestamp,
|
|
@@ -36201,6 +36498,34 @@ async function warmCandles(params) {
|
|
|
36201
36498
|
PRINT_PROGRESS_FN(fetched, totalCandles, symbol, interval);
|
|
36202
36499
|
}
|
|
36203
36500
|
}
|
|
36501
|
+
/**
|
|
36502
|
+
* Ensures candles for the given range are present in persist storage.
|
|
36503
|
+
* Runs a check-then-warm pipeline with one retry: validates the cache first
|
|
36504
|
+
* and, on a miss, downloads the missing data and re-validates.
|
|
36505
|
+
*
|
|
36506
|
+
* @param params - Combined cache parameters with optional lifecycle callbacks
|
|
36507
|
+
*/
|
|
36508
|
+
async function cacheCandles({ symbol, interval, from, to, exchangeName, onCheckStart = (symbol, interval, from, to) => {
|
|
36509
|
+
process.stdout.write("\n");
|
|
36510
|
+
process.stdout.write(`Checking candles cache for ${symbol} ${interval} from ${from} to ${to}\n`);
|
|
36511
|
+
}, onWarmStart = (symbol, interval, from, to) => {
|
|
36512
|
+
process.stdout.write("\n\n");
|
|
36513
|
+
process.stdout.write(`Caching candles for ${symbol} ${interval} from ${from} to ${to}\n`);
|
|
36514
|
+
}, }) {
|
|
36515
|
+
backtest.loggerService.info(CACHE_CANDLES_METHOD_NAME, {
|
|
36516
|
+
symbol,
|
|
36517
|
+
exchangeName,
|
|
36518
|
+
interval,
|
|
36519
|
+
from,
|
|
36520
|
+
to,
|
|
36521
|
+
});
|
|
36522
|
+
await CACHE_CANDLES_FN(interval, {
|
|
36523
|
+
exchangeName,
|
|
36524
|
+
from,
|
|
36525
|
+
to,
|
|
36526
|
+
symbol,
|
|
36527
|
+
}, onWarmStart, onCheckStart);
|
|
36528
|
+
}
|
|
36204
36529
|
|
|
36205
36530
|
const METHOD_NAME = "validate.validate";
|
|
36206
36531
|
/**
|
|
@@ -37412,7 +37737,19 @@ class BrokerProxy {
|
|
|
37412
37737
|
*/
|
|
37413
37738
|
class BrokerAdapter {
|
|
37414
37739
|
constructor() {
|
|
37415
|
-
|
|
37740
|
+
/** Factory producing the active `BrokerProxy` instance */
|
|
37741
|
+
this._brokerFactory = () => null;
|
|
37742
|
+
/**
|
|
37743
|
+
* Lazily constructs the `BrokerProxy` from the registered factory and
|
|
37744
|
+
* memoizes the result via `singleshot`.
|
|
37745
|
+
*
|
|
37746
|
+
* The proxy is built on the first call and cached for all subsequent calls.
|
|
37747
|
+
* Returns `null` when no adapter has been registered via `useBrokerAdapter()`.
|
|
37748
|
+
*
|
|
37749
|
+
* Reset via `clear()` so the next call rebuilds from the current factory
|
|
37750
|
+
* (e.g. when `process.cwd()` changes between strategy iterations).
|
|
37751
|
+
*/
|
|
37752
|
+
this.getInstance = functoolsKit.singleshot(() => this._brokerFactory());
|
|
37416
37753
|
/**
|
|
37417
37754
|
* Forwards a signal-open event to the registered broker adapter.
|
|
37418
37755
|
*
|
|
@@ -37446,7 +37783,10 @@ class BrokerAdapter {
|
|
|
37446
37783
|
if (payload.backtest) {
|
|
37447
37784
|
return;
|
|
37448
37785
|
}
|
|
37449
|
-
|
|
37786
|
+
const instance = this.getInstance();
|
|
37787
|
+
if (instance) {
|
|
37788
|
+
await instance.onSignalOpenCommit(payload);
|
|
37789
|
+
}
|
|
37450
37790
|
};
|
|
37451
37791
|
/**
|
|
37452
37792
|
* Forwards a signal-close event to the registered broker adapter.
|
|
@@ -37484,7 +37824,10 @@ class BrokerAdapter {
|
|
|
37484
37824
|
if (payload.backtest) {
|
|
37485
37825
|
return;
|
|
37486
37826
|
}
|
|
37487
|
-
|
|
37827
|
+
const instance = this.getInstance();
|
|
37828
|
+
if (instance) {
|
|
37829
|
+
await instance.onSignalCloseCommit(payload);
|
|
37830
|
+
}
|
|
37488
37831
|
};
|
|
37489
37832
|
/**
|
|
37490
37833
|
* Intercepts a partial-profit close before DI-core mutation.
|
|
@@ -37520,7 +37863,10 @@ class BrokerAdapter {
|
|
|
37520
37863
|
if (payload.backtest) {
|
|
37521
37864
|
return;
|
|
37522
37865
|
}
|
|
37523
|
-
|
|
37866
|
+
const instance = this.getInstance();
|
|
37867
|
+
if (instance) {
|
|
37868
|
+
await instance.onPartialProfitCommit(payload);
|
|
37869
|
+
}
|
|
37524
37870
|
};
|
|
37525
37871
|
/**
|
|
37526
37872
|
* Intercepts a partial-loss close before DI-core mutation.
|
|
@@ -37556,7 +37902,10 @@ class BrokerAdapter {
|
|
|
37556
37902
|
if (payload.backtest) {
|
|
37557
37903
|
return;
|
|
37558
37904
|
}
|
|
37559
|
-
|
|
37905
|
+
const instance = this.getInstance();
|
|
37906
|
+
if (instance) {
|
|
37907
|
+
await instance.onPartialLossCommit(payload);
|
|
37908
|
+
}
|
|
37560
37909
|
};
|
|
37561
37910
|
/**
|
|
37562
37911
|
* Intercepts a trailing stop-loss update before DI-core mutation.
|
|
@@ -37592,7 +37941,10 @@ class BrokerAdapter {
|
|
|
37592
37941
|
if (payload.backtest) {
|
|
37593
37942
|
return;
|
|
37594
37943
|
}
|
|
37595
|
-
|
|
37944
|
+
const instance = this.getInstance();
|
|
37945
|
+
if (instance) {
|
|
37946
|
+
await instance.onTrailingStopCommit(payload);
|
|
37947
|
+
}
|
|
37596
37948
|
};
|
|
37597
37949
|
/**
|
|
37598
37950
|
* Intercepts a trailing take-profit update before DI-core mutation.
|
|
@@ -37628,7 +37980,10 @@ class BrokerAdapter {
|
|
|
37628
37980
|
if (payload.backtest) {
|
|
37629
37981
|
return;
|
|
37630
37982
|
}
|
|
37631
|
-
|
|
37983
|
+
const instance = this.getInstance();
|
|
37984
|
+
if (instance) {
|
|
37985
|
+
await instance.onTrailingTakeCommit(payload);
|
|
37986
|
+
}
|
|
37632
37987
|
};
|
|
37633
37988
|
/**
|
|
37634
37989
|
* Intercepts a breakeven operation before DI-core mutation.
|
|
@@ -37665,7 +38020,10 @@ class BrokerAdapter {
|
|
|
37665
38020
|
if (payload.backtest) {
|
|
37666
38021
|
return;
|
|
37667
38022
|
}
|
|
37668
|
-
|
|
38023
|
+
const instance = this.getInstance();
|
|
38024
|
+
if (instance) {
|
|
38025
|
+
await instance.onBreakevenCommit(payload);
|
|
38026
|
+
}
|
|
37669
38027
|
};
|
|
37670
38028
|
/**
|
|
37671
38029
|
* Intercepts a DCA average-buy entry before DI-core mutation.
|
|
@@ -37701,7 +38059,10 @@ class BrokerAdapter {
|
|
|
37701
38059
|
if (payload.backtest) {
|
|
37702
38060
|
return;
|
|
37703
38061
|
}
|
|
37704
|
-
|
|
38062
|
+
const instance = this.getInstance();
|
|
38063
|
+
if (instance) {
|
|
38064
|
+
await instance.onAverageBuyCommit(payload);
|
|
38065
|
+
}
|
|
37705
38066
|
};
|
|
37706
38067
|
/**
|
|
37707
38068
|
* Registers a broker adapter instance or constructor to receive commit* callbacks.
|
|
@@ -37725,11 +38086,12 @@ class BrokerAdapter {
|
|
|
37725
38086
|
this.useBrokerAdapter = (broker) => {
|
|
37726
38087
|
backtest.loggerService.info(BROKER_METHOD_NAME_USE_BROKER_ADAPTER, {});
|
|
37727
38088
|
if (typeof broker === "function") {
|
|
37728
|
-
|
|
37729
|
-
this._brokerInstance = new BrokerProxy(instance);
|
|
37730
|
-
return;
|
|
38089
|
+
this._brokerFactory = () => new BrokerProxy(Reflect.construct(broker, []));
|
|
37731
38090
|
}
|
|
37732
|
-
|
|
38091
|
+
else {
|
|
38092
|
+
this._brokerFactory = () => new BrokerProxy(broker);
|
|
38093
|
+
}
|
|
38094
|
+
this.getInstance.clear();
|
|
37733
38095
|
};
|
|
37734
38096
|
/**
|
|
37735
38097
|
* Activates the broker: subscribes to syncSubject for signal-open / signal-close routing.
|
|
@@ -37756,7 +38118,8 @@ class BrokerAdapter {
|
|
|
37756
38118
|
*/
|
|
37757
38119
|
this.enable = functoolsKit.singleshot(() => {
|
|
37758
38120
|
backtest.loggerService.info(BROKER_METHOD_NAME_ENABLE, {});
|
|
37759
|
-
|
|
38121
|
+
const instance = this.getInstance();
|
|
38122
|
+
if (!instance) {
|
|
37760
38123
|
this.enable.clear();
|
|
37761
38124
|
throw new Error("No broker instance provided. Call Broker.useBrokerAdapter first.");
|
|
37762
38125
|
}
|
|
@@ -37844,7 +38207,7 @@ class BrokerAdapter {
|
|
|
37844
38207
|
*/
|
|
37845
38208
|
this.clear = () => {
|
|
37846
38209
|
backtest.loggerService.info(BROKER_METHOD_NAME_CLEAR, {});
|
|
37847
|
-
this.
|
|
38210
|
+
this.getInstance.clear();
|
|
37848
38211
|
this.enable.clear();
|
|
37849
38212
|
};
|
|
37850
38213
|
}
|
|
@@ -41948,11 +42311,21 @@ const INSTANCE_TASK_FN$2 = async (symbol, context, self) => {
|
|
|
41948
42311
|
self._isStopped = false;
|
|
41949
42312
|
self._isDone = false;
|
|
41950
42313
|
}
|
|
42314
|
+
Lookup.addActivity({
|
|
42315
|
+
symbol,
|
|
42316
|
+
context,
|
|
42317
|
+
backtest: true,
|
|
42318
|
+
});
|
|
41951
42319
|
for await (const _ of self.run(symbol, context)) {
|
|
41952
42320
|
if (self._isStopped) {
|
|
41953
42321
|
break;
|
|
41954
42322
|
}
|
|
41955
42323
|
}
|
|
42324
|
+
Lookup.removeActivity({
|
|
42325
|
+
symbol,
|
|
42326
|
+
context,
|
|
42327
|
+
backtest: true,
|
|
42328
|
+
});
|
|
41956
42329
|
if (!self._isDone) {
|
|
41957
42330
|
await doneBacktestSubject.next({
|
|
41958
42331
|
exchangeName: context.exchangeName,
|
|
@@ -44599,11 +44972,21 @@ const INSTANCE_TASK_FN$1 = async (symbol, context, self) => {
|
|
|
44599
44972
|
self._isStopped = false;
|
|
44600
44973
|
self._isDone = false;
|
|
44601
44974
|
}
|
|
44975
|
+
Lookup.addActivity({
|
|
44976
|
+
symbol,
|
|
44977
|
+
context,
|
|
44978
|
+
backtest: false,
|
|
44979
|
+
});
|
|
44602
44980
|
for await (const signal of self.run(symbol, context)) {
|
|
44603
44981
|
if (signal?.action === "closed" && self._isStopped) {
|
|
44604
44982
|
break;
|
|
44605
44983
|
}
|
|
44606
44984
|
}
|
|
44985
|
+
Lookup.removeActivity({
|
|
44986
|
+
symbol,
|
|
44987
|
+
context,
|
|
44988
|
+
backtest: false,
|
|
44989
|
+
});
|
|
44607
44990
|
if (!self._isDone) {
|
|
44608
44991
|
await doneLiveSubject.next({
|
|
44609
44992
|
exchangeName: context.exchangeName,
|
|
@@ -48864,8 +49247,16 @@ class RecentMemoryLiveUtils {
|
|
|
48864
49247
|
*/
|
|
48865
49248
|
class RecentBacktestAdapter {
|
|
48866
49249
|
constructor() {
|
|
48867
|
-
/**
|
|
48868
|
-
this.
|
|
49250
|
+
/** Factory producing the active storage utils instance */
|
|
49251
|
+
this._recentBacktestFactory = () => new RecentMemoryBacktestUtils();
|
|
49252
|
+
/**
|
|
49253
|
+
* Lazily constructs the storage utils from the registered factory and memoizes
|
|
49254
|
+
* the result via `singleshot`.
|
|
49255
|
+
*
|
|
49256
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
49257
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
49258
|
+
*/
|
|
49259
|
+
this.getInstance = functoolsKit.singleshot(() => this._recentBacktestFactory());
|
|
48869
49260
|
/**
|
|
48870
49261
|
* Handles active ping event.
|
|
48871
49262
|
* Proxies call to the underlying storage adapter.
|
|
@@ -48875,7 +49266,7 @@ class RecentBacktestAdapter {
|
|
|
48875
49266
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_HANDLE_ACTIVE_PING, {
|
|
48876
49267
|
signalId: event.data.id,
|
|
48877
49268
|
});
|
|
48878
|
-
return await this.
|
|
49269
|
+
return await this.getInstance().handleActivePing(event);
|
|
48879
49270
|
};
|
|
48880
49271
|
/**
|
|
48881
49272
|
* Retrieves the latest signal for the given context.
|
|
@@ -48896,7 +49287,7 @@ class RecentBacktestAdapter {
|
|
|
48896
49287
|
frameName,
|
|
48897
49288
|
backtest: backtest$1,
|
|
48898
49289
|
});
|
|
48899
|
-
return await this.
|
|
49290
|
+
return await this.getInstance().getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1, when);
|
|
48900
49291
|
};
|
|
48901
49292
|
/**
|
|
48902
49293
|
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
@@ -48920,7 +49311,7 @@ class RecentBacktestAdapter {
|
|
|
48920
49311
|
backtest: backtest$1,
|
|
48921
49312
|
timestamp,
|
|
48922
49313
|
});
|
|
48923
|
-
const signal = await this.
|
|
49314
|
+
const signal = await this.getInstance().getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1, new Date(timestamp));
|
|
48924
49315
|
if (!signal) {
|
|
48925
49316
|
return null;
|
|
48926
49317
|
}
|
|
@@ -48933,7 +49324,8 @@ class RecentBacktestAdapter {
|
|
|
48933
49324
|
*/
|
|
48934
49325
|
this.useRecentAdapter = (Ctor) => {
|
|
48935
49326
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
48936
|
-
this.
|
|
49327
|
+
this._recentBacktestFactory = () => Reflect.construct(Ctor, []);
|
|
49328
|
+
this.getInstance.clear();
|
|
48937
49329
|
};
|
|
48938
49330
|
/**
|
|
48939
49331
|
* Switches to persistent storage adapter.
|
|
@@ -48941,7 +49333,8 @@ class RecentBacktestAdapter {
|
|
|
48941
49333
|
*/
|
|
48942
49334
|
this.usePersist = () => {
|
|
48943
49335
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
48944
|
-
this.
|
|
49336
|
+
this._recentBacktestFactory = () => new RecentPersistBacktestUtils();
|
|
49337
|
+
this.getInstance.clear();
|
|
48945
49338
|
};
|
|
48946
49339
|
/**
|
|
48947
49340
|
* Switches to in-memory storage adapter (default).
|
|
@@ -48949,14 +49342,17 @@ class RecentBacktestAdapter {
|
|
|
48949
49342
|
*/
|
|
48950
49343
|
this.useMemory = () => {
|
|
48951
49344
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
48952
|
-
this.
|
|
49345
|
+
this._recentBacktestFactory = () => new RecentMemoryBacktestUtils();
|
|
49346
|
+
this.getInstance.clear();
|
|
48953
49347
|
};
|
|
48954
49348
|
/**
|
|
48955
|
-
* Clears the
|
|
49349
|
+
* Clears the memoized utils instance.
|
|
49350
|
+
* Call this when process.cwd() changes between strategy iterations
|
|
49351
|
+
* so a new instance is created with the updated base path.
|
|
48956
49352
|
*/
|
|
48957
49353
|
this.clear = () => {
|
|
48958
49354
|
backtest.loggerService.info(RECENT_BACKTEST_ADAPTER_METHOD_NAME_CLEAR);
|
|
48959
|
-
this.
|
|
49355
|
+
this.getInstance.clear();
|
|
48960
49356
|
};
|
|
48961
49357
|
}
|
|
48962
49358
|
}
|
|
@@ -48971,8 +49367,16 @@ class RecentBacktestAdapter {
|
|
|
48971
49367
|
*/
|
|
48972
49368
|
class RecentLiveAdapter {
|
|
48973
49369
|
constructor() {
|
|
48974
|
-
/**
|
|
48975
|
-
this.
|
|
49370
|
+
/** Factory producing the active storage utils instance */
|
|
49371
|
+
this._recentLiveFactory = () => new RecentPersistLiveUtils();
|
|
49372
|
+
/**
|
|
49373
|
+
* Lazily constructs the storage utils from the registered factory and memoizes
|
|
49374
|
+
* the result via `singleshot`.
|
|
49375
|
+
*
|
|
49376
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
49377
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
49378
|
+
*/
|
|
49379
|
+
this.getInstance = functoolsKit.singleshot(() => this._recentLiveFactory());
|
|
48976
49380
|
/**
|
|
48977
49381
|
* Handles active ping event.
|
|
48978
49382
|
* Proxies call to the underlying storage adapter.
|
|
@@ -48982,7 +49386,7 @@ class RecentLiveAdapter {
|
|
|
48982
49386
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_HANDLE_ACTIVE_PING, {
|
|
48983
49387
|
signalId: event.data.id,
|
|
48984
49388
|
});
|
|
48985
|
-
return await this.
|
|
49389
|
+
return await this.getInstance().handleActivePing(event);
|
|
48986
49390
|
};
|
|
48987
49391
|
/**
|
|
48988
49392
|
* Retrieves the latest signal for the given context.
|
|
@@ -49003,7 +49407,7 @@ class RecentLiveAdapter {
|
|
|
49003
49407
|
frameName,
|
|
49004
49408
|
backtest: backtest$1,
|
|
49005
49409
|
});
|
|
49006
|
-
return await this.
|
|
49410
|
+
return await this.getInstance().getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1, when);
|
|
49007
49411
|
};
|
|
49008
49412
|
/**
|
|
49009
49413
|
* Returns the number of whole minutes elapsed since the latest signal's creation timestamp.
|
|
@@ -49027,7 +49431,7 @@ class RecentLiveAdapter {
|
|
|
49027
49431
|
backtest: backtest$1,
|
|
49028
49432
|
timestamp,
|
|
49029
49433
|
});
|
|
49030
|
-
const signal = await this.
|
|
49434
|
+
const signal = await this.getInstance().getLatestSignal(symbol, strategyName, exchangeName, frameName, backtest$1, new Date(timestamp));
|
|
49031
49435
|
if (!signal) {
|
|
49032
49436
|
return null;
|
|
49033
49437
|
}
|
|
@@ -49040,7 +49444,8 @@ class RecentLiveAdapter {
|
|
|
49040
49444
|
*/
|
|
49041
49445
|
this.useRecentAdapter = (Ctor) => {
|
|
49042
49446
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
49043
|
-
this.
|
|
49447
|
+
this._recentLiveFactory = () => Reflect.construct(Ctor, []);
|
|
49448
|
+
this.getInstance.clear();
|
|
49044
49449
|
};
|
|
49045
49450
|
/**
|
|
49046
49451
|
* Switches to persistent storage adapter (default).
|
|
@@ -49048,7 +49453,8 @@ class RecentLiveAdapter {
|
|
|
49048
49453
|
*/
|
|
49049
49454
|
this.usePersist = () => {
|
|
49050
49455
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
49051
|
-
this.
|
|
49456
|
+
this._recentLiveFactory = () => new RecentPersistLiveUtils();
|
|
49457
|
+
this.getInstance.clear();
|
|
49052
49458
|
};
|
|
49053
49459
|
/**
|
|
49054
49460
|
* Switches to in-memory storage adapter.
|
|
@@ -49056,14 +49462,17 @@ class RecentLiveAdapter {
|
|
|
49056
49462
|
*/
|
|
49057
49463
|
this.useMemory = () => {
|
|
49058
49464
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
49059
|
-
this.
|
|
49465
|
+
this._recentLiveFactory = () => new RecentMemoryLiveUtils();
|
|
49466
|
+
this.getInstance.clear();
|
|
49060
49467
|
};
|
|
49061
49468
|
/**
|
|
49062
|
-
* Clears the
|
|
49469
|
+
* Clears the memoized utils instance.
|
|
49470
|
+
* Call this when process.cwd() changes between strategy iterations
|
|
49471
|
+
* so a new instance is created with the updated base path.
|
|
49063
49472
|
*/
|
|
49064
49473
|
this.clear = () => {
|
|
49065
49474
|
backtest.loggerService.info(RECENT_LIVE_ADAPTER_METHOD_NAME_CLEAR);
|
|
49066
|
-
this.
|
|
49475
|
+
this.getInstance.clear();
|
|
49067
49476
|
};
|
|
49068
49477
|
}
|
|
49069
49478
|
}
|
|
@@ -54388,16 +54797,26 @@ class LogDummyUtils {
|
|
|
54388
54797
|
*/
|
|
54389
54798
|
class LogAdapter {
|
|
54390
54799
|
constructor() {
|
|
54391
|
-
/**
|
|
54392
|
-
this.
|
|
54800
|
+
/** Factory producing the active log utils instance */
|
|
54801
|
+
this._logFactory = () => new LogMemoryUtils();
|
|
54802
|
+
/**
|
|
54803
|
+
* Lazily constructs the log utils from the registered factory and memoizes
|
|
54804
|
+
* the result via `singleshot`.
|
|
54805
|
+
*
|
|
54806
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
54807
|
+
* Reset via `clear()` so the next call rebuilds from the current factory
|
|
54808
|
+
* (e.g. when `process.cwd()` changes between strategy iterations).
|
|
54809
|
+
*/
|
|
54810
|
+
this.getInstance = functoolsKit.singleshot(() => this._logFactory());
|
|
54393
54811
|
/**
|
|
54394
54812
|
* Lists all stored log entries.
|
|
54395
54813
|
* Proxies call to the underlying log adapter.
|
|
54396
54814
|
* @returns Array of all log entries
|
|
54397
54815
|
*/
|
|
54398
54816
|
this.getList = async () => {
|
|
54399
|
-
|
|
54400
|
-
|
|
54817
|
+
const log = this.getInstance();
|
|
54818
|
+
if (log.getList) {
|
|
54819
|
+
return await log.getList();
|
|
54401
54820
|
}
|
|
54402
54821
|
return [];
|
|
54403
54822
|
};
|
|
@@ -54408,8 +54827,9 @@ class LogAdapter {
|
|
|
54408
54827
|
* @param args - Additional arguments
|
|
54409
54828
|
*/
|
|
54410
54829
|
this.log = (topic, ...args) => {
|
|
54411
|
-
|
|
54412
|
-
|
|
54830
|
+
const log = this.getInstance();
|
|
54831
|
+
if (log.log) {
|
|
54832
|
+
log.log(topic, ...args);
|
|
54413
54833
|
}
|
|
54414
54834
|
};
|
|
54415
54835
|
/**
|
|
@@ -54419,8 +54839,9 @@ class LogAdapter {
|
|
|
54419
54839
|
* @param args - Additional arguments
|
|
54420
54840
|
*/
|
|
54421
54841
|
this.debug = (topic, ...args) => {
|
|
54422
|
-
|
|
54423
|
-
|
|
54842
|
+
const log = this.getInstance();
|
|
54843
|
+
if (log.debug) {
|
|
54844
|
+
log.debug(topic, ...args);
|
|
54424
54845
|
}
|
|
54425
54846
|
};
|
|
54426
54847
|
/**
|
|
@@ -54430,8 +54851,9 @@ class LogAdapter {
|
|
|
54430
54851
|
* @param args - Additional arguments
|
|
54431
54852
|
*/
|
|
54432
54853
|
this.info = (topic, ...args) => {
|
|
54433
|
-
|
|
54434
|
-
|
|
54854
|
+
const log = this.getInstance();
|
|
54855
|
+
if (log.info) {
|
|
54856
|
+
log.info(topic, ...args);
|
|
54435
54857
|
}
|
|
54436
54858
|
};
|
|
54437
54859
|
/**
|
|
@@ -54441,8 +54863,9 @@ class LogAdapter {
|
|
|
54441
54863
|
* @param args - Additional arguments
|
|
54442
54864
|
*/
|
|
54443
54865
|
this.warn = (topic, ...args) => {
|
|
54444
|
-
|
|
54445
|
-
|
|
54866
|
+
const log = this.getInstance();
|
|
54867
|
+
if (log.warn) {
|
|
54868
|
+
log.warn(topic, ...args);
|
|
54446
54869
|
}
|
|
54447
54870
|
};
|
|
54448
54871
|
/**
|
|
@@ -54452,7 +54875,8 @@ class LogAdapter {
|
|
|
54452
54875
|
*/
|
|
54453
54876
|
this.useLogger = (Ctor) => {
|
|
54454
54877
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_LOGGER);
|
|
54455
|
-
this.
|
|
54878
|
+
this._logFactory = () => Reflect.construct(Ctor, []);
|
|
54879
|
+
this.getInstance.clear();
|
|
54456
54880
|
};
|
|
54457
54881
|
/**
|
|
54458
54882
|
* Switches to persistent log adapter.
|
|
@@ -54460,7 +54884,8 @@ class LogAdapter {
|
|
|
54460
54884
|
*/
|
|
54461
54885
|
this.usePersist = () => {
|
|
54462
54886
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
54463
|
-
this.
|
|
54887
|
+
this._logFactory = () => new LogPersistUtils();
|
|
54888
|
+
this.getInstance.clear();
|
|
54464
54889
|
};
|
|
54465
54890
|
/**
|
|
54466
54891
|
* Switches to in-memory log adapter (default).
|
|
@@ -54468,7 +54893,8 @@ class LogAdapter {
|
|
|
54468
54893
|
*/
|
|
54469
54894
|
this.useMemory = () => {
|
|
54470
54895
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
54471
|
-
this.
|
|
54896
|
+
this._logFactory = () => new LogMemoryUtils();
|
|
54897
|
+
this.getInstance.clear();
|
|
54472
54898
|
};
|
|
54473
54899
|
/**
|
|
54474
54900
|
* Switches to dummy log adapter.
|
|
@@ -54476,7 +54902,8 @@ class LogAdapter {
|
|
|
54476
54902
|
*/
|
|
54477
54903
|
this.useDummy = () => {
|
|
54478
54904
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
54479
|
-
this.
|
|
54905
|
+
this._logFactory = () => new LogDummyUtils();
|
|
54906
|
+
this.getInstance.clear();
|
|
54480
54907
|
};
|
|
54481
54908
|
/**
|
|
54482
54909
|
* Switches to JSONL file log adapter.
|
|
@@ -54486,18 +54913,22 @@ class LogAdapter {
|
|
|
54486
54913
|
* @param fileName - Base file name without extension (default: "log")
|
|
54487
54914
|
* @param dirName - Directory for the JSONL file (default: ./dump/log)
|
|
54488
54915
|
*/
|
|
54489
|
-
this.useJsonl = (fileName = "log.jsonl", dirName
|
|
54916
|
+
this.useJsonl = (fileName = "log.jsonl", dirName) => {
|
|
54490
54917
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_JSONL);
|
|
54491
|
-
this.
|
|
54918
|
+
this._logFactory = () => {
|
|
54919
|
+
const dir = dirName || path.join(process.cwd(), "./dump/log");
|
|
54920
|
+
return new LogJsonlUtils(fileName, dir);
|
|
54921
|
+
};
|
|
54922
|
+
this.getInstance.clear();
|
|
54492
54923
|
};
|
|
54493
54924
|
/**
|
|
54494
|
-
* Clears the
|
|
54925
|
+
* Clears the memoized log instance.
|
|
54495
54926
|
* Call this when process.cwd() changes between strategy iterations
|
|
54496
54927
|
* so a new adapter instance is created with the updated base path.
|
|
54497
54928
|
*/
|
|
54498
54929
|
this.clear = () => {
|
|
54499
54930
|
backtest.loggerService.info(LOG_ADAPTER_METHOD_NAME_CLEAR);
|
|
54500
|
-
this.
|
|
54931
|
+
this.getInstance.clear();
|
|
54501
54932
|
};
|
|
54502
54933
|
}
|
|
54503
54934
|
}
|
|
@@ -58389,15 +58820,23 @@ class StorageDummyLiveUtils {
|
|
|
58389
58820
|
*/
|
|
58390
58821
|
class StorageBacktestAdapter {
|
|
58391
58822
|
constructor() {
|
|
58392
|
-
/**
|
|
58393
|
-
this.
|
|
58823
|
+
/** Factory producing the active storage utils instance */
|
|
58824
|
+
this._signalBacktestFactory = () => new StorageMemoryBacktestUtils();
|
|
58825
|
+
/**
|
|
58826
|
+
* Lazily constructs the storage utils from the registered factory and memoizes
|
|
58827
|
+
* the result via `singleshot`.
|
|
58828
|
+
*
|
|
58829
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
58830
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
58831
|
+
*/
|
|
58832
|
+
this.getInstance = functoolsKit.singleshot(() => this._signalBacktestFactory());
|
|
58394
58833
|
/**
|
|
58395
58834
|
* Handles signal opened event.
|
|
58396
58835
|
* Proxies call to the underlying storage adapter.
|
|
58397
58836
|
* @param tick - The opened signal tick data
|
|
58398
58837
|
*/
|
|
58399
58838
|
this.handleOpened = async (tick) => {
|
|
58400
|
-
return await this.
|
|
58839
|
+
return await this.getInstance().handleOpened(tick);
|
|
58401
58840
|
};
|
|
58402
58841
|
/**
|
|
58403
58842
|
* Handles signal closed event.
|
|
@@ -58405,7 +58844,7 @@ class StorageBacktestAdapter {
|
|
|
58405
58844
|
* @param tick - The closed signal tick data
|
|
58406
58845
|
*/
|
|
58407
58846
|
this.handleClosed = async (tick) => {
|
|
58408
|
-
return await this.
|
|
58847
|
+
return await this.getInstance().handleClosed(tick);
|
|
58409
58848
|
};
|
|
58410
58849
|
/**
|
|
58411
58850
|
* Handles signal scheduled event.
|
|
@@ -58413,7 +58852,7 @@ class StorageBacktestAdapter {
|
|
|
58413
58852
|
* @param tick - The scheduled signal tick data
|
|
58414
58853
|
*/
|
|
58415
58854
|
this.handleScheduled = async (tick) => {
|
|
58416
|
-
return await this.
|
|
58855
|
+
return await this.getInstance().handleScheduled(tick);
|
|
58417
58856
|
};
|
|
58418
58857
|
/**
|
|
58419
58858
|
* Handles signal cancelled event.
|
|
@@ -58421,7 +58860,7 @@ class StorageBacktestAdapter {
|
|
|
58421
58860
|
* @param tick - The cancelled signal tick data
|
|
58422
58861
|
*/
|
|
58423
58862
|
this.handleCancelled = async (tick) => {
|
|
58424
|
-
return await this.
|
|
58863
|
+
return await this.getInstance().handleCancelled(tick);
|
|
58425
58864
|
};
|
|
58426
58865
|
/**
|
|
58427
58866
|
* Finds a signal by its ID.
|
|
@@ -58430,7 +58869,7 @@ class StorageBacktestAdapter {
|
|
|
58430
58869
|
* @returns The signal row or null if not found
|
|
58431
58870
|
*/
|
|
58432
58871
|
this.findById = async (id) => {
|
|
58433
|
-
return await this.
|
|
58872
|
+
return await this.getInstance().findById(id);
|
|
58434
58873
|
};
|
|
58435
58874
|
/**
|
|
58436
58875
|
* Lists all stored signals.
|
|
@@ -58438,13 +58877,13 @@ class StorageBacktestAdapter {
|
|
|
58438
58877
|
* @returns Array of all signal rows
|
|
58439
58878
|
*/
|
|
58440
58879
|
this.list = async () => {
|
|
58441
|
-
return await this.
|
|
58880
|
+
return await this.getInstance().list();
|
|
58442
58881
|
};
|
|
58443
58882
|
this.handleActivePing = async (event) => {
|
|
58444
|
-
return await this.
|
|
58883
|
+
return await this.getInstance().handleActivePing(event);
|
|
58445
58884
|
};
|
|
58446
58885
|
this.handleSchedulePing = async (event) => {
|
|
58447
|
-
return await this.
|
|
58886
|
+
return await this.getInstance().handleSchedulePing(event);
|
|
58448
58887
|
};
|
|
58449
58888
|
/**
|
|
58450
58889
|
* Sets the storage adapter constructor.
|
|
@@ -58454,7 +58893,8 @@ class StorageBacktestAdapter {
|
|
|
58454
58893
|
*/
|
|
58455
58894
|
this.useStorageAdapter = (Ctor) => {
|
|
58456
58895
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
58457
|
-
this.
|
|
58896
|
+
this._signalBacktestFactory = () => Reflect.construct(Ctor, []);
|
|
58897
|
+
this.getInstance.clear();
|
|
58458
58898
|
};
|
|
58459
58899
|
/**
|
|
58460
58900
|
* Switches to dummy storage adapter.
|
|
@@ -58462,7 +58902,8 @@ class StorageBacktestAdapter {
|
|
|
58462
58902
|
*/
|
|
58463
58903
|
this.useDummy = () => {
|
|
58464
58904
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
58465
|
-
this.
|
|
58905
|
+
this._signalBacktestFactory = () => new StorageDummyBacktestUtils();
|
|
58906
|
+
this.getInstance.clear();
|
|
58466
58907
|
};
|
|
58467
58908
|
/**
|
|
58468
58909
|
* Switches to persistent storage adapter (default).
|
|
@@ -58470,7 +58911,8 @@ class StorageBacktestAdapter {
|
|
|
58470
58911
|
*/
|
|
58471
58912
|
this.usePersist = () => {
|
|
58472
58913
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
58473
|
-
this.
|
|
58914
|
+
this._signalBacktestFactory = () => new StoragePersistBacktestUtils();
|
|
58915
|
+
this.getInstance.clear();
|
|
58474
58916
|
};
|
|
58475
58917
|
/**
|
|
58476
58918
|
* Switches to in-memory storage adapter.
|
|
@@ -58478,16 +58920,17 @@ class StorageBacktestAdapter {
|
|
|
58478
58920
|
*/
|
|
58479
58921
|
this.useMemory = () => {
|
|
58480
58922
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
58481
|
-
this.
|
|
58923
|
+
this._signalBacktestFactory = () => new StorageMemoryBacktestUtils();
|
|
58924
|
+
this.getInstance.clear();
|
|
58482
58925
|
};
|
|
58483
58926
|
/**
|
|
58484
|
-
* Clears the
|
|
58927
|
+
* Clears the memoized utils instance.
|
|
58485
58928
|
* Call this when process.cwd() changes between strategy iterations
|
|
58486
58929
|
* so a new instance is created with the updated base path.
|
|
58487
58930
|
*/
|
|
58488
58931
|
this.clear = () => {
|
|
58489
58932
|
backtest.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_CLEAR);
|
|
58490
|
-
this.
|
|
58933
|
+
this.getInstance.clear();
|
|
58491
58934
|
};
|
|
58492
58935
|
}
|
|
58493
58936
|
}
|
|
@@ -58502,15 +58945,23 @@ class StorageBacktestAdapter {
|
|
|
58502
58945
|
*/
|
|
58503
58946
|
class StorageLiveAdapter {
|
|
58504
58947
|
constructor() {
|
|
58505
|
-
/**
|
|
58506
|
-
this.
|
|
58948
|
+
/** Factory producing the active storage utils instance */
|
|
58949
|
+
this._signalLiveFactory = () => new StoragePersistLiveUtils();
|
|
58950
|
+
/**
|
|
58951
|
+
* Lazily constructs the storage utils from the registered factory and memoizes
|
|
58952
|
+
* the result via `singleshot`.
|
|
58953
|
+
*
|
|
58954
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
58955
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
58956
|
+
*/
|
|
58957
|
+
this.getInstance = functoolsKit.singleshot(() => this._signalLiveFactory());
|
|
58507
58958
|
/**
|
|
58508
58959
|
* Handles signal opened event.
|
|
58509
58960
|
* Proxies call to the underlying storage adapter.
|
|
58510
58961
|
* @param tick - The opened signal tick data
|
|
58511
58962
|
*/
|
|
58512
58963
|
this.handleOpened = async (tick) => {
|
|
58513
|
-
return await this.
|
|
58964
|
+
return await this.getInstance().handleOpened(tick);
|
|
58514
58965
|
};
|
|
58515
58966
|
/**
|
|
58516
58967
|
* Handles signal closed event.
|
|
@@ -58518,7 +58969,7 @@ class StorageLiveAdapter {
|
|
|
58518
58969
|
* @param tick - The closed signal tick data
|
|
58519
58970
|
*/
|
|
58520
58971
|
this.handleClosed = async (tick) => {
|
|
58521
|
-
return await this.
|
|
58972
|
+
return await this.getInstance().handleClosed(tick);
|
|
58522
58973
|
};
|
|
58523
58974
|
/**
|
|
58524
58975
|
* Handles signal scheduled event.
|
|
@@ -58526,7 +58977,7 @@ class StorageLiveAdapter {
|
|
|
58526
58977
|
* @param tick - The scheduled signal tick data
|
|
58527
58978
|
*/
|
|
58528
58979
|
this.handleScheduled = async (tick) => {
|
|
58529
|
-
return await this.
|
|
58980
|
+
return await this.getInstance().handleScheduled(tick);
|
|
58530
58981
|
};
|
|
58531
58982
|
/**
|
|
58532
58983
|
* Handles signal cancelled event.
|
|
@@ -58534,7 +58985,7 @@ class StorageLiveAdapter {
|
|
|
58534
58985
|
* @param tick - The cancelled signal tick data
|
|
58535
58986
|
*/
|
|
58536
58987
|
this.handleCancelled = async (tick) => {
|
|
58537
|
-
return await this.
|
|
58988
|
+
return await this.getInstance().handleCancelled(tick);
|
|
58538
58989
|
};
|
|
58539
58990
|
/**
|
|
58540
58991
|
* Finds a signal by its ID.
|
|
@@ -58543,7 +58994,7 @@ class StorageLiveAdapter {
|
|
|
58543
58994
|
* @returns The signal row or null if not found
|
|
58544
58995
|
*/
|
|
58545
58996
|
this.findById = async (id) => {
|
|
58546
|
-
return await this.
|
|
58997
|
+
return await this.getInstance().findById(id);
|
|
58547
58998
|
};
|
|
58548
58999
|
/**
|
|
58549
59000
|
* Lists all stored signals.
|
|
@@ -58551,13 +59002,13 @@ class StorageLiveAdapter {
|
|
|
58551
59002
|
* @returns Array of all signal rows
|
|
58552
59003
|
*/
|
|
58553
59004
|
this.list = async () => {
|
|
58554
|
-
return await this.
|
|
59005
|
+
return await this.getInstance().list();
|
|
58555
59006
|
};
|
|
58556
59007
|
this.handleActivePing = async (event) => {
|
|
58557
|
-
return await this.
|
|
59008
|
+
return await this.getInstance().handleActivePing(event);
|
|
58558
59009
|
};
|
|
58559
59010
|
this.handleSchedulePing = async (event) => {
|
|
58560
|
-
return await this.
|
|
59011
|
+
return await this.getInstance().handleSchedulePing(event);
|
|
58561
59012
|
};
|
|
58562
59013
|
/**
|
|
58563
59014
|
* Sets the storage adapter constructor.
|
|
@@ -58567,7 +59018,8 @@ class StorageLiveAdapter {
|
|
|
58567
59018
|
*/
|
|
58568
59019
|
this.useStorageAdapter = (Ctor) => {
|
|
58569
59020
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
58570
|
-
this.
|
|
59021
|
+
this._signalLiveFactory = () => Reflect.construct(Ctor, []);
|
|
59022
|
+
this.getInstance.clear();
|
|
58571
59023
|
};
|
|
58572
59024
|
/**
|
|
58573
59025
|
* Switches to dummy storage adapter.
|
|
@@ -58575,7 +59027,8 @@ class StorageLiveAdapter {
|
|
|
58575
59027
|
*/
|
|
58576
59028
|
this.useDummy = () => {
|
|
58577
59029
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
58578
|
-
this.
|
|
59030
|
+
this._signalLiveFactory = () => new StorageDummyLiveUtils();
|
|
59031
|
+
this.getInstance.clear();
|
|
58579
59032
|
};
|
|
58580
59033
|
/**
|
|
58581
59034
|
* Switches to persistent storage adapter (default).
|
|
@@ -58583,7 +59036,8 @@ class StorageLiveAdapter {
|
|
|
58583
59036
|
*/
|
|
58584
59037
|
this.usePersist = () => {
|
|
58585
59038
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
58586
|
-
this.
|
|
59039
|
+
this._signalLiveFactory = () => new StoragePersistLiveUtils();
|
|
59040
|
+
this.getInstance.clear();
|
|
58587
59041
|
};
|
|
58588
59042
|
/**
|
|
58589
59043
|
* Switches to in-memory storage adapter.
|
|
@@ -58591,16 +59045,17 @@ class StorageLiveAdapter {
|
|
|
58591
59045
|
*/
|
|
58592
59046
|
this.useMemory = () => {
|
|
58593
59047
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
58594
|
-
this.
|
|
59048
|
+
this._signalLiveFactory = () => new StorageMemoryLiveUtils();
|
|
59049
|
+
this.getInstance.clear();
|
|
58595
59050
|
};
|
|
58596
59051
|
/**
|
|
58597
|
-
* Clears the
|
|
59052
|
+
* Clears the memoized utils instance.
|
|
58598
59053
|
* Call this when process.cwd() changes between strategy iterations
|
|
58599
59054
|
* so a new instance is created with the updated base path.
|
|
58600
59055
|
*/
|
|
58601
59056
|
this.clear = () => {
|
|
58602
59057
|
backtest.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_CLEAR);
|
|
58603
|
-
this.
|
|
59058
|
+
this.getInstance.clear();
|
|
58604
59059
|
};
|
|
58605
59060
|
}
|
|
58606
59061
|
}
|
|
@@ -60716,18 +61171,26 @@ class NotificationPersistLiveUtils {
|
|
|
60716
61171
|
*/
|
|
60717
61172
|
class NotificationBacktestAdapter {
|
|
60718
61173
|
constructor() {
|
|
60719
|
-
/**
|
|
60720
|
-
this.
|
|
61174
|
+
/** Factory producing the active notification utils instance */
|
|
61175
|
+
this._notificationBacktestFactory = () => new NotificationMemoryBacktestUtils();
|
|
61176
|
+
/**
|
|
61177
|
+
* Lazily constructs the notification utils from the registered factory and
|
|
61178
|
+
* memoizes the result via `singleshot`.
|
|
61179
|
+
*
|
|
61180
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
61181
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
61182
|
+
*/
|
|
61183
|
+
this.getInstance = functoolsKit.singleshot(() => this._notificationBacktestFactory());
|
|
60721
61184
|
/**
|
|
60722
61185
|
* Handles signal events.
|
|
60723
61186
|
* Proxies call to the underlying notification adapter.
|
|
60724
61187
|
* @param data - The strategy tick result data
|
|
60725
61188
|
*/
|
|
60726
61189
|
this.handleSignal = async (data) => {
|
|
60727
|
-
return await this.
|
|
61190
|
+
return await this.getInstance().handleSignal(data);
|
|
60728
61191
|
};
|
|
60729
61192
|
this.handleSignalNotify = async (data) => {
|
|
60730
|
-
return await this.
|
|
61193
|
+
return await this.getInstance().handleSignalNotify(data);
|
|
60731
61194
|
};
|
|
60732
61195
|
/**
|
|
60733
61196
|
* Handles partial profit availability event.
|
|
@@ -60735,7 +61198,7 @@ class NotificationBacktestAdapter {
|
|
|
60735
61198
|
* @param data - The partial profit contract data
|
|
60736
61199
|
*/
|
|
60737
61200
|
this.handlePartialProfit = async (data) => {
|
|
60738
|
-
return await this.
|
|
61201
|
+
return await this.getInstance().handlePartialProfit(data);
|
|
60739
61202
|
};
|
|
60740
61203
|
/**
|
|
60741
61204
|
* Handles partial loss availability event.
|
|
@@ -60743,7 +61206,7 @@ class NotificationBacktestAdapter {
|
|
|
60743
61206
|
* @param data - The partial loss contract data
|
|
60744
61207
|
*/
|
|
60745
61208
|
this.handlePartialLoss = async (data) => {
|
|
60746
|
-
return await this.
|
|
61209
|
+
return await this.getInstance().handlePartialLoss(data);
|
|
60747
61210
|
};
|
|
60748
61211
|
/**
|
|
60749
61212
|
* Handles breakeven availability event.
|
|
@@ -60751,7 +61214,7 @@ class NotificationBacktestAdapter {
|
|
|
60751
61214
|
* @param data - The breakeven contract data
|
|
60752
61215
|
*/
|
|
60753
61216
|
this.handleBreakeven = async (data) => {
|
|
60754
|
-
return await this.
|
|
61217
|
+
return await this.getInstance().handleBreakeven(data);
|
|
60755
61218
|
};
|
|
60756
61219
|
/**
|
|
60757
61220
|
* Handles strategy commit events.
|
|
@@ -60759,7 +61222,7 @@ class NotificationBacktestAdapter {
|
|
|
60759
61222
|
* @param data - The strategy commit contract data
|
|
60760
61223
|
*/
|
|
60761
61224
|
this.handleStrategyCommit = async (data) => {
|
|
60762
|
-
return await this.
|
|
61225
|
+
return await this.getInstance().handleStrategyCommit(data);
|
|
60763
61226
|
};
|
|
60764
61227
|
/**
|
|
60765
61228
|
* Handles signal sync events (signal-open, signal-close).
|
|
@@ -60767,7 +61230,7 @@ class NotificationBacktestAdapter {
|
|
|
60767
61230
|
* @param data - The signal sync contract data
|
|
60768
61231
|
*/
|
|
60769
61232
|
this.handleSync = functoolsKit.trycatch(async (data) => {
|
|
60770
|
-
return await this.
|
|
61233
|
+
return await this.getInstance().handleSync(data);
|
|
60771
61234
|
}, {
|
|
60772
61235
|
defaultValue: null,
|
|
60773
61236
|
});
|
|
@@ -60777,7 +61240,7 @@ class NotificationBacktestAdapter {
|
|
|
60777
61240
|
* @param data - The risk contract data
|
|
60778
61241
|
*/
|
|
60779
61242
|
this.handleRisk = async (data) => {
|
|
60780
|
-
return await this.
|
|
61243
|
+
return await this.getInstance().handleRisk(data);
|
|
60781
61244
|
};
|
|
60782
61245
|
/**
|
|
60783
61246
|
* Handles error event.
|
|
@@ -60785,7 +61248,7 @@ class NotificationBacktestAdapter {
|
|
|
60785
61248
|
* @param error - The error object
|
|
60786
61249
|
*/
|
|
60787
61250
|
this.handleError = async (error) => {
|
|
60788
|
-
return await this.
|
|
61251
|
+
return await this.getInstance().handleError(error);
|
|
60789
61252
|
};
|
|
60790
61253
|
/**
|
|
60791
61254
|
* Handles critical error event.
|
|
@@ -60793,7 +61256,7 @@ class NotificationBacktestAdapter {
|
|
|
60793
61256
|
* @param error - The error object
|
|
60794
61257
|
*/
|
|
60795
61258
|
this.handleCriticalError = async (error) => {
|
|
60796
|
-
return await this.
|
|
61259
|
+
return await this.getInstance().handleCriticalError(error);
|
|
60797
61260
|
};
|
|
60798
61261
|
/**
|
|
60799
61262
|
* Handles validation error event.
|
|
@@ -60801,7 +61264,7 @@ class NotificationBacktestAdapter {
|
|
|
60801
61264
|
* @param error - The error object
|
|
60802
61265
|
*/
|
|
60803
61266
|
this.handleValidationError = async (error) => {
|
|
60804
|
-
return await this.
|
|
61267
|
+
return await this.getInstance().handleValidationError(error);
|
|
60805
61268
|
};
|
|
60806
61269
|
/**
|
|
60807
61270
|
* Gets all stored notifications.
|
|
@@ -60809,14 +61272,14 @@ class NotificationBacktestAdapter {
|
|
|
60809
61272
|
* @returns Array of all notification models
|
|
60810
61273
|
*/
|
|
60811
61274
|
this.getData = async () => {
|
|
60812
|
-
return await this.
|
|
61275
|
+
return await this.getInstance().getData();
|
|
60813
61276
|
};
|
|
60814
61277
|
/**
|
|
60815
61278
|
* Clears all stored notifications.
|
|
60816
61279
|
* Proxies call to the underlying notification adapter.
|
|
60817
61280
|
*/
|
|
60818
61281
|
this.dispose = async () => {
|
|
60819
|
-
return await this.
|
|
61282
|
+
return await this.getInstance().dispose();
|
|
60820
61283
|
};
|
|
60821
61284
|
/**
|
|
60822
61285
|
* Sets the notification adapter constructor.
|
|
@@ -60826,7 +61289,8 @@ class NotificationBacktestAdapter {
|
|
|
60826
61289
|
*/
|
|
60827
61290
|
this.useNotificationAdapter = (Ctor) => {
|
|
60828
61291
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
60829
|
-
this.
|
|
61292
|
+
this._notificationBacktestFactory = () => Reflect.construct(Ctor, []);
|
|
61293
|
+
this.getInstance.clear();
|
|
60830
61294
|
};
|
|
60831
61295
|
/**
|
|
60832
61296
|
* Switches to dummy notification adapter.
|
|
@@ -60834,7 +61298,8 @@ class NotificationBacktestAdapter {
|
|
|
60834
61298
|
*/
|
|
60835
61299
|
this.useDummy = () => {
|
|
60836
61300
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
60837
|
-
this.
|
|
61301
|
+
this._notificationBacktestFactory = () => new NotificationDummyBacktestUtils();
|
|
61302
|
+
this.getInstance.clear();
|
|
60838
61303
|
};
|
|
60839
61304
|
/**
|
|
60840
61305
|
* Switches to in-memory notification adapter (default).
|
|
@@ -60842,7 +61307,8 @@ class NotificationBacktestAdapter {
|
|
|
60842
61307
|
*/
|
|
60843
61308
|
this.useMemory = () => {
|
|
60844
61309
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
60845
|
-
this.
|
|
61310
|
+
this._notificationBacktestFactory = () => new NotificationMemoryBacktestUtils();
|
|
61311
|
+
this.getInstance.clear();
|
|
60846
61312
|
};
|
|
60847
61313
|
/**
|
|
60848
61314
|
* Switches to persistent notification adapter.
|
|
@@ -60850,16 +61316,17 @@ class NotificationBacktestAdapter {
|
|
|
60850
61316
|
*/
|
|
60851
61317
|
this.usePersist = () => {
|
|
60852
61318
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
60853
|
-
this.
|
|
61319
|
+
this._notificationBacktestFactory = () => new NotificationPersistBacktestUtils();
|
|
61320
|
+
this.getInstance.clear();
|
|
60854
61321
|
};
|
|
60855
61322
|
/**
|
|
60856
|
-
*
|
|
61323
|
+
* Clears the memoized utils instance.
|
|
60857
61324
|
* Call this when process.cwd() changes between strategy iterations
|
|
60858
61325
|
* so a new instance is created with the updated base path.
|
|
60859
61326
|
*/
|
|
60860
61327
|
this.clear = () => {
|
|
60861
61328
|
backtest.loggerService.info(NOTIFICATION_BACKTEST_ADAPTER_METHOD_NAME_CLEAR);
|
|
60862
|
-
this.
|
|
61329
|
+
this.getInstance.clear();
|
|
60863
61330
|
};
|
|
60864
61331
|
}
|
|
60865
61332
|
}
|
|
@@ -60874,18 +61341,26 @@ class NotificationBacktestAdapter {
|
|
|
60874
61341
|
*/
|
|
60875
61342
|
class NotificationLiveAdapter {
|
|
60876
61343
|
constructor() {
|
|
60877
|
-
/**
|
|
60878
|
-
this.
|
|
61344
|
+
/** Factory producing the active notification utils instance */
|
|
61345
|
+
this._notificationLiveFactory = () => new NotificationMemoryLiveUtils();
|
|
61346
|
+
/**
|
|
61347
|
+
* Lazily constructs the notification utils from the registered factory and
|
|
61348
|
+
* memoizes the result via `singleshot`.
|
|
61349
|
+
*
|
|
61350
|
+
* The instance is built on the first call and cached for all subsequent calls.
|
|
61351
|
+
* Reset via `clear()` so the next call rebuilds from the current factory.
|
|
61352
|
+
*/
|
|
61353
|
+
this.getInstance = functoolsKit.singleshot(() => this._notificationLiveFactory());
|
|
60879
61354
|
/**
|
|
60880
61355
|
* Handles signal events.
|
|
60881
61356
|
* Proxies call to the underlying notification adapter.
|
|
60882
61357
|
* @param data - The strategy tick result data
|
|
60883
61358
|
*/
|
|
60884
61359
|
this.handleSignal = async (data) => {
|
|
60885
|
-
return await this.
|
|
61360
|
+
return await this.getInstance().handleSignal(data);
|
|
60886
61361
|
};
|
|
60887
61362
|
this.handleSignalNotify = async (data) => {
|
|
60888
|
-
return await this.
|
|
61363
|
+
return await this.getInstance().handleSignalNotify(data);
|
|
60889
61364
|
};
|
|
60890
61365
|
/**
|
|
60891
61366
|
* Handles partial profit availability event.
|
|
@@ -60893,7 +61368,7 @@ class NotificationLiveAdapter {
|
|
|
60893
61368
|
* @param data - The partial profit contract data
|
|
60894
61369
|
*/
|
|
60895
61370
|
this.handlePartialProfit = async (data) => {
|
|
60896
|
-
return await this.
|
|
61371
|
+
return await this.getInstance().handlePartialProfit(data);
|
|
60897
61372
|
};
|
|
60898
61373
|
/**
|
|
60899
61374
|
* Handles partial loss availability event.
|
|
@@ -60901,7 +61376,7 @@ class NotificationLiveAdapter {
|
|
|
60901
61376
|
* @param data - The partial loss contract data
|
|
60902
61377
|
*/
|
|
60903
61378
|
this.handlePartialLoss = async (data) => {
|
|
60904
|
-
return await this.
|
|
61379
|
+
return await this.getInstance().handlePartialLoss(data);
|
|
60905
61380
|
};
|
|
60906
61381
|
/**
|
|
60907
61382
|
* Handles breakeven availability event.
|
|
@@ -60909,7 +61384,7 @@ class NotificationLiveAdapter {
|
|
|
60909
61384
|
* @param data - The breakeven contract data
|
|
60910
61385
|
*/
|
|
60911
61386
|
this.handleBreakeven = async (data) => {
|
|
60912
|
-
return await this.
|
|
61387
|
+
return await this.getInstance().handleBreakeven(data);
|
|
60913
61388
|
};
|
|
60914
61389
|
/**
|
|
60915
61390
|
* Handles strategy commit events.
|
|
@@ -60917,7 +61392,7 @@ class NotificationLiveAdapter {
|
|
|
60917
61392
|
* @param data - The strategy commit contract data
|
|
60918
61393
|
*/
|
|
60919
61394
|
this.handleStrategyCommit = async (data) => {
|
|
60920
|
-
return await this.
|
|
61395
|
+
return await this.getInstance().handleStrategyCommit(data);
|
|
60921
61396
|
};
|
|
60922
61397
|
/**
|
|
60923
61398
|
* Handles signal sync events (signal-open, signal-close).
|
|
@@ -60925,7 +61400,7 @@ class NotificationLiveAdapter {
|
|
|
60925
61400
|
* @param data - The signal sync contract data
|
|
60926
61401
|
*/
|
|
60927
61402
|
this.handleSync = functoolsKit.trycatch(async (data) => {
|
|
60928
|
-
return await this.
|
|
61403
|
+
return await this.getInstance().handleSync(data);
|
|
60929
61404
|
}, {
|
|
60930
61405
|
defaultValue: null,
|
|
60931
61406
|
});
|
|
@@ -60935,7 +61410,7 @@ class NotificationLiveAdapter {
|
|
|
60935
61410
|
* @param data - The risk contract data
|
|
60936
61411
|
*/
|
|
60937
61412
|
this.handleRisk = async (data) => {
|
|
60938
|
-
return await this.
|
|
61413
|
+
return await this.getInstance().handleRisk(data);
|
|
60939
61414
|
};
|
|
60940
61415
|
/**
|
|
60941
61416
|
* Handles error event.
|
|
@@ -60943,7 +61418,7 @@ class NotificationLiveAdapter {
|
|
|
60943
61418
|
* @param error - The error object
|
|
60944
61419
|
*/
|
|
60945
61420
|
this.handleError = async (error) => {
|
|
60946
|
-
return await this.
|
|
61421
|
+
return await this.getInstance().handleError(error);
|
|
60947
61422
|
};
|
|
60948
61423
|
/**
|
|
60949
61424
|
* Handles critical error event.
|
|
@@ -60951,7 +61426,7 @@ class NotificationLiveAdapter {
|
|
|
60951
61426
|
* @param error - The error object
|
|
60952
61427
|
*/
|
|
60953
61428
|
this.handleCriticalError = async (error) => {
|
|
60954
|
-
return await this.
|
|
61429
|
+
return await this.getInstance().handleCriticalError(error);
|
|
60955
61430
|
};
|
|
60956
61431
|
/**
|
|
60957
61432
|
* Handles validation error event.
|
|
@@ -60959,7 +61434,7 @@ class NotificationLiveAdapter {
|
|
|
60959
61434
|
* @param error - The error object
|
|
60960
61435
|
*/
|
|
60961
61436
|
this.handleValidationError = async (error) => {
|
|
60962
|
-
return await this.
|
|
61437
|
+
return await this.getInstance().handleValidationError(error);
|
|
60963
61438
|
};
|
|
60964
61439
|
/**
|
|
60965
61440
|
* Gets all stored notifications.
|
|
@@ -60967,14 +61442,14 @@ class NotificationLiveAdapter {
|
|
|
60967
61442
|
* @returns Array of all notification models
|
|
60968
61443
|
*/
|
|
60969
61444
|
this.getData = async () => {
|
|
60970
|
-
return await this.
|
|
61445
|
+
return await this.getInstance().getData();
|
|
60971
61446
|
};
|
|
60972
61447
|
/**
|
|
60973
61448
|
* Clears all stored notifications.
|
|
60974
61449
|
* Proxies call to the underlying notification adapter.
|
|
60975
61450
|
*/
|
|
60976
61451
|
this.dispose = async () => {
|
|
60977
|
-
return await this.
|
|
61452
|
+
return await this.getInstance().dispose();
|
|
60978
61453
|
};
|
|
60979
61454
|
/**
|
|
60980
61455
|
* Sets the notification adapter constructor.
|
|
@@ -60984,7 +61459,8 @@ class NotificationLiveAdapter {
|
|
|
60984
61459
|
*/
|
|
60985
61460
|
this.useNotificationAdapter = (Ctor) => {
|
|
60986
61461
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
60987
|
-
this.
|
|
61462
|
+
this._notificationLiveFactory = () => Reflect.construct(Ctor, []);
|
|
61463
|
+
this.getInstance.clear();
|
|
60988
61464
|
};
|
|
60989
61465
|
/**
|
|
60990
61466
|
* Switches to dummy notification adapter.
|
|
@@ -60992,7 +61468,8 @@ class NotificationLiveAdapter {
|
|
|
60992
61468
|
*/
|
|
60993
61469
|
this.useDummy = () => {
|
|
60994
61470
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
60995
|
-
this.
|
|
61471
|
+
this._notificationLiveFactory = () => new NotificationDummyLiveUtils();
|
|
61472
|
+
this.getInstance.clear();
|
|
60996
61473
|
};
|
|
60997
61474
|
/**
|
|
60998
61475
|
* Switches to in-memory notification adapter (default).
|
|
@@ -61000,7 +61477,8 @@ class NotificationLiveAdapter {
|
|
|
61000
61477
|
*/
|
|
61001
61478
|
this.useMemory = () => {
|
|
61002
61479
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
61003
|
-
this.
|
|
61480
|
+
this._notificationLiveFactory = () => new NotificationMemoryLiveUtils();
|
|
61481
|
+
this.getInstance.clear();
|
|
61004
61482
|
};
|
|
61005
61483
|
/**
|
|
61006
61484
|
* Switches to persistent notification adapter.
|
|
@@ -61008,16 +61486,17 @@ class NotificationLiveAdapter {
|
|
|
61008
61486
|
*/
|
|
61009
61487
|
this.usePersist = () => {
|
|
61010
61488
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
61011
|
-
this.
|
|
61489
|
+
this._notificationLiveFactory = () => new NotificationPersistLiveUtils();
|
|
61490
|
+
this.getInstance.clear();
|
|
61012
61491
|
};
|
|
61013
61492
|
/**
|
|
61014
|
-
*
|
|
61493
|
+
* Clears the memoized utils instance.
|
|
61015
61494
|
* Call this when process.cwd() changes between strategy iterations
|
|
61016
61495
|
* so a new instance is created with the updated base path.
|
|
61017
61496
|
*/
|
|
61018
61497
|
this.clear = () => {
|
|
61019
61498
|
backtest.loggerService.info(NOTIFICATION_LIVE_ADAPTER_METHOD_NAME_CLEAR);
|
|
61020
|
-
this.
|
|
61499
|
+
this.getInstance.clear();
|
|
61021
61500
|
};
|
|
61022
61501
|
}
|
|
61023
61502
|
}
|
|
@@ -63633,6 +64112,7 @@ exports.HighestProfit = HighestProfit;
|
|
|
63633
64112
|
exports.Interval = Interval;
|
|
63634
64113
|
exports.Live = Live;
|
|
63635
64114
|
exports.Log = Log;
|
|
64115
|
+
exports.Lookup = Lookup;
|
|
63636
64116
|
exports.Markdown = Markdown;
|
|
63637
64117
|
exports.MarkdownFileBase = MarkdownFileBase;
|
|
63638
64118
|
exports.MarkdownFolderBase = MarkdownFolderBase;
|
|
@@ -63714,6 +64194,7 @@ exports.addSizingSchema = addSizingSchema;
|
|
|
63714
64194
|
exports.addStrategySchema = addStrategySchema;
|
|
63715
64195
|
exports.addWalkerSchema = addWalkerSchema;
|
|
63716
64196
|
exports.alignToInterval = alignToInterval;
|
|
64197
|
+
exports.cacheCandles = cacheCandles;
|
|
63717
64198
|
exports.checkCandles = checkCandles;
|
|
63718
64199
|
exports.commitActivateScheduled = commitActivateScheduled;
|
|
63719
64200
|
exports.commitAverageBuy = commitAverageBuy;
|