backtest-kit 9.8.1 → 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 +477 -130
- package/build/index.mjs +476 -131
- package/package.json +86 -86
- package/types.d.ts +123 -3
package/build/index.mjs
CHANGED
|
@@ -554,6 +554,22 @@ const GLOBAL_CONFIG = {
|
|
|
554
554
|
* Default: true (mutex locking enabled for candle fetching)
|
|
555
555
|
*/
|
|
556
556
|
CC_ENABLE_CANDLE_FETCH_MUTEX: true,
|
|
557
|
+
/**
|
|
558
|
+
* Enables cooperative interleaving of concurrently running backtests after each candle fetch.
|
|
559
|
+
*
|
|
560
|
+
* Mechanism (implemented in `Candle.spinLock`):
|
|
561
|
+
* - After `getNextCandles` resolves, the current backtest awaits
|
|
562
|
+
* `Promise.race([_spin.toPromise(), sleep(50)])`, where `_spin` is emitted whenever
|
|
563
|
+
* another caller acquires the candle-fetch mutex.
|
|
564
|
+
* - This hands the event loop to a peer backtest waiting on the same mutex, so multiple
|
|
565
|
+
* parallel `Backtest.run` / `Walker` workloads progress in round-robin fashion instead
|
|
566
|
+
* of one monopolizing the event loop until completion.
|
|
567
|
+
* - The spin is skipped entirely when `Lookup.isParallel` is `false` (single active workload —
|
|
568
|
+
* no peer to yield to) or when `CC_ENABLE_CANDLE_FETCH_MUTEX` is disabled.
|
|
569
|
+
*
|
|
570
|
+
* Default: true (parallel backtests are interleaved on each candle fetch boundary)
|
|
571
|
+
*/
|
|
572
|
+
CC_ENABLE_BACKTEST_PARALLEL_SPIN: true,
|
|
557
573
|
/**
|
|
558
574
|
* Enables DCA (Dollar-Cost Averaging) logic even if antirecord is not broken.
|
|
559
575
|
* Allows to commitAverageBuy if currentPrice is not the lowest price since entry, but still lower than priceOpen.
|
|
@@ -914,7 +930,7 @@ async function writeFileAtomic(file, data, options = {}) {
|
|
|
914
930
|
|
|
915
931
|
var _a$3;
|
|
916
932
|
/** Logger service injected as DI singleton */
|
|
917
|
-
const LOGGER_SERVICE$
|
|
933
|
+
const LOGGER_SERVICE$8 = new LoggerService();
|
|
918
934
|
/** Symbol key for the singleshot waitForInit function on PersistBase instances. */
|
|
919
935
|
const BASE_WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
|
|
920
936
|
// Calculate step in milliseconds for candle close time validation
|
|
@@ -1037,7 +1053,7 @@ const BASE_WAIT_FOR_INIT_FN_METHOD_NAME = "PersistBase.waitForInitFn";
|
|
|
1037
1053
|
const BASE_UNLINK_RETRY_COUNT = 5;
|
|
1038
1054
|
const BASE_UNLINK_RETRY_DELAY = 1000;
|
|
1039
1055
|
const BASE_WAIT_FOR_INIT_FN = async (self) => {
|
|
1040
|
-
LOGGER_SERVICE$
|
|
1056
|
+
LOGGER_SERVICE$8.debug(BASE_WAIT_FOR_INIT_FN_METHOD_NAME, {
|
|
1041
1057
|
entityName: self.entityName,
|
|
1042
1058
|
directory: self._directory,
|
|
1043
1059
|
});
|
|
@@ -1095,7 +1111,7 @@ class PersistBase {
|
|
|
1095
1111
|
this.entityName = entityName;
|
|
1096
1112
|
this.baseDir = baseDir;
|
|
1097
1113
|
this[_a$3] = singleshot(async () => await BASE_WAIT_FOR_INIT_FN(this));
|
|
1098
|
-
LOGGER_SERVICE$
|
|
1114
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_CTOR, {
|
|
1099
1115
|
entityName: this.entityName,
|
|
1100
1116
|
baseDir,
|
|
1101
1117
|
});
|
|
@@ -1111,14 +1127,14 @@ class PersistBase {
|
|
|
1111
1127
|
return join(this.baseDir, this.entityName, `${entityId}.json`);
|
|
1112
1128
|
}
|
|
1113
1129
|
async waitForInit(initial) {
|
|
1114
|
-
LOGGER_SERVICE$
|
|
1130
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_WAIT_FOR_INIT, {
|
|
1115
1131
|
entityName: this.entityName,
|
|
1116
1132
|
initial,
|
|
1117
1133
|
});
|
|
1118
1134
|
await this[BASE_WAIT_FOR_INIT_SYMBOL]();
|
|
1119
1135
|
}
|
|
1120
1136
|
async readValue(entityId) {
|
|
1121
|
-
LOGGER_SERVICE$
|
|
1137
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_READ_VALUE, {
|
|
1122
1138
|
entityName: this.entityName,
|
|
1123
1139
|
entityId,
|
|
1124
1140
|
});
|
|
@@ -1135,7 +1151,7 @@ class PersistBase {
|
|
|
1135
1151
|
}
|
|
1136
1152
|
}
|
|
1137
1153
|
async hasValue(entityId) {
|
|
1138
|
-
LOGGER_SERVICE$
|
|
1154
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_HAS_VALUE, {
|
|
1139
1155
|
entityName: this.entityName,
|
|
1140
1156
|
entityId,
|
|
1141
1157
|
});
|
|
@@ -1152,7 +1168,7 @@ class PersistBase {
|
|
|
1152
1168
|
}
|
|
1153
1169
|
}
|
|
1154
1170
|
async writeValue(entityId, entity) {
|
|
1155
|
-
LOGGER_SERVICE$
|
|
1171
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_WRITE_VALUE, {
|
|
1156
1172
|
entityName: this.entityName,
|
|
1157
1173
|
entityId,
|
|
1158
1174
|
});
|
|
@@ -1174,7 +1190,7 @@ class PersistBase {
|
|
|
1174
1190
|
* @throws Error if reading fails
|
|
1175
1191
|
*/
|
|
1176
1192
|
async *keys() {
|
|
1177
|
-
LOGGER_SERVICE$
|
|
1193
|
+
LOGGER_SERVICE$8.debug(PERSIST_BASE_METHOD_NAME_KEYS, {
|
|
1178
1194
|
entityName: this.entityName,
|
|
1179
1195
|
});
|
|
1180
1196
|
try {
|
|
@@ -1319,7 +1335,7 @@ class PersistSignalUtils {
|
|
|
1319
1335
|
* @returns Promise resolving to signal or null if none persisted
|
|
1320
1336
|
*/
|
|
1321
1337
|
this.readSignalData = async (symbol, strategyName, exchangeName) => {
|
|
1322
|
-
LOGGER_SERVICE$
|
|
1338
|
+
LOGGER_SERVICE$8.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_READ_DATA);
|
|
1323
1339
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1324
1340
|
const isInitial = !this.getStorage.has(key);
|
|
1325
1341
|
const instance = this.getStorage(symbol, strategyName, exchangeName);
|
|
@@ -1337,7 +1353,7 @@ class PersistSignalUtils {
|
|
|
1337
1353
|
* @returns Promise that resolves when write is complete
|
|
1338
1354
|
*/
|
|
1339
1355
|
this.writeSignalData = async (signalRow, symbol, strategyName, exchangeName) => {
|
|
1340
|
-
LOGGER_SERVICE$
|
|
1356
|
+
LOGGER_SERVICE$8.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1341
1357
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1342
1358
|
const isInitial = !this.getStorage.has(key);
|
|
1343
1359
|
const instance = this.getStorage(symbol, strategyName, exchangeName);
|
|
@@ -1352,7 +1368,7 @@ class PersistSignalUtils {
|
|
|
1352
1368
|
* @param Ctor - Custom IPersistSignalInstance constructor
|
|
1353
1369
|
*/
|
|
1354
1370
|
usePersistSignalAdapter(Ctor) {
|
|
1355
|
-
LOGGER_SERVICE$
|
|
1371
|
+
LOGGER_SERVICE$8.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_PERSIST_SIGNAL_ADAPTER);
|
|
1356
1372
|
this.PersistSignalInstanceCtor = Ctor;
|
|
1357
1373
|
this.getStorage.clear();
|
|
1358
1374
|
}
|
|
@@ -1361,21 +1377,21 @@ class PersistSignalUtils {
|
|
|
1361
1377
|
* Call when process.cwd() changes between strategy iterations.
|
|
1362
1378
|
*/
|
|
1363
1379
|
clear() {
|
|
1364
|
-
LOGGER_SERVICE$
|
|
1380
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_CLEAR);
|
|
1365
1381
|
this.getStorage.clear();
|
|
1366
1382
|
}
|
|
1367
1383
|
/**
|
|
1368
1384
|
* Switches to the default file-based PersistSignalInstance.
|
|
1369
1385
|
*/
|
|
1370
1386
|
useJson() {
|
|
1371
|
-
LOGGER_SERVICE$
|
|
1387
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_JSON);
|
|
1372
1388
|
this.usePersistSignalAdapter(PersistSignalInstance);
|
|
1373
1389
|
}
|
|
1374
1390
|
/**
|
|
1375
1391
|
* Switches to PersistSignalDummyInstance (all operations are no-ops).
|
|
1376
1392
|
*/
|
|
1377
1393
|
useDummy() {
|
|
1378
|
-
LOGGER_SERVICE$
|
|
1394
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1379
1395
|
this.usePersistSignalAdapter(PersistSignalDummyInstance);
|
|
1380
1396
|
}
|
|
1381
1397
|
}
|
|
@@ -1515,7 +1531,7 @@ class PersistRiskUtils {
|
|
|
1515
1531
|
* @returns Promise resolving to position entries (empty array if none)
|
|
1516
1532
|
*/
|
|
1517
1533
|
this.readPositionData = async (riskName, exchangeName, when) => {
|
|
1518
|
-
LOGGER_SERVICE$
|
|
1534
|
+
LOGGER_SERVICE$8.info(PERSIST_RISK_UTILS_METHOD_NAME_READ_DATA);
|
|
1519
1535
|
const key = `${riskName}:${exchangeName}`;
|
|
1520
1536
|
const isInitial = !this.getRiskStorage.has(key);
|
|
1521
1537
|
const instance = this.getRiskStorage(riskName, exchangeName);
|
|
@@ -1533,7 +1549,7 @@ class PersistRiskUtils {
|
|
|
1533
1549
|
* @returns Promise that resolves when write is complete
|
|
1534
1550
|
*/
|
|
1535
1551
|
this.writePositionData = async (riskRow, riskName, exchangeName, when) => {
|
|
1536
|
-
LOGGER_SERVICE$
|
|
1552
|
+
LOGGER_SERVICE$8.info(PERSIST_RISK_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1537
1553
|
const key = `${riskName}:${exchangeName}`;
|
|
1538
1554
|
const isInitial = !this.getRiskStorage.has(key);
|
|
1539
1555
|
const instance = this.getRiskStorage(riskName, exchangeName);
|
|
@@ -1548,7 +1564,7 @@ class PersistRiskUtils {
|
|
|
1548
1564
|
* @param Ctor - Custom IPersistRiskInstance constructor
|
|
1549
1565
|
*/
|
|
1550
1566
|
usePersistRiskAdapter(Ctor) {
|
|
1551
|
-
LOGGER_SERVICE$
|
|
1567
|
+
LOGGER_SERVICE$8.info(PERSIST_RISK_UTILS_METHOD_NAME_USE_PERSIST_RISK_ADAPTER);
|
|
1552
1568
|
this.PersistRiskInstanceCtor = Ctor;
|
|
1553
1569
|
this.getRiskStorage.clear();
|
|
1554
1570
|
}
|
|
@@ -1557,21 +1573,21 @@ class PersistRiskUtils {
|
|
|
1557
1573
|
* Call when process.cwd() changes between strategy iterations.
|
|
1558
1574
|
*/
|
|
1559
1575
|
clear() {
|
|
1560
|
-
LOGGER_SERVICE$
|
|
1576
|
+
LOGGER_SERVICE$8.log(PERSIST_RISK_UTILS_METHOD_NAME_CLEAR);
|
|
1561
1577
|
this.getRiskStorage.clear();
|
|
1562
1578
|
}
|
|
1563
1579
|
/**
|
|
1564
1580
|
* Switches to the default file-based PersistRiskInstance.
|
|
1565
1581
|
*/
|
|
1566
1582
|
useJson() {
|
|
1567
|
-
LOGGER_SERVICE$
|
|
1583
|
+
LOGGER_SERVICE$8.log(PERSIST_RISK_UTILS_METHOD_NAME_USE_JSON);
|
|
1568
1584
|
this.usePersistRiskAdapter(PersistRiskInstance);
|
|
1569
1585
|
}
|
|
1570
1586
|
/**
|
|
1571
1587
|
* Switches to PersistRiskDummyInstance (all operations are no-ops).
|
|
1572
1588
|
*/
|
|
1573
1589
|
useDummy() {
|
|
1574
|
-
LOGGER_SERVICE$
|
|
1590
|
+
LOGGER_SERVICE$8.log(PERSIST_RISK_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1575
1591
|
this.usePersistRiskAdapter(PersistRiskDummyInstance);
|
|
1576
1592
|
}
|
|
1577
1593
|
}
|
|
@@ -1710,7 +1726,7 @@ class PersistScheduleUtils {
|
|
|
1710
1726
|
* @returns Promise resolving to scheduled signal or null if none persisted
|
|
1711
1727
|
*/
|
|
1712
1728
|
this.readScheduleData = async (symbol, strategyName, exchangeName) => {
|
|
1713
|
-
LOGGER_SERVICE$
|
|
1729
|
+
LOGGER_SERVICE$8.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_READ_DATA);
|
|
1714
1730
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1715
1731
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
1716
1732
|
const instance = this.getScheduleStorage(symbol, strategyName, exchangeName);
|
|
@@ -1728,7 +1744,7 @@ class PersistScheduleUtils {
|
|
|
1728
1744
|
* @returns Promise that resolves when write is complete
|
|
1729
1745
|
*/
|
|
1730
1746
|
this.writeScheduleData = async (scheduledSignalRow, symbol, strategyName, exchangeName) => {
|
|
1731
|
-
LOGGER_SERVICE$
|
|
1747
|
+
LOGGER_SERVICE$8.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1732
1748
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1733
1749
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
1734
1750
|
const instance = this.getScheduleStorage(symbol, strategyName, exchangeName);
|
|
@@ -1743,7 +1759,7 @@ class PersistScheduleUtils {
|
|
|
1743
1759
|
* @param Ctor - Custom IPersistScheduleInstance constructor
|
|
1744
1760
|
*/
|
|
1745
1761
|
usePersistScheduleAdapter(Ctor) {
|
|
1746
|
-
LOGGER_SERVICE$
|
|
1762
|
+
LOGGER_SERVICE$8.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_PERSIST_SCHEDULE_ADAPTER);
|
|
1747
1763
|
this.PersistScheduleInstanceCtor = Ctor;
|
|
1748
1764
|
this.getScheduleStorage.clear();
|
|
1749
1765
|
}
|
|
@@ -1752,21 +1768,21 @@ class PersistScheduleUtils {
|
|
|
1752
1768
|
* Call when process.cwd() changes between strategy iterations.
|
|
1753
1769
|
*/
|
|
1754
1770
|
clear() {
|
|
1755
|
-
LOGGER_SERVICE$
|
|
1771
|
+
LOGGER_SERVICE$8.log(PERSIST_SCHEDULE_UTILS_METHOD_NAME_CLEAR);
|
|
1756
1772
|
this.getScheduleStorage.clear();
|
|
1757
1773
|
}
|
|
1758
1774
|
/**
|
|
1759
1775
|
* Switches to the default file-based PersistScheduleInstance.
|
|
1760
1776
|
*/
|
|
1761
1777
|
useJson() {
|
|
1762
|
-
LOGGER_SERVICE$
|
|
1778
|
+
LOGGER_SERVICE$8.log(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_JSON);
|
|
1763
1779
|
this.usePersistScheduleAdapter(PersistScheduleInstance);
|
|
1764
1780
|
}
|
|
1765
1781
|
/**
|
|
1766
1782
|
* Switches to PersistScheduleDummyInstance (all operations are no-ops).
|
|
1767
1783
|
*/
|
|
1768
1784
|
useDummy() {
|
|
1769
|
-
LOGGER_SERVICE$
|
|
1785
|
+
LOGGER_SERVICE$8.log(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1770
1786
|
this.usePersistScheduleAdapter(PersistScheduleDummyInstance);
|
|
1771
1787
|
}
|
|
1772
1788
|
}
|
|
@@ -1911,7 +1927,7 @@ class PersistPartialUtils {
|
|
|
1911
1927
|
* @returns Promise resolving to partial data record (empty object if none)
|
|
1912
1928
|
*/
|
|
1913
1929
|
this.readPartialData = async (symbol, strategyName, signalId, exchangeName, when) => {
|
|
1914
|
-
LOGGER_SERVICE$
|
|
1930
|
+
LOGGER_SERVICE$8.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_READ_DATA);
|
|
1915
1931
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1916
1932
|
const isInitial = !this.getPartialStorage.has(key);
|
|
1917
1933
|
const instance = this.getPartialStorage(symbol, strategyName, exchangeName);
|
|
@@ -1931,7 +1947,7 @@ class PersistPartialUtils {
|
|
|
1931
1947
|
* @returns Promise that resolves when write is complete
|
|
1932
1948
|
*/
|
|
1933
1949
|
this.writePartialData = async (partialData, symbol, strategyName, signalId, exchangeName, when) => {
|
|
1934
|
-
LOGGER_SERVICE$
|
|
1950
|
+
LOGGER_SERVICE$8.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_WRITE_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);
|
|
@@ -1946,7 +1962,7 @@ class PersistPartialUtils {
|
|
|
1946
1962
|
* @param Ctor - Custom IPersistPartialInstance constructor
|
|
1947
1963
|
*/
|
|
1948
1964
|
usePersistPartialAdapter(Ctor) {
|
|
1949
|
-
LOGGER_SERVICE$
|
|
1965
|
+
LOGGER_SERVICE$8.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_PERSIST_PARTIAL_ADAPTER);
|
|
1950
1966
|
this.PersistPartialInstanceCtor = Ctor;
|
|
1951
1967
|
this.getPartialStorage.clear();
|
|
1952
1968
|
}
|
|
@@ -1955,21 +1971,21 @@ class PersistPartialUtils {
|
|
|
1955
1971
|
* Call when process.cwd() changes between strategy iterations.
|
|
1956
1972
|
*/
|
|
1957
1973
|
clear() {
|
|
1958
|
-
LOGGER_SERVICE$
|
|
1974
|
+
LOGGER_SERVICE$8.log(PERSIST_PARTIAL_UTILS_METHOD_NAME_CLEAR);
|
|
1959
1975
|
this.getPartialStorage.clear();
|
|
1960
1976
|
}
|
|
1961
1977
|
/**
|
|
1962
1978
|
* Switches to the default file-based PersistPartialInstance.
|
|
1963
1979
|
*/
|
|
1964
1980
|
useJson() {
|
|
1965
|
-
LOGGER_SERVICE$
|
|
1981
|
+
LOGGER_SERVICE$8.log(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_JSON);
|
|
1966
1982
|
this.usePersistPartialAdapter(PersistPartialInstance);
|
|
1967
1983
|
}
|
|
1968
1984
|
/**
|
|
1969
1985
|
* Switches to PersistPartialDummyInstance (all operations are no-ops).
|
|
1970
1986
|
*/
|
|
1971
1987
|
useDummy() {
|
|
1972
|
-
LOGGER_SERVICE$
|
|
1988
|
+
LOGGER_SERVICE$8.log(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1973
1989
|
this.usePersistPartialAdapter(PersistPartialDummyInstance);
|
|
1974
1990
|
}
|
|
1975
1991
|
}
|
|
@@ -2134,7 +2150,7 @@ class PersistBreakevenUtils {
|
|
|
2134
2150
|
* @returns Promise resolving to breakeven data record (empty object if none)
|
|
2135
2151
|
*/
|
|
2136
2152
|
this.readBreakevenData = async (symbol, strategyName, signalId, exchangeName, when) => {
|
|
2137
|
-
LOGGER_SERVICE$
|
|
2153
|
+
LOGGER_SERVICE$8.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_READ_DATA);
|
|
2138
2154
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
2139
2155
|
const isInitial = !this.getBreakevenStorage.has(key);
|
|
2140
2156
|
const instance = this.getBreakevenStorage(symbol, strategyName, exchangeName);
|
|
@@ -2154,7 +2170,7 @@ class PersistBreakevenUtils {
|
|
|
2154
2170
|
* @returns Promise that resolves when write is complete
|
|
2155
2171
|
*/
|
|
2156
2172
|
this.writeBreakevenData = async (breakevenData, symbol, strategyName, signalId, exchangeName, when) => {
|
|
2157
|
-
LOGGER_SERVICE$
|
|
2173
|
+
LOGGER_SERVICE$8.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_WRITE_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);
|
|
@@ -2169,7 +2185,7 @@ class PersistBreakevenUtils {
|
|
|
2169
2185
|
* @param Ctor - Custom IPersistBreakevenInstance constructor
|
|
2170
2186
|
*/
|
|
2171
2187
|
usePersistBreakevenAdapter(Ctor) {
|
|
2172
|
-
LOGGER_SERVICE$
|
|
2188
|
+
LOGGER_SERVICE$8.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_USE_PERSIST_BREAKEVEN_ADAPTER);
|
|
2173
2189
|
this.PersistBreakevenInstanceCtor = Ctor;
|
|
2174
2190
|
this.getBreakevenStorage.clear();
|
|
2175
2191
|
}
|
|
@@ -2178,21 +2194,21 @@ class PersistBreakevenUtils {
|
|
|
2178
2194
|
* Call when process.cwd() changes between strategy iterations.
|
|
2179
2195
|
*/
|
|
2180
2196
|
clear() {
|
|
2181
|
-
LOGGER_SERVICE$
|
|
2197
|
+
LOGGER_SERVICE$8.log(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_CLEAR);
|
|
2182
2198
|
this.getBreakevenStorage.clear();
|
|
2183
2199
|
}
|
|
2184
2200
|
/**
|
|
2185
2201
|
* Switches to the default file-based PersistBreakevenInstance.
|
|
2186
2202
|
*/
|
|
2187
2203
|
useJson() {
|
|
2188
|
-
LOGGER_SERVICE$
|
|
2204
|
+
LOGGER_SERVICE$8.log(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_USE_JSON);
|
|
2189
2205
|
this.usePersistBreakevenAdapter(PersistBreakevenInstance);
|
|
2190
2206
|
}
|
|
2191
2207
|
/**
|
|
2192
2208
|
* Switches to PersistBreakevenDummyInstance (all operations are no-ops).
|
|
2193
2209
|
*/
|
|
2194
2210
|
useDummy() {
|
|
2195
|
-
LOGGER_SERVICE$
|
|
2211
|
+
LOGGER_SERVICE$8.log(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2196
2212
|
this.usePersistBreakevenAdapter(PersistBreakevenDummyInstance);
|
|
2197
2213
|
}
|
|
2198
2214
|
}
|
|
@@ -2283,7 +2299,7 @@ class PersistCandleInstance {
|
|
|
2283
2299
|
error: errorData(error),
|
|
2284
2300
|
message: getErrorMessage(error),
|
|
2285
2301
|
};
|
|
2286
|
-
LOGGER_SERVICE$
|
|
2302
|
+
LOGGER_SERVICE$8.warn(message, payload);
|
|
2287
2303
|
console.warn(message, payload);
|
|
2288
2304
|
errorEmitter.next(error);
|
|
2289
2305
|
return null;
|
|
@@ -2305,7 +2321,7 @@ class PersistCandleInstance {
|
|
|
2305
2321
|
for (const candle of candles) {
|
|
2306
2322
|
const candleCloseTime = candle.timestamp + stepMs;
|
|
2307
2323
|
if (candleCloseTime > now) {
|
|
2308
|
-
LOGGER_SERVICE$
|
|
2324
|
+
LOGGER_SERVICE$8.debug("PersistCandleInstance.writeCandlesData: skipping incomplete candle", {
|
|
2309
2325
|
symbol: this.symbol,
|
|
2310
2326
|
interval: this.interval,
|
|
2311
2327
|
exchangeName: this.exchangeName,
|
|
@@ -2382,7 +2398,7 @@ class PersistCandleUtils {
|
|
|
2382
2398
|
* @returns Promise resolving to candles in order, or null on cache miss
|
|
2383
2399
|
*/
|
|
2384
2400
|
this.readCandlesData = async (symbol, interval, exchangeName, limit, sinceTimestamp, untilTimestamp) => {
|
|
2385
|
-
LOGGER_SERVICE$
|
|
2401
|
+
LOGGER_SERVICE$8.info("PersistCandleUtils.readCandlesData", {
|
|
2386
2402
|
symbol,
|
|
2387
2403
|
interval,
|
|
2388
2404
|
exchangeName,
|
|
@@ -2406,7 +2422,7 @@ class PersistCandleUtils {
|
|
|
2406
2422
|
* @returns Promise that resolves when all writes are complete
|
|
2407
2423
|
*/
|
|
2408
2424
|
this.writeCandlesData = async (candles, symbol, interval, exchangeName) => {
|
|
2409
|
-
LOGGER_SERVICE$
|
|
2425
|
+
LOGGER_SERVICE$8.info("PersistCandleUtils.writeCandlesData", {
|
|
2410
2426
|
symbol,
|
|
2411
2427
|
interval,
|
|
2412
2428
|
exchangeName,
|
|
@@ -2426,7 +2442,7 @@ class PersistCandleUtils {
|
|
|
2426
2442
|
* @param Ctor - Custom IPersistCandleInstance constructor
|
|
2427
2443
|
*/
|
|
2428
2444
|
usePersistCandleAdapter(Ctor) {
|
|
2429
|
-
LOGGER_SERVICE$
|
|
2445
|
+
LOGGER_SERVICE$8.info("PersistCandleUtils.usePersistCandleAdapter");
|
|
2430
2446
|
this.PersistCandleInstanceCtor = Ctor;
|
|
2431
2447
|
this.getCandlesStorage.clear();
|
|
2432
2448
|
}
|
|
@@ -2435,21 +2451,21 @@ class PersistCandleUtils {
|
|
|
2435
2451
|
* Call when process.cwd() changes between strategy iterations.
|
|
2436
2452
|
*/
|
|
2437
2453
|
clear() {
|
|
2438
|
-
LOGGER_SERVICE$
|
|
2454
|
+
LOGGER_SERVICE$8.log(PERSIST_CANDLE_UTILS_METHOD_NAME_CLEAR);
|
|
2439
2455
|
this.getCandlesStorage.clear();
|
|
2440
2456
|
}
|
|
2441
2457
|
/**
|
|
2442
2458
|
* Switches to the default file-based PersistCandleInstance.
|
|
2443
2459
|
*/
|
|
2444
2460
|
useJson() {
|
|
2445
|
-
LOGGER_SERVICE$
|
|
2461
|
+
LOGGER_SERVICE$8.log("PersistCandleUtils.useJson");
|
|
2446
2462
|
this.usePersistCandleAdapter(PersistCandleInstance);
|
|
2447
2463
|
}
|
|
2448
2464
|
/**
|
|
2449
2465
|
* Switches to PersistCandleDummyInstance (always returns null on read, discards writes).
|
|
2450
2466
|
*/
|
|
2451
2467
|
useDummy() {
|
|
2452
|
-
LOGGER_SERVICE$
|
|
2468
|
+
LOGGER_SERVICE$8.log("PersistCandleUtils.useDummy");
|
|
2453
2469
|
this.usePersistCandleAdapter(PersistCandleDummyInstance);
|
|
2454
2470
|
}
|
|
2455
2471
|
}
|
|
@@ -2587,7 +2603,7 @@ class PersistStorageUtils {
|
|
|
2587
2603
|
* @returns Promise resolving to array of signal entries
|
|
2588
2604
|
*/
|
|
2589
2605
|
this.readStorageData = async (backtest) => {
|
|
2590
|
-
LOGGER_SERVICE$
|
|
2606
|
+
LOGGER_SERVICE$8.info(PERSIST_STORAGE_UTILS_METHOD_NAME_READ_DATA);
|
|
2591
2607
|
const key = backtest ? `backtest` : `live`;
|
|
2592
2608
|
const isInitial = !this.getStorage.has(key);
|
|
2593
2609
|
const instance = this.getStorage(backtest);
|
|
@@ -2603,7 +2619,7 @@ class PersistStorageUtils {
|
|
|
2603
2619
|
* @returns Promise that resolves when write is complete
|
|
2604
2620
|
*/
|
|
2605
2621
|
this.writeStorageData = async (signalData, backtest) => {
|
|
2606
|
-
LOGGER_SERVICE$
|
|
2622
|
+
LOGGER_SERVICE$8.info(PERSIST_STORAGE_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2607
2623
|
const key = backtest ? `backtest` : `live`;
|
|
2608
2624
|
const isInitial = !this.getStorage.has(key);
|
|
2609
2625
|
const instance = this.getStorage(backtest);
|
|
@@ -2618,7 +2634,7 @@ class PersistStorageUtils {
|
|
|
2618
2634
|
* @param Ctor - Custom IPersistStorageInstance constructor
|
|
2619
2635
|
*/
|
|
2620
2636
|
usePersistStorageAdapter(Ctor) {
|
|
2621
|
-
LOGGER_SERVICE$
|
|
2637
|
+
LOGGER_SERVICE$8.info(PERSIST_STORAGE_UTILS_METHOD_NAME_USE_PERSIST_STORAGE_ADAPTER);
|
|
2622
2638
|
this.PersistStorageInstanceCtor = Ctor;
|
|
2623
2639
|
this.getStorage.clear();
|
|
2624
2640
|
}
|
|
@@ -2627,21 +2643,21 @@ class PersistStorageUtils {
|
|
|
2627
2643
|
* Call when process.cwd() changes between strategy iterations.
|
|
2628
2644
|
*/
|
|
2629
2645
|
clear() {
|
|
2630
|
-
LOGGER_SERVICE$
|
|
2646
|
+
LOGGER_SERVICE$8.log(PERSIST_STORAGE_UTILS_METHOD_NAME_CLEAR);
|
|
2631
2647
|
this.getStorage.clear();
|
|
2632
2648
|
}
|
|
2633
2649
|
/**
|
|
2634
2650
|
* Switches to the default file-based PersistStorageInstance.
|
|
2635
2651
|
*/
|
|
2636
2652
|
useJson() {
|
|
2637
|
-
LOGGER_SERVICE$
|
|
2653
|
+
LOGGER_SERVICE$8.log(PERSIST_STORAGE_UTILS_METHOD_NAME_USE_JSON);
|
|
2638
2654
|
this.usePersistStorageAdapter(PersistStorageInstance);
|
|
2639
2655
|
}
|
|
2640
2656
|
/**
|
|
2641
2657
|
* Switches to PersistStorageDummyInstance (all operations are no-ops).
|
|
2642
2658
|
*/
|
|
2643
2659
|
useDummy() {
|
|
2644
|
-
LOGGER_SERVICE$
|
|
2660
|
+
LOGGER_SERVICE$8.log(PERSIST_STORAGE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2645
2661
|
this.usePersistStorageAdapter(PersistStorageDummyInstance);
|
|
2646
2662
|
}
|
|
2647
2663
|
}
|
|
@@ -2768,7 +2784,7 @@ class PersistNotificationUtils {
|
|
|
2768
2784
|
* @returns Promise resolving to array of notification entries
|
|
2769
2785
|
*/
|
|
2770
2786
|
this.readNotificationData = async (backtest) => {
|
|
2771
|
-
LOGGER_SERVICE$
|
|
2787
|
+
LOGGER_SERVICE$8.info(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_READ_DATA);
|
|
2772
2788
|
const key = backtest ? `backtest` : `live`;
|
|
2773
2789
|
const isInitial = !this.getNotificationStorage.has(key);
|
|
2774
2790
|
const instance = this.getNotificationStorage(backtest);
|
|
@@ -2784,7 +2800,7 @@ class PersistNotificationUtils {
|
|
|
2784
2800
|
* @returns Promise that resolves when write is complete
|
|
2785
2801
|
*/
|
|
2786
2802
|
this.writeNotificationData = async (notificationData, backtest) => {
|
|
2787
|
-
LOGGER_SERVICE$
|
|
2803
|
+
LOGGER_SERVICE$8.info(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2788
2804
|
const key = backtest ? `backtest` : `live`;
|
|
2789
2805
|
const isInitial = !this.getNotificationStorage.has(key);
|
|
2790
2806
|
const instance = this.getNotificationStorage(backtest);
|
|
@@ -2799,7 +2815,7 @@ class PersistNotificationUtils {
|
|
|
2799
2815
|
* @param Ctor - Custom IPersistNotificationInstance constructor
|
|
2800
2816
|
*/
|
|
2801
2817
|
usePersistNotificationAdapter(Ctor) {
|
|
2802
|
-
LOGGER_SERVICE$
|
|
2818
|
+
LOGGER_SERVICE$8.info(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_USE_PERSIST_NOTIFICATION_ADAPTER);
|
|
2803
2819
|
this.PersistNotificationInstanceCtor = Ctor;
|
|
2804
2820
|
this.getNotificationStorage.clear();
|
|
2805
2821
|
}
|
|
@@ -2809,21 +2825,21 @@ class PersistNotificationUtils {
|
|
|
2809
2825
|
* instances are created with the updated base path.
|
|
2810
2826
|
*/
|
|
2811
2827
|
clear() {
|
|
2812
|
-
LOGGER_SERVICE$
|
|
2828
|
+
LOGGER_SERVICE$8.log(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_CLEAR);
|
|
2813
2829
|
this.getNotificationStorage.clear();
|
|
2814
2830
|
}
|
|
2815
2831
|
/**
|
|
2816
2832
|
* Switches to the default file-based PersistNotificationInstance.
|
|
2817
2833
|
*/
|
|
2818
2834
|
useJson() {
|
|
2819
|
-
LOGGER_SERVICE$
|
|
2835
|
+
LOGGER_SERVICE$8.log(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_USE_JSON);
|
|
2820
2836
|
this.usePersistNotificationAdapter(PersistNotificationInstance);
|
|
2821
2837
|
}
|
|
2822
2838
|
/**
|
|
2823
2839
|
* Switches to PersistNotificationDummyInstance (all operations are no-ops).
|
|
2824
2840
|
*/
|
|
2825
2841
|
useDummy() {
|
|
2826
|
-
LOGGER_SERVICE$
|
|
2842
|
+
LOGGER_SERVICE$8.log(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2827
2843
|
this.usePersistNotificationAdapter(PersistNotificationDummyInstance);
|
|
2828
2844
|
}
|
|
2829
2845
|
}
|
|
@@ -2947,7 +2963,7 @@ class PersistLogUtils {
|
|
|
2947
2963
|
* @returns Promise resolving to array of log entries
|
|
2948
2964
|
*/
|
|
2949
2965
|
this.readLogData = async () => {
|
|
2950
|
-
LOGGER_SERVICE$
|
|
2966
|
+
LOGGER_SERVICE$8.info(PERSIST_LOG_UTILS_METHOD_NAME_READ_DATA);
|
|
2951
2967
|
const isInitial = !this._logInstance;
|
|
2952
2968
|
const instance = this.getLogInstance();
|
|
2953
2969
|
await instance.waitForInit(isInitial);
|
|
@@ -2961,7 +2977,7 @@ class PersistLogUtils {
|
|
|
2961
2977
|
* @returns Promise that resolves when write is complete
|
|
2962
2978
|
*/
|
|
2963
2979
|
this.writeLogData = async (logData) => {
|
|
2964
|
-
LOGGER_SERVICE$
|
|
2980
|
+
LOGGER_SERVICE$8.info(PERSIST_LOG_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2965
2981
|
const isInitial = !this._logInstance;
|
|
2966
2982
|
const instance = this.getLogInstance();
|
|
2967
2983
|
await instance.waitForInit(isInitial);
|
|
@@ -2986,7 +3002,7 @@ class PersistLogUtils {
|
|
|
2986
3002
|
* @param Ctor - Custom IPersistLogInstance constructor
|
|
2987
3003
|
*/
|
|
2988
3004
|
usePersistLogAdapter(Ctor) {
|
|
2989
|
-
LOGGER_SERVICE$
|
|
3005
|
+
LOGGER_SERVICE$8.info(PERSIST_LOG_UTILS_METHOD_NAME_USE_PERSIST_LOG_ADAPTER);
|
|
2990
3006
|
this.PersistLogInstanceCtor = Ctor;
|
|
2991
3007
|
this._logInstance = null;
|
|
2992
3008
|
}
|
|
@@ -2995,21 +3011,21 @@ class PersistLogUtils {
|
|
|
2995
3011
|
* Call when process.cwd() changes between strategy iterations.
|
|
2996
3012
|
*/
|
|
2997
3013
|
clear() {
|
|
2998
|
-
LOGGER_SERVICE$
|
|
3014
|
+
LOGGER_SERVICE$8.log(PERSIST_LOG_UTILS_METHOD_NAME_CLEAR);
|
|
2999
3015
|
this._logInstance = null;
|
|
3000
3016
|
}
|
|
3001
3017
|
/**
|
|
3002
3018
|
* Switches to the default file-based PersistLogInstance.
|
|
3003
3019
|
*/
|
|
3004
3020
|
useJson() {
|
|
3005
|
-
LOGGER_SERVICE$
|
|
3021
|
+
LOGGER_SERVICE$8.log(PERSIST_LOG_UTILS_METHOD_NAME_USE_JSON);
|
|
3006
3022
|
this.usePersistLogAdapter(PersistLogInstance);
|
|
3007
3023
|
}
|
|
3008
3024
|
/**
|
|
3009
3025
|
* Switches to PersistLogDummyInstance (all operations are no-ops).
|
|
3010
3026
|
*/
|
|
3011
3027
|
useDummy() {
|
|
3012
|
-
LOGGER_SERVICE$
|
|
3028
|
+
LOGGER_SERVICE$8.log(PERSIST_LOG_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3013
3029
|
this.usePersistLogAdapter(PersistLogDummyInstance);
|
|
3014
3030
|
}
|
|
3015
3031
|
}
|
|
@@ -3171,7 +3187,7 @@ class PersistMeasureUtils {
|
|
|
3171
3187
|
* @returns Promise resolving to cached value, or null if not found / soft-deleted
|
|
3172
3188
|
*/
|
|
3173
3189
|
this.readMeasureData = async (bucket, key) => {
|
|
3174
|
-
LOGGER_SERVICE$
|
|
3190
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_READ_DATA, { bucket, key });
|
|
3175
3191
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3176
3192
|
const instance = this.getMeasureStorage(bucket);
|
|
3177
3193
|
await instance.waitForInit(isInitial);
|
|
@@ -3187,7 +3203,7 @@ class PersistMeasureUtils {
|
|
|
3187
3203
|
* @returns Promise that resolves when write is complete
|
|
3188
3204
|
*/
|
|
3189
3205
|
this.writeMeasureData = async (data, bucket, key, when) => {
|
|
3190
|
-
LOGGER_SERVICE$
|
|
3206
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_WRITE_DATA, { bucket, key });
|
|
3191
3207
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3192
3208
|
const instance = this.getMeasureStorage(bucket);
|
|
3193
3209
|
await instance.waitForInit(isInitial);
|
|
@@ -3202,7 +3218,7 @@ class PersistMeasureUtils {
|
|
|
3202
3218
|
* @returns Promise that resolves when removal is complete
|
|
3203
3219
|
*/
|
|
3204
3220
|
this.removeMeasureData = async (bucket, key) => {
|
|
3205
|
-
LOGGER_SERVICE$
|
|
3221
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_REMOVE_DATA, { bucket, key });
|
|
3206
3222
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3207
3223
|
const instance = this.getMeasureStorage(bucket);
|
|
3208
3224
|
await instance.waitForInit(isInitial);
|
|
@@ -3216,7 +3232,7 @@ class PersistMeasureUtils {
|
|
|
3216
3232
|
* @param Ctor - Custom IPersistMeasureInstance constructor
|
|
3217
3233
|
*/
|
|
3218
3234
|
usePersistMeasureAdapter(Ctor) {
|
|
3219
|
-
LOGGER_SERVICE$
|
|
3235
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_USE_PERSIST_MEASURE_ADAPTER);
|
|
3220
3236
|
this.PersistMeasureInstanceCtor = Ctor;
|
|
3221
3237
|
this.getMeasureStorage.clear();
|
|
3222
3238
|
}
|
|
@@ -3228,7 +3244,7 @@ class PersistMeasureUtils {
|
|
|
3228
3244
|
* @returns AsyncGenerator yielding entry keys
|
|
3229
3245
|
*/
|
|
3230
3246
|
async *listMeasureData(bucket) {
|
|
3231
|
-
LOGGER_SERVICE$
|
|
3247
|
+
LOGGER_SERVICE$8.info(PERSIST_MEASURE_UTILS_METHOD_NAME_LIST_DATA, { bucket });
|
|
3232
3248
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3233
3249
|
const instance = this.getMeasureStorage(bucket);
|
|
3234
3250
|
await instance.waitForInit(isInitial);
|
|
@@ -3239,21 +3255,21 @@ class PersistMeasureUtils {
|
|
|
3239
3255
|
* Call when process.cwd() changes between strategy iterations.
|
|
3240
3256
|
*/
|
|
3241
3257
|
clear() {
|
|
3242
|
-
LOGGER_SERVICE$
|
|
3258
|
+
LOGGER_SERVICE$8.log(PERSIST_MEASURE_UTILS_METHOD_NAME_CLEAR);
|
|
3243
3259
|
this.getMeasureStorage.clear();
|
|
3244
3260
|
}
|
|
3245
3261
|
/**
|
|
3246
3262
|
* Switches to the default file-based PersistMeasureInstance.
|
|
3247
3263
|
*/
|
|
3248
3264
|
useJson() {
|
|
3249
|
-
LOGGER_SERVICE$
|
|
3265
|
+
LOGGER_SERVICE$8.log(PERSIST_MEASURE_UTILS_METHOD_NAME_USE_JSON);
|
|
3250
3266
|
this.usePersistMeasureAdapter(PersistMeasureInstance);
|
|
3251
3267
|
}
|
|
3252
3268
|
/**
|
|
3253
3269
|
* Switches to PersistMeasureDummyInstance (all operations are no-ops).
|
|
3254
3270
|
*/
|
|
3255
3271
|
useDummy() {
|
|
3256
|
-
LOGGER_SERVICE$
|
|
3272
|
+
LOGGER_SERVICE$8.log(PERSIST_MEASURE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3257
3273
|
this.usePersistMeasureAdapter(PersistMeasureDummyInstance);
|
|
3258
3274
|
}
|
|
3259
3275
|
}
|
|
@@ -3412,7 +3428,7 @@ class PersistIntervalUtils {
|
|
|
3412
3428
|
* @returns Promise resolving to marker data, or null if not found / soft-deleted
|
|
3413
3429
|
*/
|
|
3414
3430
|
this.readIntervalData = async (bucket, key) => {
|
|
3415
|
-
LOGGER_SERVICE$
|
|
3431
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_READ_DATA, { bucket, key });
|
|
3416
3432
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3417
3433
|
const instance = this.getIntervalStorage(bucket);
|
|
3418
3434
|
await instance.waitForInit(isInitial);
|
|
@@ -3428,7 +3444,7 @@ class PersistIntervalUtils {
|
|
|
3428
3444
|
* @returns Promise that resolves when write is complete
|
|
3429
3445
|
*/
|
|
3430
3446
|
this.writeIntervalData = async (data, bucket, key, when) => {
|
|
3431
|
-
LOGGER_SERVICE$
|
|
3447
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_WRITE_DATA, { bucket, key });
|
|
3432
3448
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3433
3449
|
const instance = this.getIntervalStorage(bucket);
|
|
3434
3450
|
await instance.waitForInit(isInitial);
|
|
@@ -3443,7 +3459,7 @@ class PersistIntervalUtils {
|
|
|
3443
3459
|
* @returns Promise that resolves when removal is complete
|
|
3444
3460
|
*/
|
|
3445
3461
|
this.removeIntervalData = async (bucket, key) => {
|
|
3446
|
-
LOGGER_SERVICE$
|
|
3462
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_REMOVE_DATA, { bucket, key });
|
|
3447
3463
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3448
3464
|
const instance = this.getIntervalStorage(bucket);
|
|
3449
3465
|
await instance.waitForInit(isInitial);
|
|
@@ -3457,7 +3473,7 @@ class PersistIntervalUtils {
|
|
|
3457
3473
|
* @param Ctor - Custom IPersistIntervalInstance constructor
|
|
3458
3474
|
*/
|
|
3459
3475
|
usePersistIntervalAdapter(Ctor) {
|
|
3460
|
-
LOGGER_SERVICE$
|
|
3476
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_USE_PERSIST_INTERVAL_ADAPTER);
|
|
3461
3477
|
this.PersistIntervalInstanceCtor = Ctor;
|
|
3462
3478
|
this.getIntervalStorage.clear();
|
|
3463
3479
|
}
|
|
@@ -3469,7 +3485,7 @@ class PersistIntervalUtils {
|
|
|
3469
3485
|
* @returns AsyncGenerator yielding marker keys
|
|
3470
3486
|
*/
|
|
3471
3487
|
async *listIntervalData(bucket) {
|
|
3472
|
-
LOGGER_SERVICE$
|
|
3488
|
+
LOGGER_SERVICE$8.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_LIST_DATA, { bucket });
|
|
3473
3489
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3474
3490
|
const instance = this.getIntervalStorage(bucket);
|
|
3475
3491
|
await instance.waitForInit(isInitial);
|
|
@@ -3480,21 +3496,21 @@ class PersistIntervalUtils {
|
|
|
3480
3496
|
* Call when process.cwd() changes between strategy iterations.
|
|
3481
3497
|
*/
|
|
3482
3498
|
clear() {
|
|
3483
|
-
LOGGER_SERVICE$
|
|
3499
|
+
LOGGER_SERVICE$8.log(PERSIST_INTERVAL_UTILS_METHOD_NAME_CLEAR);
|
|
3484
3500
|
this.getIntervalStorage.clear();
|
|
3485
3501
|
}
|
|
3486
3502
|
/**
|
|
3487
3503
|
* Switches to the default file-based PersistIntervalInstance.
|
|
3488
3504
|
*/
|
|
3489
3505
|
useJson() {
|
|
3490
|
-
LOGGER_SERVICE$
|
|
3506
|
+
LOGGER_SERVICE$8.log(PERSIST_INTERVAL_UTILS_METHOD_NAME_USE_JSON);
|
|
3491
3507
|
this.usePersistIntervalAdapter(PersistIntervalInstance);
|
|
3492
3508
|
}
|
|
3493
3509
|
/**
|
|
3494
3510
|
* Switches to PersistIntervalDummyInstance (all operations are no-ops).
|
|
3495
3511
|
*/
|
|
3496
3512
|
useDummy() {
|
|
3497
|
-
LOGGER_SERVICE$
|
|
3513
|
+
LOGGER_SERVICE$8.log(PERSIST_INTERVAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3498
3514
|
this.usePersistIntervalAdapter(PersistIntervalDummyInstance);
|
|
3499
3515
|
}
|
|
3500
3516
|
}
|
|
@@ -3700,7 +3716,7 @@ class PersistMemoryUtils {
|
|
|
3700
3716
|
* @returns Promise resolving to entry data, or null if not found / soft-deleted
|
|
3701
3717
|
*/
|
|
3702
3718
|
this.readMemoryData = async (signalId, bucketName, memoryId) => {
|
|
3703
|
-
LOGGER_SERVICE$
|
|
3719
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_READ_DATA, { signalId, bucketName, memoryId });
|
|
3704
3720
|
const key = `${signalId}:${bucketName}`;
|
|
3705
3721
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3706
3722
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3717,7 +3733,7 @@ class PersistMemoryUtils {
|
|
|
3717
3733
|
* @returns Promise resolving to true if entry exists
|
|
3718
3734
|
*/
|
|
3719
3735
|
this.hasMemoryData = async (signalId, bucketName, memoryId) => {
|
|
3720
|
-
LOGGER_SERVICE$
|
|
3736
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_HAS_DATA, { signalId, bucketName, memoryId });
|
|
3721
3737
|
const key = `${signalId}:${bucketName}`;
|
|
3722
3738
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3723
3739
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3736,7 +3752,7 @@ class PersistMemoryUtils {
|
|
|
3736
3752
|
* @returns Promise that resolves when write is complete
|
|
3737
3753
|
*/
|
|
3738
3754
|
this.writeMemoryData = async (data, signalId, bucketName, memoryId, when) => {
|
|
3739
|
-
LOGGER_SERVICE$
|
|
3755
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName, memoryId });
|
|
3740
3756
|
const key = `${signalId}:${bucketName}`;
|
|
3741
3757
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3742
3758
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3753,7 +3769,7 @@ class PersistMemoryUtils {
|
|
|
3753
3769
|
* @returns Promise that resolves when removal is complete
|
|
3754
3770
|
*/
|
|
3755
3771
|
this.removeMemoryData = async (signalId, bucketName, memoryId) => {
|
|
3756
|
-
LOGGER_SERVICE$
|
|
3772
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_REMOVE_DATA, { signalId, bucketName, memoryId });
|
|
3757
3773
|
const key = `${signalId}:${bucketName}`;
|
|
3758
3774
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3759
3775
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3765,7 +3781,7 @@ class PersistMemoryUtils {
|
|
|
3765
3781
|
* Call when process.cwd() changes between strategy iterations.
|
|
3766
3782
|
*/
|
|
3767
3783
|
this.clear = () => {
|
|
3768
|
-
LOGGER_SERVICE$
|
|
3784
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_CLEAR);
|
|
3769
3785
|
this.getMemoryStorage.clear();
|
|
3770
3786
|
};
|
|
3771
3787
|
/**
|
|
@@ -3776,7 +3792,7 @@ class PersistMemoryUtils {
|
|
|
3776
3792
|
* @param bucketName - Bucket name
|
|
3777
3793
|
*/
|
|
3778
3794
|
this.dispose = (signalId, bucketName) => {
|
|
3779
|
-
LOGGER_SERVICE$
|
|
3795
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_DISPOSE);
|
|
3780
3796
|
const key = `${signalId}:${bucketName}`;
|
|
3781
3797
|
this.getMemoryStorage.clear(key);
|
|
3782
3798
|
};
|
|
@@ -3788,7 +3804,7 @@ class PersistMemoryUtils {
|
|
|
3788
3804
|
* @param Ctor - Custom IPersistMemoryInstance constructor
|
|
3789
3805
|
*/
|
|
3790
3806
|
usePersistMemoryAdapter(Ctor) {
|
|
3791
|
-
LOGGER_SERVICE$
|
|
3807
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_USE_PERSIST_MEMORY_ADAPTER);
|
|
3792
3808
|
this.PersistMemoryInstanceCtor = Ctor;
|
|
3793
3809
|
this.getMemoryStorage.clear();
|
|
3794
3810
|
}
|
|
@@ -3802,7 +3818,7 @@ class PersistMemoryUtils {
|
|
|
3802
3818
|
* @returns AsyncGenerator yielding `{ memoryId, data }` tuples
|
|
3803
3819
|
*/
|
|
3804
3820
|
async *listMemoryData(signalId, bucketName) {
|
|
3805
|
-
LOGGER_SERVICE$
|
|
3821
|
+
LOGGER_SERVICE$8.info(PERSIST_MEMORY_UTILS_METHOD_NAME_LIST_DATA, { signalId, bucketName });
|
|
3806
3822
|
const key = `${signalId}:${bucketName}`;
|
|
3807
3823
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3808
3824
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3813,14 +3829,14 @@ class PersistMemoryUtils {
|
|
|
3813
3829
|
* Switches to the default file-based PersistMemoryInstance.
|
|
3814
3830
|
*/
|
|
3815
3831
|
useJson() {
|
|
3816
|
-
LOGGER_SERVICE$
|
|
3832
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_JSON);
|
|
3817
3833
|
this.usePersistMemoryAdapter(PersistMemoryInstance);
|
|
3818
3834
|
}
|
|
3819
3835
|
/**
|
|
3820
3836
|
* Switches to PersistMemoryDummyInstance (all operations are no-ops).
|
|
3821
3837
|
*/
|
|
3822
3838
|
useDummy() {
|
|
3823
|
-
LOGGER_SERVICE$
|
|
3839
|
+
LOGGER_SERVICE$8.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3824
3840
|
this.usePersistMemoryAdapter(PersistMemoryDummyInstance);
|
|
3825
3841
|
}
|
|
3826
3842
|
}
|
|
@@ -3969,7 +3985,7 @@ class PersistRecentUtils {
|
|
|
3969
3985
|
* @returns Promise resolving to recent signal or null if none persisted
|
|
3970
3986
|
*/
|
|
3971
3987
|
this.readRecentData = async (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
3972
|
-
LOGGER_SERVICE$
|
|
3988
|
+
LOGGER_SERVICE$8.info(PERSIST_RECENT_UTILS_METHOD_NAME_READ_DATA);
|
|
3973
3989
|
const key = this.createKey(symbol, strategyName, exchangeName, frameName, backtest);
|
|
3974
3990
|
const isInitial = !this.getStorage.has(key);
|
|
3975
3991
|
const instance = this.getStorage(symbol, strategyName, exchangeName, frameName, backtest);
|
|
@@ -3990,7 +4006,7 @@ class PersistRecentUtils {
|
|
|
3990
4006
|
* @returns Promise that resolves when write is complete
|
|
3991
4007
|
*/
|
|
3992
4008
|
this.writeRecentData = async (signalRow, symbol, strategyName, exchangeName, frameName, backtest, when) => {
|
|
3993
|
-
LOGGER_SERVICE$
|
|
4009
|
+
LOGGER_SERVICE$8.info(PERSIST_RECENT_UTILS_METHOD_NAME_WRITE_DATA);
|
|
3994
4010
|
const key = this.createKey(symbol, strategyName, exchangeName, frameName, backtest);
|
|
3995
4011
|
const isInitial = !this.getStorage.has(key);
|
|
3996
4012
|
const instance = this.getStorage(symbol, strategyName, exchangeName, frameName, backtest);
|
|
@@ -4023,7 +4039,7 @@ class PersistRecentUtils {
|
|
|
4023
4039
|
* @param Ctor - Custom IPersistRecentInstance constructor
|
|
4024
4040
|
*/
|
|
4025
4041
|
usePersistRecentAdapter(Ctor) {
|
|
4026
|
-
LOGGER_SERVICE$
|
|
4042
|
+
LOGGER_SERVICE$8.info(PERSIST_RECENT_UTILS_METHOD_NAME_USE_PERSIST_RECENT_ADAPTER);
|
|
4027
4043
|
this.PersistRecentInstanceCtor = Ctor;
|
|
4028
4044
|
this.getStorage.clear();
|
|
4029
4045
|
}
|
|
@@ -4032,21 +4048,21 @@ class PersistRecentUtils {
|
|
|
4032
4048
|
* Call when process.cwd() changes between strategy iterations.
|
|
4033
4049
|
*/
|
|
4034
4050
|
clear() {
|
|
4035
|
-
LOGGER_SERVICE$
|
|
4051
|
+
LOGGER_SERVICE$8.log(PERSIST_RECENT_UTILS_METHOD_NAME_CLEAR);
|
|
4036
4052
|
this.getStorage.clear();
|
|
4037
4053
|
}
|
|
4038
4054
|
/**
|
|
4039
4055
|
* Switches to the default file-based PersistRecentInstance.
|
|
4040
4056
|
*/
|
|
4041
4057
|
useJson() {
|
|
4042
|
-
LOGGER_SERVICE$
|
|
4058
|
+
LOGGER_SERVICE$8.log(PERSIST_RECENT_UTILS_METHOD_NAME_USE_JSON);
|
|
4043
4059
|
this.usePersistRecentAdapter(PersistRecentInstance);
|
|
4044
4060
|
}
|
|
4045
4061
|
/**
|
|
4046
4062
|
* Switches to PersistRecentDummyInstance (all operations are no-ops).
|
|
4047
4063
|
*/
|
|
4048
4064
|
useDummy() {
|
|
4049
|
-
LOGGER_SERVICE$
|
|
4065
|
+
LOGGER_SERVICE$8.log(PERSIST_RECENT_UTILS_METHOD_NAME_USE_DUMMY);
|
|
4050
4066
|
this.usePersistRecentAdapter(PersistRecentDummyInstance);
|
|
4051
4067
|
}
|
|
4052
4068
|
}
|
|
@@ -4181,7 +4197,7 @@ class PersistStateUtils {
|
|
|
4181
4197
|
* @returns Promise that resolves when initialization is complete
|
|
4182
4198
|
*/
|
|
4183
4199
|
this.waitForInit = async (signalId, bucketName, initial) => {
|
|
4184
|
-
LOGGER_SERVICE$
|
|
4200
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_WAIT_FOR_INIT, { signalId, bucketName, initial });
|
|
4185
4201
|
const key = `${signalId}:${bucketName}`;
|
|
4186
4202
|
const isInitial = initial && !this.getStateStorage.has(key);
|
|
4187
4203
|
const instance = this.getStateStorage(signalId, bucketName);
|
|
@@ -4196,7 +4212,7 @@ class PersistStateUtils {
|
|
|
4196
4212
|
* @returns Promise resolving to state data or null if none persisted
|
|
4197
4213
|
*/
|
|
4198
4214
|
this.readStateData = async (signalId, bucketName) => {
|
|
4199
|
-
LOGGER_SERVICE$
|
|
4215
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_READ_DATA, { signalId, bucketName });
|
|
4200
4216
|
const key = `${signalId}:${bucketName}`;
|
|
4201
4217
|
const isInitial = !this.getStateStorage.has(key);
|
|
4202
4218
|
const instance = this.getStateStorage(signalId, bucketName);
|
|
@@ -4214,7 +4230,7 @@ class PersistStateUtils {
|
|
|
4214
4230
|
* @returns Promise that resolves when write is complete
|
|
4215
4231
|
*/
|
|
4216
4232
|
this.writeStateData = async (data, signalId, bucketName, when) => {
|
|
4217
|
-
LOGGER_SERVICE$
|
|
4233
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName });
|
|
4218
4234
|
const key = `${signalId}:${bucketName}`;
|
|
4219
4235
|
const isInitial = !this.getStateStorage.has(key);
|
|
4220
4236
|
const instance = this.getStateStorage(signalId, bucketName);
|
|
@@ -4225,14 +4241,14 @@ class PersistStateUtils {
|
|
|
4225
4241
|
* Switches to PersistStateDummyInstance (all operations are no-ops).
|
|
4226
4242
|
*/
|
|
4227
4243
|
this.useDummy = () => {
|
|
4228
|
-
LOGGER_SERVICE$
|
|
4244
|
+
LOGGER_SERVICE$8.log(PERSIST_STATE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
4229
4245
|
this.usePersistStateAdapter(PersistStateDummyInstance);
|
|
4230
4246
|
};
|
|
4231
4247
|
/**
|
|
4232
4248
|
* Switches to the default file-based PersistStateInstance.
|
|
4233
4249
|
*/
|
|
4234
4250
|
this.useJson = () => {
|
|
4235
|
-
LOGGER_SERVICE$
|
|
4251
|
+
LOGGER_SERVICE$8.log(PERSIST_STATE_UTILS_METHOD_NAME_USE_JSON);
|
|
4236
4252
|
this.usePersistStateAdapter(PersistStateInstance);
|
|
4237
4253
|
};
|
|
4238
4254
|
/**
|
|
@@ -4240,7 +4256,7 @@ class PersistStateUtils {
|
|
|
4240
4256
|
* Call when process.cwd() changes between strategy iterations.
|
|
4241
4257
|
*/
|
|
4242
4258
|
this.clear = () => {
|
|
4243
|
-
LOGGER_SERVICE$
|
|
4259
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_CLEAR);
|
|
4244
4260
|
this.getStateStorage.clear();
|
|
4245
4261
|
};
|
|
4246
4262
|
/**
|
|
@@ -4251,7 +4267,7 @@ class PersistStateUtils {
|
|
|
4251
4267
|
* @param bucketName - Bucket name
|
|
4252
4268
|
*/
|
|
4253
4269
|
this.dispose = (signalId, bucketName) => {
|
|
4254
|
-
LOGGER_SERVICE$
|
|
4270
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_DISPOSE);
|
|
4255
4271
|
const key = `${signalId}:${bucketName}`;
|
|
4256
4272
|
this.getStateStorage.clear(key);
|
|
4257
4273
|
};
|
|
@@ -4263,7 +4279,7 @@ class PersistStateUtils {
|
|
|
4263
4279
|
* @param Ctor - Custom IPersistStateInstance constructor
|
|
4264
4280
|
*/
|
|
4265
4281
|
usePersistStateAdapter(Ctor) {
|
|
4266
|
-
LOGGER_SERVICE$
|
|
4282
|
+
LOGGER_SERVICE$8.info(PERSIST_STATE_UTILS_METHOD_NAME_USE_PERSIST_STATE_ADAPTER);
|
|
4267
4283
|
this.PersistStateInstanceCtor = Ctor;
|
|
4268
4284
|
this.getStateStorage.clear();
|
|
4269
4285
|
}
|
|
@@ -4403,7 +4419,7 @@ class PersistSessionUtils {
|
|
|
4403
4419
|
* @returns Promise that resolves when initialization is complete
|
|
4404
4420
|
*/
|
|
4405
4421
|
this.waitForInit = async (strategyName, exchangeName, frameName, initial) => {
|
|
4406
|
-
LOGGER_SERVICE$
|
|
4422
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_WAIT_FOR_INIT, { strategyName, exchangeName, frameName, initial });
|
|
4407
4423
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4408
4424
|
const isInitial = initial && !this.getSessionStorage.has(key);
|
|
4409
4425
|
const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
|
|
@@ -4419,7 +4435,7 @@ class PersistSessionUtils {
|
|
|
4419
4435
|
* @returns Promise resolving to session data or null if none persisted
|
|
4420
4436
|
*/
|
|
4421
4437
|
this.readSessionData = async (strategyName, exchangeName, frameName) => {
|
|
4422
|
-
LOGGER_SERVICE$
|
|
4438
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_READ_DATA, { strategyName, exchangeName, frameName });
|
|
4423
4439
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4424
4440
|
const isInitial = !this.getSessionStorage.has(key);
|
|
4425
4441
|
const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
|
|
@@ -4438,7 +4454,7 @@ class PersistSessionUtils {
|
|
|
4438
4454
|
* @returns Promise that resolves when write is complete
|
|
4439
4455
|
*/
|
|
4440
4456
|
this.writeSessionData = async (data, strategyName, exchangeName, frameName, when) => {
|
|
4441
|
-
LOGGER_SERVICE$
|
|
4457
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_WRITE_DATA, { strategyName, exchangeName, frameName });
|
|
4442
4458
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4443
4459
|
const isInitial = !this.getSessionStorage.has(key);
|
|
4444
4460
|
const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
|
|
@@ -4449,14 +4465,14 @@ class PersistSessionUtils {
|
|
|
4449
4465
|
* Switches to PersistSessionDummyInstance (all operations are no-ops).
|
|
4450
4466
|
*/
|
|
4451
4467
|
this.useDummy = () => {
|
|
4452
|
-
LOGGER_SERVICE$
|
|
4468
|
+
LOGGER_SERVICE$8.log(PERSIST_SESSION_UTILS_METHOD_NAME_USE_DUMMY);
|
|
4453
4469
|
this.usePersistSessionAdapter(PersistSessionDummyInstance);
|
|
4454
4470
|
};
|
|
4455
4471
|
/**
|
|
4456
4472
|
* Switches to the default file-based PersistSessionInstance.
|
|
4457
4473
|
*/
|
|
4458
4474
|
this.useJson = () => {
|
|
4459
|
-
LOGGER_SERVICE$
|
|
4475
|
+
LOGGER_SERVICE$8.log(PERSIST_SESSION_UTILS_METHOD_NAME_USE_JSON);
|
|
4460
4476
|
this.usePersistSessionAdapter(PersistSessionInstance);
|
|
4461
4477
|
};
|
|
4462
4478
|
/**
|
|
@@ -4464,7 +4480,7 @@ class PersistSessionUtils {
|
|
|
4464
4480
|
* Call when process.cwd() changes between strategy iterations.
|
|
4465
4481
|
*/
|
|
4466
4482
|
this.clear = () => {
|
|
4467
|
-
LOGGER_SERVICE$
|
|
4483
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_CLEAR);
|
|
4468
4484
|
this.getSessionStorage.clear();
|
|
4469
4485
|
};
|
|
4470
4486
|
/**
|
|
@@ -4476,7 +4492,7 @@ class PersistSessionUtils {
|
|
|
4476
4492
|
* @param frameName - Frame identifier
|
|
4477
4493
|
*/
|
|
4478
4494
|
this.dispose = (strategyName, exchangeName, frameName) => {
|
|
4479
|
-
LOGGER_SERVICE$
|
|
4495
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_DISPOSE);
|
|
4480
4496
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4481
4497
|
this.getSessionStorage.clear(key);
|
|
4482
4498
|
};
|
|
@@ -4488,7 +4504,7 @@ class PersistSessionUtils {
|
|
|
4488
4504
|
* @param Ctor - Custom IPersistSessionInstance constructor
|
|
4489
4505
|
*/
|
|
4490
4506
|
usePersistSessionAdapter(Ctor) {
|
|
4491
|
-
LOGGER_SERVICE$
|
|
4507
|
+
LOGGER_SERVICE$8.info(PERSIST_SESSION_UTILS_METHOD_NAME_USE_PERSIST_SESSION_ADAPTER);
|
|
4492
4508
|
this.PersistSessionInstanceCtor = Ctor;
|
|
4493
4509
|
this.getSessionStorage.clear();
|
|
4494
4510
|
}
|
|
@@ -4500,28 +4516,39 @@ class PersistSessionUtils {
|
|
|
4500
4516
|
const PersistSessionAdapter = new PersistSessionUtils();
|
|
4501
4517
|
|
|
4502
4518
|
var _a$2, _b$2;
|
|
4503
|
-
const BUSY_DELAY = 100;
|
|
4504
4519
|
const SET_BUSY_SYMBOL = Symbol("setBusy");
|
|
4505
4520
|
const GET_BUSY_SYMBOL = Symbol("getBusy");
|
|
4506
4521
|
const ACQUIRE_LOCK_SYMBOL = Symbol("acquireLock");
|
|
4507
4522
|
const RELEASE_LOCK_SYMBOL = Symbol("releaseLock");
|
|
4523
|
+
/**
|
|
4524
|
+
* Body of the queued acquire operation.
|
|
4525
|
+
*
|
|
4526
|
+
* Parks the caller on `self._tick` whenever the lock is already busy: each
|
|
4527
|
+
* `releaseLock` emits on `_tick`, waking exactly the next queued acquirer
|
|
4528
|
+
* instead of polling on a fixed delay. The busy counter is bumped only after
|
|
4529
|
+
* the loop exits, so re-entry checks remain coherent under contention.
|
|
4530
|
+
*
|
|
4531
|
+
* @param self - The owning {@link Lock} instance.
|
|
4532
|
+
*/
|
|
4508
4533
|
const ACQUIRE_LOCK_FN = async (self) => {
|
|
4509
4534
|
while (self[GET_BUSY_SYMBOL]()) {
|
|
4510
|
-
|
|
4535
|
+
// @ts-ignore
|
|
4536
|
+
await self._tick.toPromise();
|
|
4511
4537
|
}
|
|
4512
4538
|
self[SET_BUSY_SYMBOL](true);
|
|
4513
4539
|
};
|
|
4514
4540
|
/**
|
|
4515
4541
|
* Mutual exclusion primitive for async TypeScript code.
|
|
4516
4542
|
*
|
|
4517
|
-
* Provides a
|
|
4518
|
-
*
|
|
4519
|
-
*
|
|
4520
|
-
*
|
|
4543
|
+
* Provides a queued lock that serializes access to a critical section across
|
|
4544
|
+
* concurrent async callers. Wake-ups are event-driven (via an internal
|
|
4545
|
+
* `_tick` subject emitted on every `releaseLock`) rather than polling,
|
|
4546
|
+
* so contention does not incur a fixed delay.
|
|
4521
4547
|
*
|
|
4522
|
-
*
|
|
4548
|
+
* The busy counter detects mis-matched releases and throws immediately on
|
|
4549
|
+
* extra `releaseLock` calls.
|
|
4523
4550
|
*
|
|
4524
|
-
* **
|
|
4551
|
+
* **Usage**
|
|
4525
4552
|
* ```ts
|
|
4526
4553
|
* await lock.acquireLock();
|
|
4527
4554
|
* try {
|
|
@@ -4536,7 +4563,18 @@ const ACQUIRE_LOCK_FN = async (self) => {
|
|
|
4536
4563
|
*/
|
|
4537
4564
|
class Lock {
|
|
4538
4565
|
constructor() {
|
|
4566
|
+
/**
|
|
4567
|
+
* Outstanding acquires that have not yet been released.
|
|
4568
|
+
* Incremented in `[SET_BUSY_SYMBOL](true)`, decremented in `[SET_BUSY_SYMBOL](false)`.
|
|
4569
|
+
* A negative value indicates an extra `releaseLock` and throws on detection.
|
|
4570
|
+
*/
|
|
4539
4571
|
this._isBusy = 0;
|
|
4572
|
+
/**
|
|
4573
|
+
* Wake-up channel for {@link ACQUIRE_LOCK_FN}.
|
|
4574
|
+
* Every {@link releaseLock} emits a single tick that unblocks the next
|
|
4575
|
+
* queued acquirer parked on `toPromise()`.
|
|
4576
|
+
*/
|
|
4577
|
+
this._tick = new Subject();
|
|
4540
4578
|
this[_a$2] = queued(ACQUIRE_LOCK_FN);
|
|
4541
4579
|
this[_b$2] = () => this[SET_BUSY_SYMBOL](false);
|
|
4542
4580
|
/**
|
|
@@ -4557,16 +4595,19 @@ class Lock {
|
|
|
4557
4595
|
await this[ACQUIRE_LOCK_SYMBOL](this);
|
|
4558
4596
|
};
|
|
4559
4597
|
/**
|
|
4560
|
-
* Releases the lock previously acquired with {@link acquireLock}
|
|
4598
|
+
* Releases the lock previously acquired with {@link acquireLock} and emits
|
|
4599
|
+
* on the internal `_tick` subject to wake the next queued acquirer.
|
|
4600
|
+
*
|
|
4561
4601
|
* Must be called exactly once per successful {@link acquireLock} call,
|
|
4562
|
-
* typically inside a `finally` block. Throws if called more times
|
|
4563
|
-
*
|
|
4602
|
+
* typically inside a `finally` block. Throws if called more times than
|
|
4603
|
+
* the lock was acquired.
|
|
4564
4604
|
*
|
|
4565
4605
|
* @returns {Promise<void>} Resolves once the lock has been released.
|
|
4566
4606
|
* @throws {Error} If the lock is released more times than it was acquired.
|
|
4567
4607
|
*/
|
|
4568
4608
|
this.releaseLock = async () => {
|
|
4569
4609
|
await this[RELEASE_LOCK_SYMBOL]();
|
|
4610
|
+
await this._tick.next();
|
|
4570
4611
|
};
|
|
4571
4612
|
}
|
|
4572
4613
|
[SET_BUSY_SYMBOL](isBusy) {
|
|
@@ -4581,18 +4622,166 @@ class Lock {
|
|
|
4581
4622
|
}
|
|
4582
4623
|
_a$2 = ACQUIRE_LOCK_SYMBOL, _b$2 = RELEASE_LOCK_SYMBOL;
|
|
4583
4624
|
|
|
4625
|
+
const METHOD_NAME_ADD_ACTIVITY = "LookupUtils.addActivity";
|
|
4626
|
+
const METHOD_NAME_REMOVE_ACTIVITY = "LookupUtils.removeActivity";
|
|
4627
|
+
const METHOD_NAME_LIST_ACTIVITY = "LookupUtils.listActivity";
|
|
4628
|
+
/** Logger service injected as DI singleton */
|
|
4629
|
+
const LOGGER_SERVICE$7 = new LoggerService();
|
|
4630
|
+
/**
|
|
4631
|
+
* Builds the composite {@link Key} used to register an activity in `_lookupMap`.
|
|
4632
|
+
*
|
|
4633
|
+
* Mirrors the {@link Key} type construction: appends `frameName` only when provided
|
|
4634
|
+
* (typical for backtest), then a `"backtest"` / `"live"` discriminator suffix.
|
|
4635
|
+
*
|
|
4636
|
+
* @param symbol - Trading pair symbol.
|
|
4637
|
+
* @param strategyName - Strategy schema name.
|
|
4638
|
+
* @param exchangeName - Exchange schema name.
|
|
4639
|
+
* @param frameName - Frame schema name; omitted from the key when falsy.
|
|
4640
|
+
* @param backtest - `true` for backtest, `false` for live.
|
|
4641
|
+
* @returns Colon-joined composite key.
|
|
4642
|
+
*/
|
|
4643
|
+
const CREATE_KEY_FN$y = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
4644
|
+
const parts = [symbol, strategyName, exchangeName];
|
|
4645
|
+
if (frameName)
|
|
4646
|
+
parts.push(frameName);
|
|
4647
|
+
parts.push(backtest ? "backtest" : "live");
|
|
4648
|
+
return parts.join(":");
|
|
4649
|
+
};
|
|
4650
|
+
/**
|
|
4651
|
+
* In-memory registry of currently running backtest and live activities.
|
|
4652
|
+
*
|
|
4653
|
+
* Purpose:
|
|
4654
|
+
* - Each `Backtest.run` / `Live.run` / per-strategy walker iteration registers an
|
|
4655
|
+
* {@link IActivityEntry} on start and removes it on completion.
|
|
4656
|
+
* - `Candle.spinLock` consults {@link isParallel} to decide whether the event-loop
|
|
4657
|
+
* hand-off (post-candle-fetch spin) is worth performing. With a single active
|
|
4658
|
+
* workload there is no peer to yield to, so the spin is skipped entirely.
|
|
4659
|
+
*
|
|
4660
|
+
* Exposed as the `Lookup` singleton; no constructor parameters.
|
|
4661
|
+
*
|
|
4662
|
+
* @example
|
|
4663
|
+
* ```typescript
|
|
4664
|
+
* Lookup.addActivity({ symbol: "BTCUSDT", context, backtest: true });
|
|
4665
|
+
* try {
|
|
4666
|
+
* for await (const _ of run(symbol, context)) { ... }
|
|
4667
|
+
* } finally {
|
|
4668
|
+
* Lookup.removeActivity({ symbol: "BTCUSDT", context, backtest: true });
|
|
4669
|
+
* }
|
|
4670
|
+
* ```
|
|
4671
|
+
*/
|
|
4672
|
+
class LookupUtils {
|
|
4673
|
+
constructor() {
|
|
4674
|
+
/** Active entries keyed by their composite {@link Key}. */
|
|
4675
|
+
this._lookupMap = new Map();
|
|
4676
|
+
/**
|
|
4677
|
+
* Registers a backtest or live activity in the lookup map.
|
|
4678
|
+
* Idempotent for identical keys — duplicate calls overwrite the existing entry.
|
|
4679
|
+
*
|
|
4680
|
+
* @param activity - Activity descriptor identifying the running workload.
|
|
4681
|
+
*/
|
|
4682
|
+
this.addActivity = (activity) => {
|
|
4683
|
+
LOGGER_SERVICE$7.info(METHOD_NAME_ADD_ACTIVITY, {
|
|
4684
|
+
activity,
|
|
4685
|
+
});
|
|
4686
|
+
const key = CREATE_KEY_FN$y(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
|
|
4687
|
+
this._lookupMap.set(key, activity);
|
|
4688
|
+
};
|
|
4689
|
+
/**
|
|
4690
|
+
* Removes a previously registered activity from the lookup map.
|
|
4691
|
+
* Must be paired with a prior {@link addActivity}, typically in a `finally` block,
|
|
4692
|
+
* so a thrown error in the underlying run does not leave a stale entry behind.
|
|
4693
|
+
*
|
|
4694
|
+
* @param activity - Activity descriptor matching the one passed to {@link addActivity}.
|
|
4695
|
+
*/
|
|
4696
|
+
this.removeActivity = (activity) => {
|
|
4697
|
+
LOGGER_SERVICE$7.info(METHOD_NAME_REMOVE_ACTIVITY, {
|
|
4698
|
+
activity,
|
|
4699
|
+
});
|
|
4700
|
+
const key = CREATE_KEY_FN$y(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
|
|
4701
|
+
this._lookupMap.delete(key);
|
|
4702
|
+
};
|
|
4703
|
+
/**
|
|
4704
|
+
* Returns a snapshot of currently active entries.
|
|
4705
|
+
*
|
|
4706
|
+
* @returns Array of all activities present in the lookup map at call time.
|
|
4707
|
+
*/
|
|
4708
|
+
this.listActivity = () => {
|
|
4709
|
+
LOGGER_SERVICE$7.info(METHOD_NAME_LIST_ACTIVITY);
|
|
4710
|
+
return Array.from(this._lookupMap.values());
|
|
4711
|
+
};
|
|
4712
|
+
}
|
|
4713
|
+
/**
|
|
4714
|
+
* `true` when more than one activity is currently registered.
|
|
4715
|
+
* Used by `Candle.spinLock` to decide whether yielding the event loop is useful.
|
|
4716
|
+
*/
|
|
4717
|
+
get isParallel() {
|
|
4718
|
+
return this._lookupMap.size > 1;
|
|
4719
|
+
}
|
|
4720
|
+
}
|
|
4721
|
+
/**
|
|
4722
|
+
* Process-wide singleton instance of {@link LookupUtils}.
|
|
4723
|
+
* Imported by `Backtest`, `Live`, `WalkerLogicPrivateService` (registration sites)
|
|
4724
|
+
* and by `Candle` (read-only consumer via `isParallel`).
|
|
4725
|
+
*/
|
|
4726
|
+
const Lookup = new LookupUtils();
|
|
4727
|
+
|
|
4584
4728
|
const METHOD_NAME_ACQUIRE_LOCK = "CandleUtils.acquireLock";
|
|
4585
4729
|
const METHOD_NAME_RELEASE_LOCK = "CandleUtils.releaseLock";
|
|
4730
|
+
const METHOD_NAME_SPIN_LOCK = "CandleUtils.spinLock";
|
|
4731
|
+
/**
|
|
4732
|
+
* Upper bound (ms) on how long `spinLock` may park before falling through.
|
|
4733
|
+
* If no peer backtest acquires the candle-fetch mutex within this window,
|
|
4734
|
+
* the spinner proceeds without further yielding.
|
|
4735
|
+
*/
|
|
4736
|
+
const ROTATE_DELAY = 50;
|
|
4586
4737
|
/** Logger service injected as DI singleton */
|
|
4587
4738
|
const LOGGER_SERVICE$6 = new LoggerService();
|
|
4739
|
+
/**
|
|
4740
|
+
* Process-wide coordinator for candle-fetch serialization and cooperative
|
|
4741
|
+
* yielding between parallel backtests.
|
|
4742
|
+
*
|
|
4743
|
+
* Two complementary primitives are exposed:
|
|
4744
|
+
* - **Mutex** via {@link acquireLock} / {@link releaseLock}: prevents concurrent
|
|
4745
|
+
* candle fetches from racing on the same exchange.
|
|
4746
|
+
* - **Spin hand-off** via {@link spinLock}: invoked after a fetch completes to
|
|
4747
|
+
* give peer backtests waiting on the mutex a chance to run, so multiple
|
|
4748
|
+
* `Backtest.run` workloads interleave instead of one monopolizing the loop.
|
|
4749
|
+
*
|
|
4750
|
+
* All three operations are no-ops when `CC_ENABLE_CANDLE_FETCH_MUTEX` is `false`.
|
|
4751
|
+
* The spin additionally requires `CC_ENABLE_BACKTEST_PARALLEL_SPIN` and at least
|
|
4752
|
+
* two registered activities in `Lookup` (see `Lookup.isParallel`).
|
|
4753
|
+
*
|
|
4754
|
+
* @example
|
|
4755
|
+
* ```typescript
|
|
4756
|
+
* await Candle.acquireLock("ClientExchange GET_CANDLES_FN");
|
|
4757
|
+
* try {
|
|
4758
|
+
* const candles = await fetchFromExchange(...);
|
|
4759
|
+
* return candles;
|
|
4760
|
+
* } finally {
|
|
4761
|
+
* await Candle.releaseLock("ClientExchange GET_CANDLES_FN");
|
|
4762
|
+
* }
|
|
4763
|
+
* // Elsewhere, after a fetch completes inside a backtest loop:
|
|
4764
|
+
* await Candle.spinLock("BacktestLogicPrivateService GET_CANDLES_FN");
|
|
4765
|
+
* ```
|
|
4766
|
+
*/
|
|
4588
4767
|
class CandleUtils {
|
|
4589
4768
|
constructor() {
|
|
4769
|
+
/** Underlying mutex serializing candle fetches across concurrent callers. */
|
|
4590
4770
|
this._lock = new Lock();
|
|
4591
4771
|
/**
|
|
4592
|
-
*
|
|
4772
|
+
* Emits whenever {@link acquireLock} successfully takes the mutex.
|
|
4773
|
+
* Awaited by {@link spinLock} to detect that a peer backtest has just
|
|
4774
|
+
* started its own fetch — the signal that yielding now will be productive.
|
|
4775
|
+
*/
|
|
4776
|
+
this._spin = new Subject();
|
|
4777
|
+
/**
|
|
4778
|
+
* Acquires the candle fetch mutex if `CC_ENABLE_CANDLE_FETCH_MUTEX` is enabled.
|
|
4593
4779
|
* Prevents concurrent candle fetches from the same exchange.
|
|
4594
4780
|
*
|
|
4595
|
-
*
|
|
4781
|
+
* On successful acquisition, emits on the internal spin subject so any
|
|
4782
|
+
* peer parked inside {@link spinLock} can wake up and proceed.
|
|
4783
|
+
*
|
|
4784
|
+
* @param source - Caller identifier for logging.
|
|
4596
4785
|
*/
|
|
4597
4786
|
this.acquireLock = async (source) => {
|
|
4598
4787
|
LOGGER_SERVICE$6.info(METHOD_NAME_ACQUIRE_LOCK, {
|
|
@@ -4601,13 +4790,14 @@ class CandleUtils {
|
|
|
4601
4790
|
if (!GLOBAL_CONFIG.CC_ENABLE_CANDLE_FETCH_MUTEX) {
|
|
4602
4791
|
return;
|
|
4603
4792
|
}
|
|
4604
|
-
|
|
4793
|
+
await this._lock.acquireLock();
|
|
4794
|
+
await this._spin.next();
|
|
4605
4795
|
};
|
|
4606
4796
|
/**
|
|
4607
|
-
* Releases the candle fetch mutex if CC_ENABLE_CANDLE_FETCH_MUTEX is enabled.
|
|
4608
|
-
* Must be called after acquireLock, typically in a finally block.
|
|
4797
|
+
* Releases the candle fetch mutex if `CC_ENABLE_CANDLE_FETCH_MUTEX` is enabled.
|
|
4798
|
+
* Must be called after {@link acquireLock}, typically in a `finally` block.
|
|
4609
4799
|
*
|
|
4610
|
-
* @param source - Caller identifier for logging
|
|
4800
|
+
* @param source - Caller identifier for logging.
|
|
4611
4801
|
*/
|
|
4612
4802
|
this.releaseLock = async (source) => {
|
|
4613
4803
|
LOGGER_SERVICE$6.info(METHOD_NAME_RELEASE_LOCK, {
|
|
@@ -4618,8 +4808,47 @@ class CandleUtils {
|
|
|
4618
4808
|
}
|
|
4619
4809
|
return await this._lock.releaseLock();
|
|
4620
4810
|
};
|
|
4811
|
+
/**
|
|
4812
|
+
* Cooperative event-loop hand-off invoked by `BacktestLogicPrivateService`
|
|
4813
|
+
* after a successful `getNextCandles`. Allows peer backtests waiting on the
|
|
4814
|
+
* candle-fetch mutex to run before the current backtest fetches the next chunk.
|
|
4815
|
+
*
|
|
4816
|
+
* Waits for one of:
|
|
4817
|
+
* - a peer calling {@link acquireLock} (signalled via the spin subject), or
|
|
4818
|
+
* - a `ROTATE_DELAY` ms timeout, so the caller never parks indefinitely.
|
|
4819
|
+
*
|
|
4820
|
+
* Returns immediately as a no-op when any of these is true:
|
|
4821
|
+
* - `CC_ENABLE_CANDLE_FETCH_MUTEX` is disabled (mutex is off entirely),
|
|
4822
|
+
* - `CC_ENABLE_BACKTEST_PARALLEL_SPIN` is disabled (cooperative yielding off),
|
|
4823
|
+
* - `Lookup.isParallel` is `false` (only one active workload — no peer to yield to).
|
|
4824
|
+
*
|
|
4825
|
+
* @param source - Caller identifier for logging.
|
|
4826
|
+
*/
|
|
4827
|
+
this.spinLock = async (source) => {
|
|
4828
|
+
LOGGER_SERVICE$6.info(METHOD_NAME_SPIN_LOCK, {
|
|
4829
|
+
source,
|
|
4830
|
+
});
|
|
4831
|
+
if (!GLOBAL_CONFIG.CC_ENABLE_CANDLE_FETCH_MUTEX) {
|
|
4832
|
+
return;
|
|
4833
|
+
}
|
|
4834
|
+
if (!GLOBAL_CONFIG.CC_ENABLE_BACKTEST_PARALLEL_SPIN) {
|
|
4835
|
+
return;
|
|
4836
|
+
}
|
|
4837
|
+
if (!Lookup.isParallel) {
|
|
4838
|
+
return;
|
|
4839
|
+
}
|
|
4840
|
+
await Promise.race([
|
|
4841
|
+
this._spin.toPromise(),
|
|
4842
|
+
sleep(ROTATE_DELAY),
|
|
4843
|
+
]);
|
|
4844
|
+
};
|
|
4621
4845
|
}
|
|
4622
4846
|
}
|
|
4847
|
+
/**
|
|
4848
|
+
* Process-wide singleton instance of {@link CandleUtils}.
|
|
4849
|
+
* Imported by `ClientExchange` (mutex around exchange fetches) and by
|
|
4850
|
+
* `BacktestLogicPrivateService` (spin hand-off between parallel backtests).
|
|
4851
|
+
*/
|
|
4623
4852
|
const Candle = new CandleUtils();
|
|
4624
4853
|
|
|
4625
4854
|
const MS_PER_MINUTE$7 = 60000;
|
|
@@ -19153,9 +19382,28 @@ const TICK_FN = async (self, symbol, when) => {
|
|
|
19153
19382
|
return { type: "error", __error__: SYMBOL_FN_ERROR, reason: "TICK_FN", message: getErrorMessage(error) };
|
|
19154
19383
|
}
|
|
19155
19384
|
};
|
|
19385
|
+
/**
|
|
19386
|
+
* Wraps `exchangeCoreService.getNextCandles` with error capture and a cooperative
|
|
19387
|
+
* event-loop hand-off after a successful fetch.
|
|
19388
|
+
*
|
|
19389
|
+
* Calls `Candle.spinLock(...)` on success: when multiple backtests run in parallel
|
|
19390
|
+
* (`Lookup.isParallel === true`), this yields the event loop so a peer waiting on
|
|
19391
|
+
* the candle-fetch mutex can take its turn, producing round-robin interleaving
|
|
19392
|
+
* instead of one backtest monopolizing the loop until completion. The spin is a
|
|
19393
|
+
* no-op for single-workload runs.
|
|
19394
|
+
*
|
|
19395
|
+
* @param self - Owning service instance, used for logging and exchange access.
|
|
19396
|
+
* @param symbol - Trading pair symbol.
|
|
19397
|
+
* @param candlesNeeded - Number of 1m candles to request.
|
|
19398
|
+
* @param bufferStartTime - Inclusive start time for the fetch window.
|
|
19399
|
+
* @param logMeta - Extra structured fields appended to the warn log on failure.
|
|
19400
|
+
* @returns Fetched candles, or a {@link TFnError} discriminated union on failure.
|
|
19401
|
+
*/
|
|
19156
19402
|
const GET_CANDLES_FN = async (self, symbol, candlesNeeded, bufferStartTime, logMeta) => {
|
|
19157
19403
|
try {
|
|
19158
|
-
|
|
19404
|
+
const result = await self.exchangeCoreService.getNextCandles(symbol, "1m", candlesNeeded, bufferStartTime, true);
|
|
19405
|
+
await Candle.spinLock("BacktestLogicPrivateService GET_CANDLES_FN");
|
|
19406
|
+
return result;
|
|
19159
19407
|
}
|
|
19160
19408
|
catch (error) {
|
|
19161
19409
|
console.error(`backtestLogicPrivateService getNextCandles failed symbol=${symbol} strategyName=${self.methodContextService.context.strategyName} exchangeName=${self.methodContextService.context.exchangeName}`);
|
|
@@ -20041,6 +20289,15 @@ class WalkerLogicPrivateService {
|
|
|
20041
20289
|
exchangeName: context.exchangeName,
|
|
20042
20290
|
frameName: context.frameName,
|
|
20043
20291
|
});
|
|
20292
|
+
Lookup.addActivity({
|
|
20293
|
+
symbol,
|
|
20294
|
+
context: {
|
|
20295
|
+
strategyName,
|
|
20296
|
+
exchangeName: context.exchangeName,
|
|
20297
|
+
frameName: context.frameName,
|
|
20298
|
+
},
|
|
20299
|
+
backtest: true,
|
|
20300
|
+
});
|
|
20044
20301
|
try {
|
|
20045
20302
|
await resolveDocuments(iterator);
|
|
20046
20303
|
}
|
|
@@ -20056,6 +20313,17 @@ class WalkerLogicPrivateService {
|
|
|
20056
20313
|
await CALL_STRATEGY_ERROR_CALLBACKS_FN(this, walkerSchema, strategyName, symbol, error);
|
|
20057
20314
|
continue;
|
|
20058
20315
|
}
|
|
20316
|
+
finally {
|
|
20317
|
+
Lookup.removeActivity({
|
|
20318
|
+
symbol,
|
|
20319
|
+
context: {
|
|
20320
|
+
strategyName,
|
|
20321
|
+
exchangeName: context.exchangeName,
|
|
20322
|
+
frameName: context.frameName,
|
|
20323
|
+
},
|
|
20324
|
+
backtest: true,
|
|
20325
|
+
});
|
|
20326
|
+
}
|
|
20059
20327
|
this.loggerService.info("walkerLogicPrivateService backtest complete", {
|
|
20060
20328
|
strategyName,
|
|
20061
20329
|
symbol,
|
|
@@ -36075,6 +36343,7 @@ const Exchange = new ExchangeUtils();
|
|
|
36075
36343
|
|
|
36076
36344
|
const WARM_CANDLES_METHOD_NAME = "cache.warmCandles";
|
|
36077
36345
|
const CHECK_CANDLES_METHOD_NAME = "cache.checkCandles";
|
|
36346
|
+
const CACHE_CANDLES_METHOD_NAME = "cache.cacheCandles";
|
|
36078
36347
|
const MS_PER_MINUTE$3 = 60000;
|
|
36079
36348
|
const INTERVAL_MINUTES$3 = {
|
|
36080
36349
|
"1m": 1,
|
|
@@ -36106,6 +36375,34 @@ const PRINT_PROGRESS_FN = (fetched, total, symbol, interval) => {
|
|
|
36106
36375
|
process.stdout.write("\n");
|
|
36107
36376
|
}
|
|
36108
36377
|
};
|
|
36378
|
+
/**
|
|
36379
|
+
* Retry-wrapped pipeline: validates the cache via `checkCandles` and, on miss,
|
|
36380
|
+
* fills it via `warmCandles` and rethrows to trigger a retry pass that
|
|
36381
|
+
* re-validates the freshly cached range. Limited to 2 attempts.
|
|
36382
|
+
*/
|
|
36383
|
+
const CACHE_CANDLES_FN = retry(async (interval, dto, onWarmStart, onCheckStart) => {
|
|
36384
|
+
try {
|
|
36385
|
+
onWarmStart && onWarmStart(dto.symbol, interval, dto.from, dto.to);
|
|
36386
|
+
await checkCandles({
|
|
36387
|
+
exchangeName: dto.exchangeName,
|
|
36388
|
+
from: dto.from,
|
|
36389
|
+
to: dto.to,
|
|
36390
|
+
symbol: dto.symbol,
|
|
36391
|
+
interval: interval,
|
|
36392
|
+
});
|
|
36393
|
+
}
|
|
36394
|
+
catch (error) {
|
|
36395
|
+
onCheckStart && onCheckStart(dto.symbol, interval, dto.from, dto.to);
|
|
36396
|
+
await warmCandles({
|
|
36397
|
+
symbol: dto.symbol,
|
|
36398
|
+
exchangeName: dto.exchangeName,
|
|
36399
|
+
from: dto.from,
|
|
36400
|
+
to: dto.to,
|
|
36401
|
+
interval: interval,
|
|
36402
|
+
});
|
|
36403
|
+
throw error;
|
|
36404
|
+
}
|
|
36405
|
+
}, 2);
|
|
36109
36406
|
/**
|
|
36110
36407
|
* Checks cached candle presence via the persist adapter.
|
|
36111
36408
|
* Issues one ranged read; adapter-side `hasValue` covers each expected timestamp,
|
|
@@ -36181,6 +36478,34 @@ async function warmCandles(params) {
|
|
|
36181
36478
|
PRINT_PROGRESS_FN(fetched, totalCandles, symbol, interval);
|
|
36182
36479
|
}
|
|
36183
36480
|
}
|
|
36481
|
+
/**
|
|
36482
|
+
* Ensures candles for the given range are present in persist storage.
|
|
36483
|
+
* Runs a check-then-warm pipeline with one retry: validates the cache first
|
|
36484
|
+
* and, on a miss, downloads the missing data and re-validates.
|
|
36485
|
+
*
|
|
36486
|
+
* @param params - Combined cache parameters with optional lifecycle callbacks
|
|
36487
|
+
*/
|
|
36488
|
+
async function cacheCandles({ symbol, interval, from, to, exchangeName, onCheckStart = (symbol, interval, from, to) => {
|
|
36489
|
+
process.stdout.write("\n");
|
|
36490
|
+
process.stdout.write(`Checking candles cache for ${symbol} ${interval} from ${from} to ${to}\n`);
|
|
36491
|
+
}, onWarmStart = (symbol, interval, from, to) => {
|
|
36492
|
+
process.stdout.write("\n\n");
|
|
36493
|
+
process.stdout.write(`Caching candles for ${symbol} ${interval} from ${from} to ${to}\n`);
|
|
36494
|
+
}, }) {
|
|
36495
|
+
backtest.loggerService.info(CACHE_CANDLES_METHOD_NAME, {
|
|
36496
|
+
symbol,
|
|
36497
|
+
exchangeName,
|
|
36498
|
+
interval,
|
|
36499
|
+
from,
|
|
36500
|
+
to,
|
|
36501
|
+
});
|
|
36502
|
+
await CACHE_CANDLES_FN(interval, {
|
|
36503
|
+
exchangeName,
|
|
36504
|
+
from,
|
|
36505
|
+
to,
|
|
36506
|
+
symbol,
|
|
36507
|
+
}, onWarmStart, onCheckStart);
|
|
36508
|
+
}
|
|
36184
36509
|
|
|
36185
36510
|
const METHOD_NAME = "validate.validate";
|
|
36186
36511
|
/**
|
|
@@ -41966,11 +42291,21 @@ const INSTANCE_TASK_FN$2 = async (symbol, context, self) => {
|
|
|
41966
42291
|
self._isStopped = false;
|
|
41967
42292
|
self._isDone = false;
|
|
41968
42293
|
}
|
|
42294
|
+
Lookup.addActivity({
|
|
42295
|
+
symbol,
|
|
42296
|
+
context,
|
|
42297
|
+
backtest: true,
|
|
42298
|
+
});
|
|
41969
42299
|
for await (const _ of self.run(symbol, context)) {
|
|
41970
42300
|
if (self._isStopped) {
|
|
41971
42301
|
break;
|
|
41972
42302
|
}
|
|
41973
42303
|
}
|
|
42304
|
+
Lookup.removeActivity({
|
|
42305
|
+
symbol,
|
|
42306
|
+
context,
|
|
42307
|
+
backtest: true,
|
|
42308
|
+
});
|
|
41974
42309
|
if (!self._isDone) {
|
|
41975
42310
|
await doneBacktestSubject.next({
|
|
41976
42311
|
exchangeName: context.exchangeName,
|
|
@@ -44617,11 +44952,21 @@ const INSTANCE_TASK_FN$1 = async (symbol, context, self) => {
|
|
|
44617
44952
|
self._isStopped = false;
|
|
44618
44953
|
self._isDone = false;
|
|
44619
44954
|
}
|
|
44955
|
+
Lookup.addActivity({
|
|
44956
|
+
symbol,
|
|
44957
|
+
context,
|
|
44958
|
+
backtest: false,
|
|
44959
|
+
});
|
|
44620
44960
|
for await (const signal of self.run(symbol, context)) {
|
|
44621
44961
|
if (signal?.action === "closed" && self._isStopped) {
|
|
44622
44962
|
break;
|
|
44623
44963
|
}
|
|
44624
44964
|
}
|
|
44965
|
+
Lookup.removeActivity({
|
|
44966
|
+
symbol,
|
|
44967
|
+
context,
|
|
44968
|
+
backtest: false,
|
|
44969
|
+
});
|
|
44625
44970
|
if (!self._isDone) {
|
|
44626
44971
|
await doneLiveSubject.next({
|
|
44627
44972
|
exchangeName: context.exchangeName,
|
|
@@ -63732,4 +64077,4 @@ const validateSignal = (signal, currentPrice) => {
|
|
|
63732
64077
|
return !errors.length;
|
|
63733
64078
|
};
|
|
63734
64079
|
|
|
63735
|
-
export { ActionBase, Backtest, Breakeven, Broker, BrokerBase, Cache, Constant, Dump, Exchange, ExecutionContextService, Heat, HighestProfit, Interval, Live, Log, Markdown, MarkdownFileBase, MarkdownFolderBase, MarkdownWriter, MaxDrawdown, Memory, MemoryBacktest, MemoryBacktestAdapter, MemoryLive, MemoryLiveAdapter, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistBreakevenInstance, PersistCandleAdapter, PersistCandleInstance, PersistIntervalAdapter, PersistIntervalInstance, PersistLogAdapter, PersistLogInstance, PersistMeasureAdapter, PersistMeasureInstance, PersistMemoryAdapter, PersistMemoryInstance, PersistNotificationAdapter, PersistNotificationInstance, PersistPartialAdapter, PersistPartialInstance, PersistRecentAdapter, PersistRecentInstance, PersistRiskAdapter, PersistRiskInstance, PersistScheduleAdapter, PersistScheduleInstance, PersistSessionAdapter, PersistSessionInstance, PersistSignalAdapter, PersistSignalInstance, PersistStateAdapter, PersistStateInstance, PersistStorageAdapter, PersistStorageInstance, Position, PositionSize, Recent, RecentBacktest, RecentLive, Reflect$1 as Reflect, Report, ReportBase, ReportWriter, Risk, Schedule, Session, SessionBacktest, SessionLive, State, StateBacktest, StateBacktestAdapter, StateLive, StateLiveAdapter, Storage, StorageBacktest, StorageLive, Strategy, Sync, System, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialLossCost, commitPartialProfit, commitPartialProfitCost, commitSignalNotify, commitTrailingStop, commitTrailingStopCost, commitTrailingTake, commitTrailingTakeCost, createSignalState, dumpAgentAnswer, dumpError, dumpJson, dumpRecord, dumpTable, dumpText, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getBreakeven, getCandles, getClosePrice, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getEffectivePriceOpen, getExchangeSchema, getFrameSchema, getLatestSignal, getMaxDrawdownDistancePnlCost, getMaxDrawdownDistancePnlPercentage, getMinutesSinceLatestSignalCreated, getMode, getNextCandles, getOrderBook, getPendingSignal, getPositionActiveMinutes, getPositionCountdownMinutes, getPositionDrawdownMinutes, getPositionEffectivePrice, getPositionEntries, getPositionEntryOverlap, getPositionEstimateMinutes, getPositionHighestMaxDrawdownPnlCost, getPositionHighestMaxDrawdownPnlPercentage, getPositionHighestPnlCost, getPositionHighestPnlPercentage, getPositionHighestProfitBreakeven, getPositionHighestProfitDistancePnlCost, getPositionHighestProfitDistancePnlPercentage, getPositionHighestProfitMinutes, getPositionHighestProfitPrice, getPositionHighestProfitTimestamp, getPositionInvestedCost, getPositionInvestedCount, getPositionLevels, getPositionMaxDrawdownMinutes, getPositionMaxDrawdownPnlCost, getPositionMaxDrawdownPnlPercentage, getPositionMaxDrawdownPrice, getPositionMaxDrawdownTimestamp, getPositionPartialOverlap, getPositionPartials, getPositionPnlCost, getPositionPnlPercent, getPositionWaitingMinutes, getRawCandles, getRiskSchema, getScheduledSignal, getSessionData, getSignalState, getSizingSchema, getStrategySchema, getSymbol, getTimestamp, getTotalClosed, getTotalCostClosed, getTotalPercentClosed, getWalkerSchema, hasNoPendingSignal, hasNoScheduledSignal, hasTradeContext, intervalStepMs, investedCostToPercent, backtest as lib, listExchangeSchema, listFrameSchema, listMemory, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenHighestProfit, listenHighestProfitOnce, listenIdlePing, listenIdlePingOnce, listenMaxDrawdown, listenMaxDrawdownOnce, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalNotify, listenSignalNotifyOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenSync, listenSyncOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, percentDiff, percentToCloseCost, percentValue, readMemory, removeMemory, roundTicks, runInMockContext, searchMemory, set, setColumns, setConfig, setLogger, setSessionData, setSignalState, shutdown, slPercentShiftToPrice, slPriceToPercentShift, stopStrategy, toProfitLossDto, tpPercentShiftToPrice, tpPriceToPercentShift, validate, validateCommonSignal, validatePendingSignal, validateScheduledSignal, validateSignal, waitForCandle, waitForReady, warmCandles, writeMemory };
|
|
64080
|
+
export { ActionBase, Backtest, Breakeven, Broker, BrokerBase, Cache, Constant, Dump, Exchange, ExecutionContextService, Heat, HighestProfit, Interval, Live, Log, Lookup, Markdown, MarkdownFileBase, MarkdownFolderBase, MarkdownWriter, MaxDrawdown, Memory, MemoryBacktest, MemoryBacktestAdapter, MemoryLive, MemoryLiveAdapter, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistBreakevenInstance, PersistCandleAdapter, PersistCandleInstance, PersistIntervalAdapter, PersistIntervalInstance, PersistLogAdapter, PersistLogInstance, PersistMeasureAdapter, PersistMeasureInstance, PersistMemoryAdapter, PersistMemoryInstance, PersistNotificationAdapter, PersistNotificationInstance, PersistPartialAdapter, PersistPartialInstance, PersistRecentAdapter, PersistRecentInstance, PersistRiskAdapter, PersistRiskInstance, PersistScheduleAdapter, PersistScheduleInstance, PersistSessionAdapter, PersistSessionInstance, PersistSignalAdapter, PersistSignalInstance, PersistStateAdapter, PersistStateInstance, PersistStorageAdapter, PersistStorageInstance, Position, PositionSize, Recent, RecentBacktest, RecentLive, Reflect$1 as Reflect, Report, ReportBase, ReportWriter, Risk, Schedule, Session, SessionBacktest, SessionLive, State, StateBacktest, StateBacktestAdapter, StateLive, StateLiveAdapter, Storage, StorageBacktest, StorageLive, Strategy, Sync, System, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, cacheCandles, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialLossCost, commitPartialProfit, commitPartialProfitCost, commitSignalNotify, commitTrailingStop, commitTrailingStopCost, commitTrailingTake, commitTrailingTakeCost, createSignalState, dumpAgentAnswer, dumpError, dumpJson, dumpRecord, dumpTable, dumpText, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getBreakeven, getCandles, getClosePrice, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getEffectivePriceOpen, getExchangeSchema, getFrameSchema, getLatestSignal, getMaxDrawdownDistancePnlCost, getMaxDrawdownDistancePnlPercentage, getMinutesSinceLatestSignalCreated, getMode, getNextCandles, getOrderBook, getPendingSignal, getPositionActiveMinutes, getPositionCountdownMinutes, getPositionDrawdownMinutes, getPositionEffectivePrice, getPositionEntries, getPositionEntryOverlap, getPositionEstimateMinutes, getPositionHighestMaxDrawdownPnlCost, getPositionHighestMaxDrawdownPnlPercentage, getPositionHighestPnlCost, getPositionHighestPnlPercentage, getPositionHighestProfitBreakeven, getPositionHighestProfitDistancePnlCost, getPositionHighestProfitDistancePnlPercentage, getPositionHighestProfitMinutes, getPositionHighestProfitPrice, getPositionHighestProfitTimestamp, getPositionInvestedCost, getPositionInvestedCount, getPositionLevels, getPositionMaxDrawdownMinutes, getPositionMaxDrawdownPnlCost, getPositionMaxDrawdownPnlPercentage, getPositionMaxDrawdownPrice, getPositionMaxDrawdownTimestamp, getPositionPartialOverlap, getPositionPartials, getPositionPnlCost, getPositionPnlPercent, getPositionWaitingMinutes, getRawCandles, getRiskSchema, getScheduledSignal, getSessionData, getSignalState, getSizingSchema, getStrategySchema, getSymbol, getTimestamp, getTotalClosed, getTotalCostClosed, getTotalPercentClosed, getWalkerSchema, hasNoPendingSignal, hasNoScheduledSignal, hasTradeContext, intervalStepMs, investedCostToPercent, backtest as lib, listExchangeSchema, listFrameSchema, listMemory, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenHighestProfit, listenHighestProfitOnce, listenIdlePing, listenIdlePingOnce, listenMaxDrawdown, listenMaxDrawdownOnce, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalNotify, listenSignalNotifyOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenSync, listenSyncOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, percentDiff, percentToCloseCost, percentValue, readMemory, removeMemory, roundTicks, runInMockContext, searchMemory, set, setColumns, setConfig, setLogger, setSessionData, setSignalState, shutdown, slPercentShiftToPrice, slPriceToPercentShift, stopStrategy, toProfitLossDto, tpPercentShiftToPrice, tpPriceToPercentShift, validate, validateCommonSignal, validatePendingSignal, validateScheduledSignal, validateSignal, waitForCandle, waitForReady, warmCandles, writeMemory };
|