backtest-kit 9.8.4 → 10.1.0
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/README.md +98 -1
- package/build/index.cjs +669 -177
- package/build/index.mjs +666 -178
- package/package.json +1 -1
- package/types.d.ts +481 -1
package/build/index.cjs
CHANGED
|
@@ -962,7 +962,7 @@ async function writeFileAtomic(file, data, options = {}) {
|
|
|
962
962
|
|
|
963
963
|
var _a$3;
|
|
964
964
|
/** Logger service injected as DI singleton */
|
|
965
|
-
const LOGGER_SERVICE$
|
|
965
|
+
const LOGGER_SERVICE$9 = new LoggerService();
|
|
966
966
|
/** Symbol key for the singleshot waitForInit function on PersistBase instances. */
|
|
967
967
|
const BASE_WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
|
|
968
968
|
// Calculate step in milliseconds for candle close time validation
|
|
@@ -1085,7 +1085,7 @@ const BASE_WAIT_FOR_INIT_FN_METHOD_NAME = "PersistBase.waitForInitFn";
|
|
|
1085
1085
|
const BASE_UNLINK_RETRY_COUNT = 5;
|
|
1086
1086
|
const BASE_UNLINK_RETRY_DELAY = 1000;
|
|
1087
1087
|
const BASE_WAIT_FOR_INIT_FN = async (self) => {
|
|
1088
|
-
LOGGER_SERVICE$
|
|
1088
|
+
LOGGER_SERVICE$9.debug(BASE_WAIT_FOR_INIT_FN_METHOD_NAME, {
|
|
1089
1089
|
entityName: self.entityName,
|
|
1090
1090
|
directory: self._directory,
|
|
1091
1091
|
});
|
|
@@ -1143,7 +1143,7 @@ class PersistBase {
|
|
|
1143
1143
|
this.entityName = entityName;
|
|
1144
1144
|
this.baseDir = baseDir;
|
|
1145
1145
|
this[_a$3] = functoolsKit.singleshot(async () => await BASE_WAIT_FOR_INIT_FN(this));
|
|
1146
|
-
LOGGER_SERVICE$
|
|
1146
|
+
LOGGER_SERVICE$9.debug(PERSIST_BASE_METHOD_NAME_CTOR, {
|
|
1147
1147
|
entityName: this.entityName,
|
|
1148
1148
|
baseDir,
|
|
1149
1149
|
});
|
|
@@ -1159,14 +1159,14 @@ class PersistBase {
|
|
|
1159
1159
|
return path.join(this.baseDir, this.entityName, `${entityId}.json`);
|
|
1160
1160
|
}
|
|
1161
1161
|
async waitForInit(initial) {
|
|
1162
|
-
LOGGER_SERVICE$
|
|
1162
|
+
LOGGER_SERVICE$9.debug(PERSIST_BASE_METHOD_NAME_WAIT_FOR_INIT, {
|
|
1163
1163
|
entityName: this.entityName,
|
|
1164
1164
|
initial,
|
|
1165
1165
|
});
|
|
1166
1166
|
await this[BASE_WAIT_FOR_INIT_SYMBOL]();
|
|
1167
1167
|
}
|
|
1168
1168
|
async readValue(entityId) {
|
|
1169
|
-
LOGGER_SERVICE$
|
|
1169
|
+
LOGGER_SERVICE$9.debug(PERSIST_BASE_METHOD_NAME_READ_VALUE, {
|
|
1170
1170
|
entityName: this.entityName,
|
|
1171
1171
|
entityId,
|
|
1172
1172
|
});
|
|
@@ -1183,7 +1183,7 @@ class PersistBase {
|
|
|
1183
1183
|
}
|
|
1184
1184
|
}
|
|
1185
1185
|
async hasValue(entityId) {
|
|
1186
|
-
LOGGER_SERVICE$
|
|
1186
|
+
LOGGER_SERVICE$9.debug(PERSIST_BASE_METHOD_NAME_HAS_VALUE, {
|
|
1187
1187
|
entityName: this.entityName,
|
|
1188
1188
|
entityId,
|
|
1189
1189
|
});
|
|
@@ -1200,7 +1200,7 @@ class PersistBase {
|
|
|
1200
1200
|
}
|
|
1201
1201
|
}
|
|
1202
1202
|
async writeValue(entityId, entity) {
|
|
1203
|
-
LOGGER_SERVICE$
|
|
1203
|
+
LOGGER_SERVICE$9.debug(PERSIST_BASE_METHOD_NAME_WRITE_VALUE, {
|
|
1204
1204
|
entityName: this.entityName,
|
|
1205
1205
|
entityId,
|
|
1206
1206
|
});
|
|
@@ -1222,7 +1222,7 @@ class PersistBase {
|
|
|
1222
1222
|
* @throws Error if reading fails
|
|
1223
1223
|
*/
|
|
1224
1224
|
async *keys() {
|
|
1225
|
-
LOGGER_SERVICE$
|
|
1225
|
+
LOGGER_SERVICE$9.debug(PERSIST_BASE_METHOD_NAME_KEYS, {
|
|
1226
1226
|
entityName: this.entityName,
|
|
1227
1227
|
});
|
|
1228
1228
|
try {
|
|
@@ -1367,7 +1367,7 @@ class PersistSignalUtils {
|
|
|
1367
1367
|
* @returns Promise resolving to signal or null if none persisted
|
|
1368
1368
|
*/
|
|
1369
1369
|
this.readSignalData = async (symbol, strategyName, exchangeName) => {
|
|
1370
|
-
LOGGER_SERVICE$
|
|
1370
|
+
LOGGER_SERVICE$9.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_READ_DATA);
|
|
1371
1371
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1372
1372
|
const isInitial = !this.getStorage.has(key);
|
|
1373
1373
|
const instance = this.getStorage(symbol, strategyName, exchangeName);
|
|
@@ -1385,7 +1385,7 @@ class PersistSignalUtils {
|
|
|
1385
1385
|
* @returns Promise that resolves when write is complete
|
|
1386
1386
|
*/
|
|
1387
1387
|
this.writeSignalData = async (signalRow, symbol, strategyName, exchangeName) => {
|
|
1388
|
-
LOGGER_SERVICE$
|
|
1388
|
+
LOGGER_SERVICE$9.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1389
1389
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1390
1390
|
const isInitial = !this.getStorage.has(key);
|
|
1391
1391
|
const instance = this.getStorage(symbol, strategyName, exchangeName);
|
|
@@ -1400,7 +1400,7 @@ class PersistSignalUtils {
|
|
|
1400
1400
|
* @param Ctor - Custom IPersistSignalInstance constructor
|
|
1401
1401
|
*/
|
|
1402
1402
|
usePersistSignalAdapter(Ctor) {
|
|
1403
|
-
LOGGER_SERVICE$
|
|
1403
|
+
LOGGER_SERVICE$9.info(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_PERSIST_SIGNAL_ADAPTER);
|
|
1404
1404
|
this.PersistSignalInstanceCtor = Ctor;
|
|
1405
1405
|
this.getStorage.clear();
|
|
1406
1406
|
}
|
|
@@ -1409,21 +1409,21 @@ class PersistSignalUtils {
|
|
|
1409
1409
|
* Call when process.cwd() changes between strategy iterations.
|
|
1410
1410
|
*/
|
|
1411
1411
|
clear() {
|
|
1412
|
-
LOGGER_SERVICE$
|
|
1412
|
+
LOGGER_SERVICE$9.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_CLEAR);
|
|
1413
1413
|
this.getStorage.clear();
|
|
1414
1414
|
}
|
|
1415
1415
|
/**
|
|
1416
1416
|
* Switches to the default file-based PersistSignalInstance.
|
|
1417
1417
|
*/
|
|
1418
1418
|
useJson() {
|
|
1419
|
-
LOGGER_SERVICE$
|
|
1419
|
+
LOGGER_SERVICE$9.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_JSON);
|
|
1420
1420
|
this.usePersistSignalAdapter(PersistSignalInstance);
|
|
1421
1421
|
}
|
|
1422
1422
|
/**
|
|
1423
1423
|
* Switches to PersistSignalDummyInstance (all operations are no-ops).
|
|
1424
1424
|
*/
|
|
1425
1425
|
useDummy() {
|
|
1426
|
-
LOGGER_SERVICE$
|
|
1426
|
+
LOGGER_SERVICE$9.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1427
1427
|
this.usePersistSignalAdapter(PersistSignalDummyInstance);
|
|
1428
1428
|
}
|
|
1429
1429
|
}
|
|
@@ -1563,7 +1563,7 @@ class PersistRiskUtils {
|
|
|
1563
1563
|
* @returns Promise resolving to position entries (empty array if none)
|
|
1564
1564
|
*/
|
|
1565
1565
|
this.readPositionData = async (riskName, exchangeName, when) => {
|
|
1566
|
-
LOGGER_SERVICE$
|
|
1566
|
+
LOGGER_SERVICE$9.info(PERSIST_RISK_UTILS_METHOD_NAME_READ_DATA);
|
|
1567
1567
|
const key = `${riskName}:${exchangeName}`;
|
|
1568
1568
|
const isInitial = !this.getRiskStorage.has(key);
|
|
1569
1569
|
const instance = this.getRiskStorage(riskName, exchangeName);
|
|
@@ -1581,7 +1581,7 @@ class PersistRiskUtils {
|
|
|
1581
1581
|
* @returns Promise that resolves when write is complete
|
|
1582
1582
|
*/
|
|
1583
1583
|
this.writePositionData = async (riskRow, riskName, exchangeName, when) => {
|
|
1584
|
-
LOGGER_SERVICE$
|
|
1584
|
+
LOGGER_SERVICE$9.info(PERSIST_RISK_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1585
1585
|
const key = `${riskName}:${exchangeName}`;
|
|
1586
1586
|
const isInitial = !this.getRiskStorage.has(key);
|
|
1587
1587
|
const instance = this.getRiskStorage(riskName, exchangeName);
|
|
@@ -1596,7 +1596,7 @@ class PersistRiskUtils {
|
|
|
1596
1596
|
* @param Ctor - Custom IPersistRiskInstance constructor
|
|
1597
1597
|
*/
|
|
1598
1598
|
usePersistRiskAdapter(Ctor) {
|
|
1599
|
-
LOGGER_SERVICE$
|
|
1599
|
+
LOGGER_SERVICE$9.info(PERSIST_RISK_UTILS_METHOD_NAME_USE_PERSIST_RISK_ADAPTER);
|
|
1600
1600
|
this.PersistRiskInstanceCtor = Ctor;
|
|
1601
1601
|
this.getRiskStorage.clear();
|
|
1602
1602
|
}
|
|
@@ -1605,21 +1605,21 @@ class PersistRiskUtils {
|
|
|
1605
1605
|
* Call when process.cwd() changes between strategy iterations.
|
|
1606
1606
|
*/
|
|
1607
1607
|
clear() {
|
|
1608
|
-
LOGGER_SERVICE$
|
|
1608
|
+
LOGGER_SERVICE$9.log(PERSIST_RISK_UTILS_METHOD_NAME_CLEAR);
|
|
1609
1609
|
this.getRiskStorage.clear();
|
|
1610
1610
|
}
|
|
1611
1611
|
/**
|
|
1612
1612
|
* Switches to the default file-based PersistRiskInstance.
|
|
1613
1613
|
*/
|
|
1614
1614
|
useJson() {
|
|
1615
|
-
LOGGER_SERVICE$
|
|
1615
|
+
LOGGER_SERVICE$9.log(PERSIST_RISK_UTILS_METHOD_NAME_USE_JSON);
|
|
1616
1616
|
this.usePersistRiskAdapter(PersistRiskInstance);
|
|
1617
1617
|
}
|
|
1618
1618
|
/**
|
|
1619
1619
|
* Switches to PersistRiskDummyInstance (all operations are no-ops).
|
|
1620
1620
|
*/
|
|
1621
1621
|
useDummy() {
|
|
1622
|
-
LOGGER_SERVICE$
|
|
1622
|
+
LOGGER_SERVICE$9.log(PERSIST_RISK_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1623
1623
|
this.usePersistRiskAdapter(PersistRiskDummyInstance);
|
|
1624
1624
|
}
|
|
1625
1625
|
}
|
|
@@ -1758,7 +1758,7 @@ class PersistScheduleUtils {
|
|
|
1758
1758
|
* @returns Promise resolving to scheduled signal or null if none persisted
|
|
1759
1759
|
*/
|
|
1760
1760
|
this.readScheduleData = async (symbol, strategyName, exchangeName) => {
|
|
1761
|
-
LOGGER_SERVICE$
|
|
1761
|
+
LOGGER_SERVICE$9.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_READ_DATA);
|
|
1762
1762
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1763
1763
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
1764
1764
|
const instance = this.getScheduleStorage(symbol, strategyName, exchangeName);
|
|
@@ -1776,7 +1776,7 @@ class PersistScheduleUtils {
|
|
|
1776
1776
|
* @returns Promise that resolves when write is complete
|
|
1777
1777
|
*/
|
|
1778
1778
|
this.writeScheduleData = async (scheduledSignalRow, symbol, strategyName, exchangeName) => {
|
|
1779
|
-
LOGGER_SERVICE$
|
|
1779
|
+
LOGGER_SERVICE$9.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1780
1780
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1781
1781
|
const isInitial = !this.getScheduleStorage.has(key);
|
|
1782
1782
|
const instance = this.getScheduleStorage(symbol, strategyName, exchangeName);
|
|
@@ -1791,7 +1791,7 @@ class PersistScheduleUtils {
|
|
|
1791
1791
|
* @param Ctor - Custom IPersistScheduleInstance constructor
|
|
1792
1792
|
*/
|
|
1793
1793
|
usePersistScheduleAdapter(Ctor) {
|
|
1794
|
-
LOGGER_SERVICE$
|
|
1794
|
+
LOGGER_SERVICE$9.info(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_PERSIST_SCHEDULE_ADAPTER);
|
|
1795
1795
|
this.PersistScheduleInstanceCtor = Ctor;
|
|
1796
1796
|
this.getScheduleStorage.clear();
|
|
1797
1797
|
}
|
|
@@ -1800,21 +1800,21 @@ class PersistScheduleUtils {
|
|
|
1800
1800
|
* Call when process.cwd() changes between strategy iterations.
|
|
1801
1801
|
*/
|
|
1802
1802
|
clear() {
|
|
1803
|
-
LOGGER_SERVICE$
|
|
1803
|
+
LOGGER_SERVICE$9.log(PERSIST_SCHEDULE_UTILS_METHOD_NAME_CLEAR);
|
|
1804
1804
|
this.getScheduleStorage.clear();
|
|
1805
1805
|
}
|
|
1806
1806
|
/**
|
|
1807
1807
|
* Switches to the default file-based PersistScheduleInstance.
|
|
1808
1808
|
*/
|
|
1809
1809
|
useJson() {
|
|
1810
|
-
LOGGER_SERVICE$
|
|
1810
|
+
LOGGER_SERVICE$9.log(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_JSON);
|
|
1811
1811
|
this.usePersistScheduleAdapter(PersistScheduleInstance);
|
|
1812
1812
|
}
|
|
1813
1813
|
/**
|
|
1814
1814
|
* Switches to PersistScheduleDummyInstance (all operations are no-ops).
|
|
1815
1815
|
*/
|
|
1816
1816
|
useDummy() {
|
|
1817
|
-
LOGGER_SERVICE$
|
|
1817
|
+
LOGGER_SERVICE$9.log(PERSIST_SCHEDULE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
1818
1818
|
this.usePersistScheduleAdapter(PersistScheduleDummyInstance);
|
|
1819
1819
|
}
|
|
1820
1820
|
}
|
|
@@ -1959,7 +1959,7 @@ class PersistPartialUtils {
|
|
|
1959
1959
|
* @returns Promise resolving to partial data record (empty object if none)
|
|
1960
1960
|
*/
|
|
1961
1961
|
this.readPartialData = async (symbol, strategyName, signalId, exchangeName, when) => {
|
|
1962
|
-
LOGGER_SERVICE$
|
|
1962
|
+
LOGGER_SERVICE$9.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_READ_DATA);
|
|
1963
1963
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1964
1964
|
const isInitial = !this.getPartialStorage.has(key);
|
|
1965
1965
|
const instance = this.getPartialStorage(symbol, strategyName, exchangeName);
|
|
@@ -1979,7 +1979,7 @@ class PersistPartialUtils {
|
|
|
1979
1979
|
* @returns Promise that resolves when write is complete
|
|
1980
1980
|
*/
|
|
1981
1981
|
this.writePartialData = async (partialData, symbol, strategyName, signalId, exchangeName, when) => {
|
|
1982
|
-
LOGGER_SERVICE$
|
|
1982
|
+
LOGGER_SERVICE$9.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_WRITE_DATA);
|
|
1983
1983
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
1984
1984
|
const isInitial = !this.getPartialStorage.has(key);
|
|
1985
1985
|
const instance = this.getPartialStorage(symbol, strategyName, exchangeName);
|
|
@@ -1994,7 +1994,7 @@ class PersistPartialUtils {
|
|
|
1994
1994
|
* @param Ctor - Custom IPersistPartialInstance constructor
|
|
1995
1995
|
*/
|
|
1996
1996
|
usePersistPartialAdapter(Ctor) {
|
|
1997
|
-
LOGGER_SERVICE$
|
|
1997
|
+
LOGGER_SERVICE$9.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_PERSIST_PARTIAL_ADAPTER);
|
|
1998
1998
|
this.PersistPartialInstanceCtor = Ctor;
|
|
1999
1999
|
this.getPartialStorage.clear();
|
|
2000
2000
|
}
|
|
@@ -2003,21 +2003,21 @@ class PersistPartialUtils {
|
|
|
2003
2003
|
* Call when process.cwd() changes between strategy iterations.
|
|
2004
2004
|
*/
|
|
2005
2005
|
clear() {
|
|
2006
|
-
LOGGER_SERVICE$
|
|
2006
|
+
LOGGER_SERVICE$9.log(PERSIST_PARTIAL_UTILS_METHOD_NAME_CLEAR);
|
|
2007
2007
|
this.getPartialStorage.clear();
|
|
2008
2008
|
}
|
|
2009
2009
|
/**
|
|
2010
2010
|
* Switches to the default file-based PersistPartialInstance.
|
|
2011
2011
|
*/
|
|
2012
2012
|
useJson() {
|
|
2013
|
-
LOGGER_SERVICE$
|
|
2013
|
+
LOGGER_SERVICE$9.log(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_JSON);
|
|
2014
2014
|
this.usePersistPartialAdapter(PersistPartialInstance);
|
|
2015
2015
|
}
|
|
2016
2016
|
/**
|
|
2017
2017
|
* Switches to PersistPartialDummyInstance (all operations are no-ops).
|
|
2018
2018
|
*/
|
|
2019
2019
|
useDummy() {
|
|
2020
|
-
LOGGER_SERVICE$
|
|
2020
|
+
LOGGER_SERVICE$9.log(PERSIST_PARTIAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2021
2021
|
this.usePersistPartialAdapter(PersistPartialDummyInstance);
|
|
2022
2022
|
}
|
|
2023
2023
|
}
|
|
@@ -2182,7 +2182,7 @@ class PersistBreakevenUtils {
|
|
|
2182
2182
|
* @returns Promise resolving to breakeven data record (empty object if none)
|
|
2183
2183
|
*/
|
|
2184
2184
|
this.readBreakevenData = async (symbol, strategyName, signalId, exchangeName, when) => {
|
|
2185
|
-
LOGGER_SERVICE$
|
|
2185
|
+
LOGGER_SERVICE$9.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_READ_DATA);
|
|
2186
2186
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
2187
2187
|
const isInitial = !this.getBreakevenStorage.has(key);
|
|
2188
2188
|
const instance = this.getBreakevenStorage(symbol, strategyName, exchangeName);
|
|
@@ -2202,7 +2202,7 @@ class PersistBreakevenUtils {
|
|
|
2202
2202
|
* @returns Promise that resolves when write is complete
|
|
2203
2203
|
*/
|
|
2204
2204
|
this.writeBreakevenData = async (breakevenData, symbol, strategyName, signalId, exchangeName, when) => {
|
|
2205
|
-
LOGGER_SERVICE$
|
|
2205
|
+
LOGGER_SERVICE$9.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2206
2206
|
const key = `${symbol}:${strategyName}:${exchangeName}`;
|
|
2207
2207
|
const isInitial = !this.getBreakevenStorage.has(key);
|
|
2208
2208
|
const instance = this.getBreakevenStorage(symbol, strategyName, exchangeName);
|
|
@@ -2217,7 +2217,7 @@ class PersistBreakevenUtils {
|
|
|
2217
2217
|
* @param Ctor - Custom IPersistBreakevenInstance constructor
|
|
2218
2218
|
*/
|
|
2219
2219
|
usePersistBreakevenAdapter(Ctor) {
|
|
2220
|
-
LOGGER_SERVICE$
|
|
2220
|
+
LOGGER_SERVICE$9.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_USE_PERSIST_BREAKEVEN_ADAPTER);
|
|
2221
2221
|
this.PersistBreakevenInstanceCtor = Ctor;
|
|
2222
2222
|
this.getBreakevenStorage.clear();
|
|
2223
2223
|
}
|
|
@@ -2226,21 +2226,21 @@ class PersistBreakevenUtils {
|
|
|
2226
2226
|
* Call when process.cwd() changes between strategy iterations.
|
|
2227
2227
|
*/
|
|
2228
2228
|
clear() {
|
|
2229
|
-
LOGGER_SERVICE$
|
|
2229
|
+
LOGGER_SERVICE$9.log(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_CLEAR);
|
|
2230
2230
|
this.getBreakevenStorage.clear();
|
|
2231
2231
|
}
|
|
2232
2232
|
/**
|
|
2233
2233
|
* Switches to the default file-based PersistBreakevenInstance.
|
|
2234
2234
|
*/
|
|
2235
2235
|
useJson() {
|
|
2236
|
-
LOGGER_SERVICE$
|
|
2236
|
+
LOGGER_SERVICE$9.log(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_USE_JSON);
|
|
2237
2237
|
this.usePersistBreakevenAdapter(PersistBreakevenInstance);
|
|
2238
2238
|
}
|
|
2239
2239
|
/**
|
|
2240
2240
|
* Switches to PersistBreakevenDummyInstance (all operations are no-ops).
|
|
2241
2241
|
*/
|
|
2242
2242
|
useDummy() {
|
|
2243
|
-
LOGGER_SERVICE$
|
|
2243
|
+
LOGGER_SERVICE$9.log(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2244
2244
|
this.usePersistBreakevenAdapter(PersistBreakevenDummyInstance);
|
|
2245
2245
|
}
|
|
2246
2246
|
}
|
|
@@ -2331,7 +2331,7 @@ class PersistCandleInstance {
|
|
|
2331
2331
|
error: functoolsKit.errorData(error),
|
|
2332
2332
|
message: functoolsKit.getErrorMessage(error),
|
|
2333
2333
|
};
|
|
2334
|
-
LOGGER_SERVICE$
|
|
2334
|
+
LOGGER_SERVICE$9.warn(message, payload);
|
|
2335
2335
|
console.warn(message, payload);
|
|
2336
2336
|
errorEmitter.next(error);
|
|
2337
2337
|
return null;
|
|
@@ -2353,7 +2353,7 @@ class PersistCandleInstance {
|
|
|
2353
2353
|
for (const candle of candles) {
|
|
2354
2354
|
const candleCloseTime = candle.timestamp + stepMs;
|
|
2355
2355
|
if (candleCloseTime > now) {
|
|
2356
|
-
LOGGER_SERVICE$
|
|
2356
|
+
LOGGER_SERVICE$9.debug("PersistCandleInstance.writeCandlesData: skipping incomplete candle", {
|
|
2357
2357
|
symbol: this.symbol,
|
|
2358
2358
|
interval: this.interval,
|
|
2359
2359
|
exchangeName: this.exchangeName,
|
|
@@ -2430,7 +2430,7 @@ class PersistCandleUtils {
|
|
|
2430
2430
|
* @returns Promise resolving to candles in order, or null on cache miss
|
|
2431
2431
|
*/
|
|
2432
2432
|
this.readCandlesData = async (symbol, interval, exchangeName, limit, sinceTimestamp, untilTimestamp) => {
|
|
2433
|
-
LOGGER_SERVICE$
|
|
2433
|
+
LOGGER_SERVICE$9.info("PersistCandleUtils.readCandlesData", {
|
|
2434
2434
|
symbol,
|
|
2435
2435
|
interval,
|
|
2436
2436
|
exchangeName,
|
|
@@ -2454,7 +2454,7 @@ class PersistCandleUtils {
|
|
|
2454
2454
|
* @returns Promise that resolves when all writes are complete
|
|
2455
2455
|
*/
|
|
2456
2456
|
this.writeCandlesData = async (candles, symbol, interval, exchangeName) => {
|
|
2457
|
-
LOGGER_SERVICE$
|
|
2457
|
+
LOGGER_SERVICE$9.info("PersistCandleUtils.writeCandlesData", {
|
|
2458
2458
|
symbol,
|
|
2459
2459
|
interval,
|
|
2460
2460
|
exchangeName,
|
|
@@ -2474,7 +2474,7 @@ class PersistCandleUtils {
|
|
|
2474
2474
|
* @param Ctor - Custom IPersistCandleInstance constructor
|
|
2475
2475
|
*/
|
|
2476
2476
|
usePersistCandleAdapter(Ctor) {
|
|
2477
|
-
LOGGER_SERVICE$
|
|
2477
|
+
LOGGER_SERVICE$9.info("PersistCandleUtils.usePersistCandleAdapter");
|
|
2478
2478
|
this.PersistCandleInstanceCtor = Ctor;
|
|
2479
2479
|
this.getCandlesStorage.clear();
|
|
2480
2480
|
}
|
|
@@ -2483,21 +2483,21 @@ class PersistCandleUtils {
|
|
|
2483
2483
|
* Call when process.cwd() changes between strategy iterations.
|
|
2484
2484
|
*/
|
|
2485
2485
|
clear() {
|
|
2486
|
-
LOGGER_SERVICE$
|
|
2486
|
+
LOGGER_SERVICE$9.log(PERSIST_CANDLE_UTILS_METHOD_NAME_CLEAR);
|
|
2487
2487
|
this.getCandlesStorage.clear();
|
|
2488
2488
|
}
|
|
2489
2489
|
/**
|
|
2490
2490
|
* Switches to the default file-based PersistCandleInstance.
|
|
2491
2491
|
*/
|
|
2492
2492
|
useJson() {
|
|
2493
|
-
LOGGER_SERVICE$
|
|
2493
|
+
LOGGER_SERVICE$9.log("PersistCandleUtils.useJson");
|
|
2494
2494
|
this.usePersistCandleAdapter(PersistCandleInstance);
|
|
2495
2495
|
}
|
|
2496
2496
|
/**
|
|
2497
2497
|
* Switches to PersistCandleDummyInstance (always returns null on read, discards writes).
|
|
2498
2498
|
*/
|
|
2499
2499
|
useDummy() {
|
|
2500
|
-
LOGGER_SERVICE$
|
|
2500
|
+
LOGGER_SERVICE$9.log("PersistCandleUtils.useDummy");
|
|
2501
2501
|
this.usePersistCandleAdapter(PersistCandleDummyInstance);
|
|
2502
2502
|
}
|
|
2503
2503
|
}
|
|
@@ -2635,7 +2635,7 @@ class PersistStorageUtils {
|
|
|
2635
2635
|
* @returns Promise resolving to array of signal entries
|
|
2636
2636
|
*/
|
|
2637
2637
|
this.readStorageData = async (backtest) => {
|
|
2638
|
-
LOGGER_SERVICE$
|
|
2638
|
+
LOGGER_SERVICE$9.info(PERSIST_STORAGE_UTILS_METHOD_NAME_READ_DATA);
|
|
2639
2639
|
const key = backtest ? `backtest` : `live`;
|
|
2640
2640
|
const isInitial = !this.getStorage.has(key);
|
|
2641
2641
|
const instance = this.getStorage(backtest);
|
|
@@ -2651,7 +2651,7 @@ class PersistStorageUtils {
|
|
|
2651
2651
|
* @returns Promise that resolves when write is complete
|
|
2652
2652
|
*/
|
|
2653
2653
|
this.writeStorageData = async (signalData, backtest) => {
|
|
2654
|
-
LOGGER_SERVICE$
|
|
2654
|
+
LOGGER_SERVICE$9.info(PERSIST_STORAGE_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2655
2655
|
const key = backtest ? `backtest` : `live`;
|
|
2656
2656
|
const isInitial = !this.getStorage.has(key);
|
|
2657
2657
|
const instance = this.getStorage(backtest);
|
|
@@ -2666,7 +2666,7 @@ class PersistStorageUtils {
|
|
|
2666
2666
|
* @param Ctor - Custom IPersistStorageInstance constructor
|
|
2667
2667
|
*/
|
|
2668
2668
|
usePersistStorageAdapter(Ctor) {
|
|
2669
|
-
LOGGER_SERVICE$
|
|
2669
|
+
LOGGER_SERVICE$9.info(PERSIST_STORAGE_UTILS_METHOD_NAME_USE_PERSIST_STORAGE_ADAPTER);
|
|
2670
2670
|
this.PersistStorageInstanceCtor = Ctor;
|
|
2671
2671
|
this.getStorage.clear();
|
|
2672
2672
|
}
|
|
@@ -2675,21 +2675,21 @@ class PersistStorageUtils {
|
|
|
2675
2675
|
* Call when process.cwd() changes between strategy iterations.
|
|
2676
2676
|
*/
|
|
2677
2677
|
clear() {
|
|
2678
|
-
LOGGER_SERVICE$
|
|
2678
|
+
LOGGER_SERVICE$9.log(PERSIST_STORAGE_UTILS_METHOD_NAME_CLEAR);
|
|
2679
2679
|
this.getStorage.clear();
|
|
2680
2680
|
}
|
|
2681
2681
|
/**
|
|
2682
2682
|
* Switches to the default file-based PersistStorageInstance.
|
|
2683
2683
|
*/
|
|
2684
2684
|
useJson() {
|
|
2685
|
-
LOGGER_SERVICE$
|
|
2685
|
+
LOGGER_SERVICE$9.log(PERSIST_STORAGE_UTILS_METHOD_NAME_USE_JSON);
|
|
2686
2686
|
this.usePersistStorageAdapter(PersistStorageInstance);
|
|
2687
2687
|
}
|
|
2688
2688
|
/**
|
|
2689
2689
|
* Switches to PersistStorageDummyInstance (all operations are no-ops).
|
|
2690
2690
|
*/
|
|
2691
2691
|
useDummy() {
|
|
2692
|
-
LOGGER_SERVICE$
|
|
2692
|
+
LOGGER_SERVICE$9.log(PERSIST_STORAGE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2693
2693
|
this.usePersistStorageAdapter(PersistStorageDummyInstance);
|
|
2694
2694
|
}
|
|
2695
2695
|
}
|
|
@@ -2816,7 +2816,7 @@ class PersistNotificationUtils {
|
|
|
2816
2816
|
* @returns Promise resolving to array of notification entries
|
|
2817
2817
|
*/
|
|
2818
2818
|
this.readNotificationData = async (backtest) => {
|
|
2819
|
-
LOGGER_SERVICE$
|
|
2819
|
+
LOGGER_SERVICE$9.info(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_READ_DATA);
|
|
2820
2820
|
const key = backtest ? `backtest` : `live`;
|
|
2821
2821
|
const isInitial = !this.getNotificationStorage.has(key);
|
|
2822
2822
|
const instance = this.getNotificationStorage(backtest);
|
|
@@ -2832,7 +2832,7 @@ class PersistNotificationUtils {
|
|
|
2832
2832
|
* @returns Promise that resolves when write is complete
|
|
2833
2833
|
*/
|
|
2834
2834
|
this.writeNotificationData = async (notificationData, backtest) => {
|
|
2835
|
-
LOGGER_SERVICE$
|
|
2835
|
+
LOGGER_SERVICE$9.info(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_WRITE_DATA);
|
|
2836
2836
|
const key = backtest ? `backtest` : `live`;
|
|
2837
2837
|
const isInitial = !this.getNotificationStorage.has(key);
|
|
2838
2838
|
const instance = this.getNotificationStorage(backtest);
|
|
@@ -2847,7 +2847,7 @@ class PersistNotificationUtils {
|
|
|
2847
2847
|
* @param Ctor - Custom IPersistNotificationInstance constructor
|
|
2848
2848
|
*/
|
|
2849
2849
|
usePersistNotificationAdapter(Ctor) {
|
|
2850
|
-
LOGGER_SERVICE$
|
|
2850
|
+
LOGGER_SERVICE$9.info(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_USE_PERSIST_NOTIFICATION_ADAPTER);
|
|
2851
2851
|
this.PersistNotificationInstanceCtor = Ctor;
|
|
2852
2852
|
this.getNotificationStorage.clear();
|
|
2853
2853
|
}
|
|
@@ -2857,21 +2857,21 @@ class PersistNotificationUtils {
|
|
|
2857
2857
|
* instances are created with the updated base path.
|
|
2858
2858
|
*/
|
|
2859
2859
|
clear() {
|
|
2860
|
-
LOGGER_SERVICE$
|
|
2860
|
+
LOGGER_SERVICE$9.log(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_CLEAR);
|
|
2861
2861
|
this.getNotificationStorage.clear();
|
|
2862
2862
|
}
|
|
2863
2863
|
/**
|
|
2864
2864
|
* Switches to the default file-based PersistNotificationInstance.
|
|
2865
2865
|
*/
|
|
2866
2866
|
useJson() {
|
|
2867
|
-
LOGGER_SERVICE$
|
|
2867
|
+
LOGGER_SERVICE$9.log(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_USE_JSON);
|
|
2868
2868
|
this.usePersistNotificationAdapter(PersistNotificationInstance);
|
|
2869
2869
|
}
|
|
2870
2870
|
/**
|
|
2871
2871
|
* Switches to PersistNotificationDummyInstance (all operations are no-ops).
|
|
2872
2872
|
*/
|
|
2873
2873
|
useDummy() {
|
|
2874
|
-
LOGGER_SERVICE$
|
|
2874
|
+
LOGGER_SERVICE$9.log(PERSIST_NOTIFICATION_UTILS_METHOD_NAME_USE_DUMMY);
|
|
2875
2875
|
this.usePersistNotificationAdapter(PersistNotificationDummyInstance);
|
|
2876
2876
|
}
|
|
2877
2877
|
}
|
|
@@ -2995,7 +2995,7 @@ class PersistLogUtils {
|
|
|
2995
2995
|
* @returns Promise resolving to array of log entries
|
|
2996
2996
|
*/
|
|
2997
2997
|
this.readLogData = async () => {
|
|
2998
|
-
LOGGER_SERVICE$
|
|
2998
|
+
LOGGER_SERVICE$9.info(PERSIST_LOG_UTILS_METHOD_NAME_READ_DATA);
|
|
2999
2999
|
const isInitial = !this._logInstance;
|
|
3000
3000
|
const instance = this.getLogInstance();
|
|
3001
3001
|
await instance.waitForInit(isInitial);
|
|
@@ -3009,7 +3009,7 @@ class PersistLogUtils {
|
|
|
3009
3009
|
* @returns Promise that resolves when write is complete
|
|
3010
3010
|
*/
|
|
3011
3011
|
this.writeLogData = async (logData) => {
|
|
3012
|
-
LOGGER_SERVICE$
|
|
3012
|
+
LOGGER_SERVICE$9.info(PERSIST_LOG_UTILS_METHOD_NAME_WRITE_DATA);
|
|
3013
3013
|
const isInitial = !this._logInstance;
|
|
3014
3014
|
const instance = this.getLogInstance();
|
|
3015
3015
|
await instance.waitForInit(isInitial);
|
|
@@ -3034,7 +3034,7 @@ class PersistLogUtils {
|
|
|
3034
3034
|
* @param Ctor - Custom IPersistLogInstance constructor
|
|
3035
3035
|
*/
|
|
3036
3036
|
usePersistLogAdapter(Ctor) {
|
|
3037
|
-
LOGGER_SERVICE$
|
|
3037
|
+
LOGGER_SERVICE$9.info(PERSIST_LOG_UTILS_METHOD_NAME_USE_PERSIST_LOG_ADAPTER);
|
|
3038
3038
|
this.PersistLogInstanceCtor = Ctor;
|
|
3039
3039
|
this._logInstance = null;
|
|
3040
3040
|
}
|
|
@@ -3043,21 +3043,21 @@ class PersistLogUtils {
|
|
|
3043
3043
|
* Call when process.cwd() changes between strategy iterations.
|
|
3044
3044
|
*/
|
|
3045
3045
|
clear() {
|
|
3046
|
-
LOGGER_SERVICE$
|
|
3046
|
+
LOGGER_SERVICE$9.log(PERSIST_LOG_UTILS_METHOD_NAME_CLEAR);
|
|
3047
3047
|
this._logInstance = null;
|
|
3048
3048
|
}
|
|
3049
3049
|
/**
|
|
3050
3050
|
* Switches to the default file-based PersistLogInstance.
|
|
3051
3051
|
*/
|
|
3052
3052
|
useJson() {
|
|
3053
|
-
LOGGER_SERVICE$
|
|
3053
|
+
LOGGER_SERVICE$9.log(PERSIST_LOG_UTILS_METHOD_NAME_USE_JSON);
|
|
3054
3054
|
this.usePersistLogAdapter(PersistLogInstance);
|
|
3055
3055
|
}
|
|
3056
3056
|
/**
|
|
3057
3057
|
* Switches to PersistLogDummyInstance (all operations are no-ops).
|
|
3058
3058
|
*/
|
|
3059
3059
|
useDummy() {
|
|
3060
|
-
LOGGER_SERVICE$
|
|
3060
|
+
LOGGER_SERVICE$9.log(PERSIST_LOG_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3061
3061
|
this.usePersistLogAdapter(PersistLogDummyInstance);
|
|
3062
3062
|
}
|
|
3063
3063
|
}
|
|
@@ -3219,7 +3219,7 @@ class PersistMeasureUtils {
|
|
|
3219
3219
|
* @returns Promise resolving to cached value, or null if not found / soft-deleted
|
|
3220
3220
|
*/
|
|
3221
3221
|
this.readMeasureData = async (bucket, key) => {
|
|
3222
|
-
LOGGER_SERVICE$
|
|
3222
|
+
LOGGER_SERVICE$9.info(PERSIST_MEASURE_UTILS_METHOD_NAME_READ_DATA, { bucket, key });
|
|
3223
3223
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3224
3224
|
const instance = this.getMeasureStorage(bucket);
|
|
3225
3225
|
await instance.waitForInit(isInitial);
|
|
@@ -3235,7 +3235,7 @@ class PersistMeasureUtils {
|
|
|
3235
3235
|
* @returns Promise that resolves when write is complete
|
|
3236
3236
|
*/
|
|
3237
3237
|
this.writeMeasureData = async (data, bucket, key, when) => {
|
|
3238
|
-
LOGGER_SERVICE$
|
|
3238
|
+
LOGGER_SERVICE$9.info(PERSIST_MEASURE_UTILS_METHOD_NAME_WRITE_DATA, { bucket, key });
|
|
3239
3239
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3240
3240
|
const instance = this.getMeasureStorage(bucket);
|
|
3241
3241
|
await instance.waitForInit(isInitial);
|
|
@@ -3250,7 +3250,7 @@ class PersistMeasureUtils {
|
|
|
3250
3250
|
* @returns Promise that resolves when removal is complete
|
|
3251
3251
|
*/
|
|
3252
3252
|
this.removeMeasureData = async (bucket, key) => {
|
|
3253
|
-
LOGGER_SERVICE$
|
|
3253
|
+
LOGGER_SERVICE$9.info(PERSIST_MEASURE_UTILS_METHOD_NAME_REMOVE_DATA, { bucket, key });
|
|
3254
3254
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3255
3255
|
const instance = this.getMeasureStorage(bucket);
|
|
3256
3256
|
await instance.waitForInit(isInitial);
|
|
@@ -3264,7 +3264,7 @@ class PersistMeasureUtils {
|
|
|
3264
3264
|
* @param Ctor - Custom IPersistMeasureInstance constructor
|
|
3265
3265
|
*/
|
|
3266
3266
|
usePersistMeasureAdapter(Ctor) {
|
|
3267
|
-
LOGGER_SERVICE$
|
|
3267
|
+
LOGGER_SERVICE$9.info(PERSIST_MEASURE_UTILS_METHOD_NAME_USE_PERSIST_MEASURE_ADAPTER);
|
|
3268
3268
|
this.PersistMeasureInstanceCtor = Ctor;
|
|
3269
3269
|
this.getMeasureStorage.clear();
|
|
3270
3270
|
}
|
|
@@ -3276,7 +3276,7 @@ class PersistMeasureUtils {
|
|
|
3276
3276
|
* @returns AsyncGenerator yielding entry keys
|
|
3277
3277
|
*/
|
|
3278
3278
|
async *listMeasureData(bucket) {
|
|
3279
|
-
LOGGER_SERVICE$
|
|
3279
|
+
LOGGER_SERVICE$9.info(PERSIST_MEASURE_UTILS_METHOD_NAME_LIST_DATA, { bucket });
|
|
3280
3280
|
const isInitial = !this.getMeasureStorage.has(bucket);
|
|
3281
3281
|
const instance = this.getMeasureStorage(bucket);
|
|
3282
3282
|
await instance.waitForInit(isInitial);
|
|
@@ -3287,21 +3287,21 @@ class PersistMeasureUtils {
|
|
|
3287
3287
|
* Call when process.cwd() changes between strategy iterations.
|
|
3288
3288
|
*/
|
|
3289
3289
|
clear() {
|
|
3290
|
-
LOGGER_SERVICE$
|
|
3290
|
+
LOGGER_SERVICE$9.log(PERSIST_MEASURE_UTILS_METHOD_NAME_CLEAR);
|
|
3291
3291
|
this.getMeasureStorage.clear();
|
|
3292
3292
|
}
|
|
3293
3293
|
/**
|
|
3294
3294
|
* Switches to the default file-based PersistMeasureInstance.
|
|
3295
3295
|
*/
|
|
3296
3296
|
useJson() {
|
|
3297
|
-
LOGGER_SERVICE$
|
|
3297
|
+
LOGGER_SERVICE$9.log(PERSIST_MEASURE_UTILS_METHOD_NAME_USE_JSON);
|
|
3298
3298
|
this.usePersistMeasureAdapter(PersistMeasureInstance);
|
|
3299
3299
|
}
|
|
3300
3300
|
/**
|
|
3301
3301
|
* Switches to PersistMeasureDummyInstance (all operations are no-ops).
|
|
3302
3302
|
*/
|
|
3303
3303
|
useDummy() {
|
|
3304
|
-
LOGGER_SERVICE$
|
|
3304
|
+
LOGGER_SERVICE$9.log(PERSIST_MEASURE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3305
3305
|
this.usePersistMeasureAdapter(PersistMeasureDummyInstance);
|
|
3306
3306
|
}
|
|
3307
3307
|
}
|
|
@@ -3460,7 +3460,7 @@ class PersistIntervalUtils {
|
|
|
3460
3460
|
* @returns Promise resolving to marker data, or null if not found / soft-deleted
|
|
3461
3461
|
*/
|
|
3462
3462
|
this.readIntervalData = async (bucket, key) => {
|
|
3463
|
-
LOGGER_SERVICE$
|
|
3463
|
+
LOGGER_SERVICE$9.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_READ_DATA, { bucket, key });
|
|
3464
3464
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3465
3465
|
const instance = this.getIntervalStorage(bucket);
|
|
3466
3466
|
await instance.waitForInit(isInitial);
|
|
@@ -3476,7 +3476,7 @@ class PersistIntervalUtils {
|
|
|
3476
3476
|
* @returns Promise that resolves when write is complete
|
|
3477
3477
|
*/
|
|
3478
3478
|
this.writeIntervalData = async (data, bucket, key, when) => {
|
|
3479
|
-
LOGGER_SERVICE$
|
|
3479
|
+
LOGGER_SERVICE$9.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_WRITE_DATA, { bucket, key });
|
|
3480
3480
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3481
3481
|
const instance = this.getIntervalStorage(bucket);
|
|
3482
3482
|
await instance.waitForInit(isInitial);
|
|
@@ -3491,7 +3491,7 @@ class PersistIntervalUtils {
|
|
|
3491
3491
|
* @returns Promise that resolves when removal is complete
|
|
3492
3492
|
*/
|
|
3493
3493
|
this.removeIntervalData = async (bucket, key) => {
|
|
3494
|
-
LOGGER_SERVICE$
|
|
3494
|
+
LOGGER_SERVICE$9.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_REMOVE_DATA, { bucket, key });
|
|
3495
3495
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3496
3496
|
const instance = this.getIntervalStorage(bucket);
|
|
3497
3497
|
await instance.waitForInit(isInitial);
|
|
@@ -3505,7 +3505,7 @@ class PersistIntervalUtils {
|
|
|
3505
3505
|
* @param Ctor - Custom IPersistIntervalInstance constructor
|
|
3506
3506
|
*/
|
|
3507
3507
|
usePersistIntervalAdapter(Ctor) {
|
|
3508
|
-
LOGGER_SERVICE$
|
|
3508
|
+
LOGGER_SERVICE$9.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_USE_PERSIST_INTERVAL_ADAPTER);
|
|
3509
3509
|
this.PersistIntervalInstanceCtor = Ctor;
|
|
3510
3510
|
this.getIntervalStorage.clear();
|
|
3511
3511
|
}
|
|
@@ -3517,7 +3517,7 @@ class PersistIntervalUtils {
|
|
|
3517
3517
|
* @returns AsyncGenerator yielding marker keys
|
|
3518
3518
|
*/
|
|
3519
3519
|
async *listIntervalData(bucket) {
|
|
3520
|
-
LOGGER_SERVICE$
|
|
3520
|
+
LOGGER_SERVICE$9.info(PERSIST_INTERVAL_UTILS_METHOD_NAME_LIST_DATA, { bucket });
|
|
3521
3521
|
const isInitial = !this.getIntervalStorage.has(bucket);
|
|
3522
3522
|
const instance = this.getIntervalStorage(bucket);
|
|
3523
3523
|
await instance.waitForInit(isInitial);
|
|
@@ -3528,21 +3528,21 @@ class PersistIntervalUtils {
|
|
|
3528
3528
|
* Call when process.cwd() changes between strategy iterations.
|
|
3529
3529
|
*/
|
|
3530
3530
|
clear() {
|
|
3531
|
-
LOGGER_SERVICE$
|
|
3531
|
+
LOGGER_SERVICE$9.log(PERSIST_INTERVAL_UTILS_METHOD_NAME_CLEAR);
|
|
3532
3532
|
this.getIntervalStorage.clear();
|
|
3533
3533
|
}
|
|
3534
3534
|
/**
|
|
3535
3535
|
* Switches to the default file-based PersistIntervalInstance.
|
|
3536
3536
|
*/
|
|
3537
3537
|
useJson() {
|
|
3538
|
-
LOGGER_SERVICE$
|
|
3538
|
+
LOGGER_SERVICE$9.log(PERSIST_INTERVAL_UTILS_METHOD_NAME_USE_JSON);
|
|
3539
3539
|
this.usePersistIntervalAdapter(PersistIntervalInstance);
|
|
3540
3540
|
}
|
|
3541
3541
|
/**
|
|
3542
3542
|
* Switches to PersistIntervalDummyInstance (all operations are no-ops).
|
|
3543
3543
|
*/
|
|
3544
3544
|
useDummy() {
|
|
3545
|
-
LOGGER_SERVICE$
|
|
3545
|
+
LOGGER_SERVICE$9.log(PERSIST_INTERVAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3546
3546
|
this.usePersistIntervalAdapter(PersistIntervalDummyInstance);
|
|
3547
3547
|
}
|
|
3548
3548
|
}
|
|
@@ -3748,7 +3748,7 @@ class PersistMemoryUtils {
|
|
|
3748
3748
|
* @returns Promise resolving to entry data, or null if not found / soft-deleted
|
|
3749
3749
|
*/
|
|
3750
3750
|
this.readMemoryData = async (signalId, bucketName, memoryId) => {
|
|
3751
|
-
LOGGER_SERVICE$
|
|
3751
|
+
LOGGER_SERVICE$9.info(PERSIST_MEMORY_UTILS_METHOD_NAME_READ_DATA, { signalId, bucketName, memoryId });
|
|
3752
3752
|
const key = `${signalId}:${bucketName}`;
|
|
3753
3753
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3754
3754
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3765,7 +3765,7 @@ class PersistMemoryUtils {
|
|
|
3765
3765
|
* @returns Promise resolving to true if entry exists
|
|
3766
3766
|
*/
|
|
3767
3767
|
this.hasMemoryData = async (signalId, bucketName, memoryId) => {
|
|
3768
|
-
LOGGER_SERVICE$
|
|
3768
|
+
LOGGER_SERVICE$9.info(PERSIST_MEMORY_UTILS_METHOD_NAME_HAS_DATA, { signalId, bucketName, memoryId });
|
|
3769
3769
|
const key = `${signalId}:${bucketName}`;
|
|
3770
3770
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3771
3771
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3784,7 +3784,7 @@ class PersistMemoryUtils {
|
|
|
3784
3784
|
* @returns Promise that resolves when write is complete
|
|
3785
3785
|
*/
|
|
3786
3786
|
this.writeMemoryData = async (data, signalId, bucketName, memoryId, when) => {
|
|
3787
|
-
LOGGER_SERVICE$
|
|
3787
|
+
LOGGER_SERVICE$9.info(PERSIST_MEMORY_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName, memoryId });
|
|
3788
3788
|
const key = `${signalId}:${bucketName}`;
|
|
3789
3789
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3790
3790
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3801,7 +3801,7 @@ class PersistMemoryUtils {
|
|
|
3801
3801
|
* @returns Promise that resolves when removal is complete
|
|
3802
3802
|
*/
|
|
3803
3803
|
this.removeMemoryData = async (signalId, bucketName, memoryId) => {
|
|
3804
|
-
LOGGER_SERVICE$
|
|
3804
|
+
LOGGER_SERVICE$9.info(PERSIST_MEMORY_UTILS_METHOD_NAME_REMOVE_DATA, { signalId, bucketName, memoryId });
|
|
3805
3805
|
const key = `${signalId}:${bucketName}`;
|
|
3806
3806
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3807
3807
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3813,7 +3813,7 @@ class PersistMemoryUtils {
|
|
|
3813
3813
|
* Call when process.cwd() changes between strategy iterations.
|
|
3814
3814
|
*/
|
|
3815
3815
|
this.clear = () => {
|
|
3816
|
-
LOGGER_SERVICE$
|
|
3816
|
+
LOGGER_SERVICE$9.info(PERSIST_MEMORY_UTILS_METHOD_NAME_CLEAR);
|
|
3817
3817
|
this.getMemoryStorage.clear();
|
|
3818
3818
|
};
|
|
3819
3819
|
/**
|
|
@@ -3824,7 +3824,7 @@ class PersistMemoryUtils {
|
|
|
3824
3824
|
* @param bucketName - Bucket name
|
|
3825
3825
|
*/
|
|
3826
3826
|
this.dispose = (signalId, bucketName) => {
|
|
3827
|
-
LOGGER_SERVICE$
|
|
3827
|
+
LOGGER_SERVICE$9.info(PERSIST_MEMORY_UTILS_METHOD_NAME_DISPOSE);
|
|
3828
3828
|
const key = `${signalId}:${bucketName}`;
|
|
3829
3829
|
this.getMemoryStorage.clear(key);
|
|
3830
3830
|
};
|
|
@@ -3836,7 +3836,7 @@ class PersistMemoryUtils {
|
|
|
3836
3836
|
* @param Ctor - Custom IPersistMemoryInstance constructor
|
|
3837
3837
|
*/
|
|
3838
3838
|
usePersistMemoryAdapter(Ctor) {
|
|
3839
|
-
LOGGER_SERVICE$
|
|
3839
|
+
LOGGER_SERVICE$9.info(PERSIST_MEMORY_UTILS_METHOD_NAME_USE_PERSIST_MEMORY_ADAPTER);
|
|
3840
3840
|
this.PersistMemoryInstanceCtor = Ctor;
|
|
3841
3841
|
this.getMemoryStorage.clear();
|
|
3842
3842
|
}
|
|
@@ -3850,7 +3850,7 @@ class PersistMemoryUtils {
|
|
|
3850
3850
|
* @returns AsyncGenerator yielding `{ memoryId, data }` tuples
|
|
3851
3851
|
*/
|
|
3852
3852
|
async *listMemoryData(signalId, bucketName) {
|
|
3853
|
-
LOGGER_SERVICE$
|
|
3853
|
+
LOGGER_SERVICE$9.info(PERSIST_MEMORY_UTILS_METHOD_NAME_LIST_DATA, { signalId, bucketName });
|
|
3854
3854
|
const key = `${signalId}:${bucketName}`;
|
|
3855
3855
|
const isInitial = !this.getMemoryStorage.has(key);
|
|
3856
3856
|
const instance = this.getMemoryStorage(signalId, bucketName);
|
|
@@ -3861,14 +3861,14 @@ class PersistMemoryUtils {
|
|
|
3861
3861
|
* Switches to the default file-based PersistMemoryInstance.
|
|
3862
3862
|
*/
|
|
3863
3863
|
useJson() {
|
|
3864
|
-
LOGGER_SERVICE$
|
|
3864
|
+
LOGGER_SERVICE$9.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_JSON);
|
|
3865
3865
|
this.usePersistMemoryAdapter(PersistMemoryInstance);
|
|
3866
3866
|
}
|
|
3867
3867
|
/**
|
|
3868
3868
|
* Switches to PersistMemoryDummyInstance (all operations are no-ops).
|
|
3869
3869
|
*/
|
|
3870
3870
|
useDummy() {
|
|
3871
|
-
LOGGER_SERVICE$
|
|
3871
|
+
LOGGER_SERVICE$9.log(PERSIST_SIGNAL_UTILS_METHOD_NAME_USE_DUMMY);
|
|
3872
3872
|
this.usePersistMemoryAdapter(PersistMemoryDummyInstance);
|
|
3873
3873
|
}
|
|
3874
3874
|
}
|
|
@@ -4017,7 +4017,7 @@ class PersistRecentUtils {
|
|
|
4017
4017
|
* @returns Promise resolving to recent signal or null if none persisted
|
|
4018
4018
|
*/
|
|
4019
4019
|
this.readRecentData = async (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
4020
|
-
LOGGER_SERVICE$
|
|
4020
|
+
LOGGER_SERVICE$9.info(PERSIST_RECENT_UTILS_METHOD_NAME_READ_DATA);
|
|
4021
4021
|
const key = this.createKey(symbol, strategyName, exchangeName, frameName, backtest);
|
|
4022
4022
|
const isInitial = !this.getStorage.has(key);
|
|
4023
4023
|
const instance = this.getStorage(symbol, strategyName, exchangeName, frameName, backtest);
|
|
@@ -4038,7 +4038,7 @@ class PersistRecentUtils {
|
|
|
4038
4038
|
* @returns Promise that resolves when write is complete
|
|
4039
4039
|
*/
|
|
4040
4040
|
this.writeRecentData = async (signalRow, symbol, strategyName, exchangeName, frameName, backtest, when) => {
|
|
4041
|
-
LOGGER_SERVICE$
|
|
4041
|
+
LOGGER_SERVICE$9.info(PERSIST_RECENT_UTILS_METHOD_NAME_WRITE_DATA);
|
|
4042
4042
|
const key = this.createKey(symbol, strategyName, exchangeName, frameName, backtest);
|
|
4043
4043
|
const isInitial = !this.getStorage.has(key);
|
|
4044
4044
|
const instance = this.getStorage(symbol, strategyName, exchangeName, frameName, backtest);
|
|
@@ -4071,7 +4071,7 @@ class PersistRecentUtils {
|
|
|
4071
4071
|
* @param Ctor - Custom IPersistRecentInstance constructor
|
|
4072
4072
|
*/
|
|
4073
4073
|
usePersistRecentAdapter(Ctor) {
|
|
4074
|
-
LOGGER_SERVICE$
|
|
4074
|
+
LOGGER_SERVICE$9.info(PERSIST_RECENT_UTILS_METHOD_NAME_USE_PERSIST_RECENT_ADAPTER);
|
|
4075
4075
|
this.PersistRecentInstanceCtor = Ctor;
|
|
4076
4076
|
this.getStorage.clear();
|
|
4077
4077
|
}
|
|
@@ -4080,21 +4080,21 @@ class PersistRecentUtils {
|
|
|
4080
4080
|
* Call when process.cwd() changes between strategy iterations.
|
|
4081
4081
|
*/
|
|
4082
4082
|
clear() {
|
|
4083
|
-
LOGGER_SERVICE$
|
|
4083
|
+
LOGGER_SERVICE$9.log(PERSIST_RECENT_UTILS_METHOD_NAME_CLEAR);
|
|
4084
4084
|
this.getStorage.clear();
|
|
4085
4085
|
}
|
|
4086
4086
|
/**
|
|
4087
4087
|
* Switches to the default file-based PersistRecentInstance.
|
|
4088
4088
|
*/
|
|
4089
4089
|
useJson() {
|
|
4090
|
-
LOGGER_SERVICE$
|
|
4090
|
+
LOGGER_SERVICE$9.log(PERSIST_RECENT_UTILS_METHOD_NAME_USE_JSON);
|
|
4091
4091
|
this.usePersistRecentAdapter(PersistRecentInstance);
|
|
4092
4092
|
}
|
|
4093
4093
|
/**
|
|
4094
4094
|
* Switches to PersistRecentDummyInstance (all operations are no-ops).
|
|
4095
4095
|
*/
|
|
4096
4096
|
useDummy() {
|
|
4097
|
-
LOGGER_SERVICE$
|
|
4097
|
+
LOGGER_SERVICE$9.log(PERSIST_RECENT_UTILS_METHOD_NAME_USE_DUMMY);
|
|
4098
4098
|
this.usePersistRecentAdapter(PersistRecentDummyInstance);
|
|
4099
4099
|
}
|
|
4100
4100
|
}
|
|
@@ -4229,7 +4229,7 @@ class PersistStateUtils {
|
|
|
4229
4229
|
* @returns Promise that resolves when initialization is complete
|
|
4230
4230
|
*/
|
|
4231
4231
|
this.waitForInit = async (signalId, bucketName, initial) => {
|
|
4232
|
-
LOGGER_SERVICE$
|
|
4232
|
+
LOGGER_SERVICE$9.info(PERSIST_STATE_UTILS_METHOD_NAME_WAIT_FOR_INIT, { signalId, bucketName, initial });
|
|
4233
4233
|
const key = `${signalId}:${bucketName}`;
|
|
4234
4234
|
const isInitial = initial && !this.getStateStorage.has(key);
|
|
4235
4235
|
const instance = this.getStateStorage(signalId, bucketName);
|
|
@@ -4244,7 +4244,7 @@ class PersistStateUtils {
|
|
|
4244
4244
|
* @returns Promise resolving to state data or null if none persisted
|
|
4245
4245
|
*/
|
|
4246
4246
|
this.readStateData = async (signalId, bucketName) => {
|
|
4247
|
-
LOGGER_SERVICE$
|
|
4247
|
+
LOGGER_SERVICE$9.info(PERSIST_STATE_UTILS_METHOD_NAME_READ_DATA, { signalId, bucketName });
|
|
4248
4248
|
const key = `${signalId}:${bucketName}`;
|
|
4249
4249
|
const isInitial = !this.getStateStorage.has(key);
|
|
4250
4250
|
const instance = this.getStateStorage(signalId, bucketName);
|
|
@@ -4262,7 +4262,7 @@ class PersistStateUtils {
|
|
|
4262
4262
|
* @returns Promise that resolves when write is complete
|
|
4263
4263
|
*/
|
|
4264
4264
|
this.writeStateData = async (data, signalId, bucketName, when) => {
|
|
4265
|
-
LOGGER_SERVICE$
|
|
4265
|
+
LOGGER_SERVICE$9.info(PERSIST_STATE_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName });
|
|
4266
4266
|
const key = `${signalId}:${bucketName}`;
|
|
4267
4267
|
const isInitial = !this.getStateStorage.has(key);
|
|
4268
4268
|
const instance = this.getStateStorage(signalId, bucketName);
|
|
@@ -4273,14 +4273,14 @@ class PersistStateUtils {
|
|
|
4273
4273
|
* Switches to PersistStateDummyInstance (all operations are no-ops).
|
|
4274
4274
|
*/
|
|
4275
4275
|
this.useDummy = () => {
|
|
4276
|
-
LOGGER_SERVICE$
|
|
4276
|
+
LOGGER_SERVICE$9.log(PERSIST_STATE_UTILS_METHOD_NAME_USE_DUMMY);
|
|
4277
4277
|
this.usePersistStateAdapter(PersistStateDummyInstance);
|
|
4278
4278
|
};
|
|
4279
4279
|
/**
|
|
4280
4280
|
* Switches to the default file-based PersistStateInstance.
|
|
4281
4281
|
*/
|
|
4282
4282
|
this.useJson = () => {
|
|
4283
|
-
LOGGER_SERVICE$
|
|
4283
|
+
LOGGER_SERVICE$9.log(PERSIST_STATE_UTILS_METHOD_NAME_USE_JSON);
|
|
4284
4284
|
this.usePersistStateAdapter(PersistStateInstance);
|
|
4285
4285
|
};
|
|
4286
4286
|
/**
|
|
@@ -4288,7 +4288,7 @@ class PersistStateUtils {
|
|
|
4288
4288
|
* Call when process.cwd() changes between strategy iterations.
|
|
4289
4289
|
*/
|
|
4290
4290
|
this.clear = () => {
|
|
4291
|
-
LOGGER_SERVICE$
|
|
4291
|
+
LOGGER_SERVICE$9.info(PERSIST_STATE_UTILS_METHOD_NAME_CLEAR);
|
|
4292
4292
|
this.getStateStorage.clear();
|
|
4293
4293
|
};
|
|
4294
4294
|
/**
|
|
@@ -4299,7 +4299,7 @@ class PersistStateUtils {
|
|
|
4299
4299
|
* @param bucketName - Bucket name
|
|
4300
4300
|
*/
|
|
4301
4301
|
this.dispose = (signalId, bucketName) => {
|
|
4302
|
-
LOGGER_SERVICE$
|
|
4302
|
+
LOGGER_SERVICE$9.info(PERSIST_STATE_UTILS_METHOD_NAME_DISPOSE);
|
|
4303
4303
|
const key = `${signalId}:${bucketName}`;
|
|
4304
4304
|
this.getStateStorage.clear(key);
|
|
4305
4305
|
};
|
|
@@ -4311,7 +4311,7 @@ class PersistStateUtils {
|
|
|
4311
4311
|
* @param Ctor - Custom IPersistStateInstance constructor
|
|
4312
4312
|
*/
|
|
4313
4313
|
usePersistStateAdapter(Ctor) {
|
|
4314
|
-
LOGGER_SERVICE$
|
|
4314
|
+
LOGGER_SERVICE$9.info(PERSIST_STATE_UTILS_METHOD_NAME_USE_PERSIST_STATE_ADAPTER);
|
|
4315
4315
|
this.PersistStateInstanceCtor = Ctor;
|
|
4316
4316
|
this.getStateStorage.clear();
|
|
4317
4317
|
}
|
|
@@ -4451,7 +4451,7 @@ class PersistSessionUtils {
|
|
|
4451
4451
|
* @returns Promise that resolves when initialization is complete
|
|
4452
4452
|
*/
|
|
4453
4453
|
this.waitForInit = async (strategyName, exchangeName, frameName, initial) => {
|
|
4454
|
-
LOGGER_SERVICE$
|
|
4454
|
+
LOGGER_SERVICE$9.info(PERSIST_SESSION_UTILS_METHOD_NAME_WAIT_FOR_INIT, { strategyName, exchangeName, frameName, initial });
|
|
4455
4455
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4456
4456
|
const isInitial = initial && !this.getSessionStorage.has(key);
|
|
4457
4457
|
const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
|
|
@@ -4467,7 +4467,7 @@ class PersistSessionUtils {
|
|
|
4467
4467
|
* @returns Promise resolving to session data or null if none persisted
|
|
4468
4468
|
*/
|
|
4469
4469
|
this.readSessionData = async (strategyName, exchangeName, frameName) => {
|
|
4470
|
-
LOGGER_SERVICE$
|
|
4470
|
+
LOGGER_SERVICE$9.info(PERSIST_SESSION_UTILS_METHOD_NAME_READ_DATA, { strategyName, exchangeName, frameName });
|
|
4471
4471
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4472
4472
|
const isInitial = !this.getSessionStorage.has(key);
|
|
4473
4473
|
const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
|
|
@@ -4486,7 +4486,7 @@ class PersistSessionUtils {
|
|
|
4486
4486
|
* @returns Promise that resolves when write is complete
|
|
4487
4487
|
*/
|
|
4488
4488
|
this.writeSessionData = async (data, strategyName, exchangeName, frameName, when) => {
|
|
4489
|
-
LOGGER_SERVICE$
|
|
4489
|
+
LOGGER_SERVICE$9.info(PERSIST_SESSION_UTILS_METHOD_NAME_WRITE_DATA, { strategyName, exchangeName, frameName });
|
|
4490
4490
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4491
4491
|
const isInitial = !this.getSessionStorage.has(key);
|
|
4492
4492
|
const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
|
|
@@ -4497,14 +4497,14 @@ class PersistSessionUtils {
|
|
|
4497
4497
|
* Switches to PersistSessionDummyInstance (all operations are no-ops).
|
|
4498
4498
|
*/
|
|
4499
4499
|
this.useDummy = () => {
|
|
4500
|
-
LOGGER_SERVICE$
|
|
4500
|
+
LOGGER_SERVICE$9.log(PERSIST_SESSION_UTILS_METHOD_NAME_USE_DUMMY);
|
|
4501
4501
|
this.usePersistSessionAdapter(PersistSessionDummyInstance);
|
|
4502
4502
|
};
|
|
4503
4503
|
/**
|
|
4504
4504
|
* Switches to the default file-based PersistSessionInstance.
|
|
4505
4505
|
*/
|
|
4506
4506
|
this.useJson = () => {
|
|
4507
|
-
LOGGER_SERVICE$
|
|
4507
|
+
LOGGER_SERVICE$9.log(PERSIST_SESSION_UTILS_METHOD_NAME_USE_JSON);
|
|
4508
4508
|
this.usePersistSessionAdapter(PersistSessionInstance);
|
|
4509
4509
|
};
|
|
4510
4510
|
/**
|
|
@@ -4512,7 +4512,7 @@ class PersistSessionUtils {
|
|
|
4512
4512
|
* Call when process.cwd() changes between strategy iterations.
|
|
4513
4513
|
*/
|
|
4514
4514
|
this.clear = () => {
|
|
4515
|
-
LOGGER_SERVICE$
|
|
4515
|
+
LOGGER_SERVICE$9.info(PERSIST_SESSION_UTILS_METHOD_NAME_CLEAR);
|
|
4516
4516
|
this.getSessionStorage.clear();
|
|
4517
4517
|
};
|
|
4518
4518
|
/**
|
|
@@ -4524,7 +4524,7 @@ class PersistSessionUtils {
|
|
|
4524
4524
|
* @param frameName - Frame identifier
|
|
4525
4525
|
*/
|
|
4526
4526
|
this.dispose = (strategyName, exchangeName, frameName) => {
|
|
4527
|
-
LOGGER_SERVICE$
|
|
4527
|
+
LOGGER_SERVICE$9.info(PERSIST_SESSION_UTILS_METHOD_NAME_DISPOSE);
|
|
4528
4528
|
const key = `${strategyName}:${exchangeName}:${frameName}`;
|
|
4529
4529
|
this.getSessionStorage.clear(key);
|
|
4530
4530
|
};
|
|
@@ -4536,7 +4536,7 @@ class PersistSessionUtils {
|
|
|
4536
4536
|
* @param Ctor - Custom IPersistSessionInstance constructor
|
|
4537
4537
|
*/
|
|
4538
4538
|
usePersistSessionAdapter(Ctor) {
|
|
4539
|
-
LOGGER_SERVICE$
|
|
4539
|
+
LOGGER_SERVICE$9.info(PERSIST_SESSION_UTILS_METHOD_NAME_USE_PERSIST_SESSION_ADAPTER);
|
|
4540
4540
|
this.PersistSessionInstanceCtor = Ctor;
|
|
4541
4541
|
this.getSessionStorage.clear();
|
|
4542
4542
|
}
|
|
@@ -4658,7 +4658,7 @@ const METHOD_NAME_ADD_ACTIVITY = "LookupUtils.addActivity";
|
|
|
4658
4658
|
const METHOD_NAME_REMOVE_ACTIVITY = "LookupUtils.removeActivity";
|
|
4659
4659
|
const METHOD_NAME_LIST_ACTIVITY = "LookupUtils.listActivity";
|
|
4660
4660
|
/** Logger service injected as DI singleton */
|
|
4661
|
-
const LOGGER_SERVICE$
|
|
4661
|
+
const LOGGER_SERVICE$8 = new LoggerService();
|
|
4662
4662
|
/**
|
|
4663
4663
|
* Builds the composite {@link Key} used to register an activity in `_lookupMap`.
|
|
4664
4664
|
*
|
|
@@ -4712,7 +4712,7 @@ class LookupUtils {
|
|
|
4712
4712
|
* @param activity - Activity descriptor identifying the running workload.
|
|
4713
4713
|
*/
|
|
4714
4714
|
this.addActivity = (activity) => {
|
|
4715
|
-
LOGGER_SERVICE$
|
|
4715
|
+
LOGGER_SERVICE$8.info(METHOD_NAME_ADD_ACTIVITY, {
|
|
4716
4716
|
activity,
|
|
4717
4717
|
});
|
|
4718
4718
|
const key = CREATE_KEY_FN$y(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
|
|
@@ -4726,7 +4726,7 @@ class LookupUtils {
|
|
|
4726
4726
|
* @param activity - Activity descriptor matching the one passed to {@link addActivity}.
|
|
4727
4727
|
*/
|
|
4728
4728
|
this.removeActivity = (activity) => {
|
|
4729
|
-
LOGGER_SERVICE$
|
|
4729
|
+
LOGGER_SERVICE$8.info(METHOD_NAME_REMOVE_ACTIVITY, {
|
|
4730
4730
|
activity,
|
|
4731
4731
|
});
|
|
4732
4732
|
const key = CREATE_KEY_FN$y(activity.symbol, activity.context.strategyName, activity.context.exchangeName, activity.context.frameName, activity.backtest);
|
|
@@ -4738,7 +4738,7 @@ class LookupUtils {
|
|
|
4738
4738
|
* @returns Array of all activities present in the lookup map at call time.
|
|
4739
4739
|
*/
|
|
4740
4740
|
this.listActivity = () => {
|
|
4741
|
-
LOGGER_SERVICE$
|
|
4741
|
+
LOGGER_SERVICE$8.info(METHOD_NAME_LIST_ACTIVITY);
|
|
4742
4742
|
return Array.from(this._lookupMap.values());
|
|
4743
4743
|
};
|
|
4744
4744
|
}
|
|
@@ -4767,7 +4767,7 @@ const METHOD_NAME_SPIN_LOCK = "CandleUtils.spinLock";
|
|
|
4767
4767
|
*/
|
|
4768
4768
|
const ROTATE_DELAY = 50;
|
|
4769
4769
|
/** Logger service injected as DI singleton */
|
|
4770
|
-
const LOGGER_SERVICE$
|
|
4770
|
+
const LOGGER_SERVICE$7 = new LoggerService();
|
|
4771
4771
|
/**
|
|
4772
4772
|
* Process-wide coordinator for candle-fetch serialization and cooperative
|
|
4773
4773
|
* yielding between parallel backtests.
|
|
@@ -4816,7 +4816,7 @@ class CandleUtils {
|
|
|
4816
4816
|
* @param source - Caller identifier for logging.
|
|
4817
4817
|
*/
|
|
4818
4818
|
this.acquireLock = async (source) => {
|
|
4819
|
-
LOGGER_SERVICE$
|
|
4819
|
+
LOGGER_SERVICE$7.info(METHOD_NAME_ACQUIRE_LOCK, {
|
|
4820
4820
|
source,
|
|
4821
4821
|
});
|
|
4822
4822
|
if (!GLOBAL_CONFIG.CC_ENABLE_CANDLE_FETCH_MUTEX) {
|
|
@@ -4832,7 +4832,7 @@ class CandleUtils {
|
|
|
4832
4832
|
* @param source - Caller identifier for logging.
|
|
4833
4833
|
*/
|
|
4834
4834
|
this.releaseLock = async (source) => {
|
|
4835
|
-
LOGGER_SERVICE$
|
|
4835
|
+
LOGGER_SERVICE$7.info(METHOD_NAME_RELEASE_LOCK, {
|
|
4836
4836
|
source,
|
|
4837
4837
|
});
|
|
4838
4838
|
if (!GLOBAL_CONFIG.CC_ENABLE_CANDLE_FETCH_MUTEX) {
|
|
@@ -4857,7 +4857,7 @@ class CandleUtils {
|
|
|
4857
4857
|
* @param source - Caller identifier for logging.
|
|
4858
4858
|
*/
|
|
4859
4859
|
this.spinLock = async (source) => {
|
|
4860
|
-
LOGGER_SERVICE$
|
|
4860
|
+
LOGGER_SERVICE$7.info(METHOD_NAME_SPIN_LOCK, {
|
|
4861
4861
|
source,
|
|
4862
4862
|
});
|
|
4863
4863
|
if (!GLOBAL_CONFIG.CC_ENABLE_CANDLE_FETCH_MUTEX) {
|
|
@@ -6367,7 +6367,7 @@ const validateCommonSignal = (signal) => {
|
|
|
6367
6367
|
}
|
|
6368
6368
|
// Кидаем ошибку если есть проблемы
|
|
6369
6369
|
if (errors.length > 0) {
|
|
6370
|
-
throw new Error(`Invalid signal for ${signal.position} position:\n${errors.join("\n")}`);
|
|
6370
|
+
throw new Error(`Invalid signal for ${signal.position} position (${signal.symbol || "empty symbol"}):\n${errors.join("\n")}`);
|
|
6371
6371
|
}
|
|
6372
6372
|
};
|
|
6373
6373
|
|
|
@@ -6420,7 +6420,7 @@ const validatePendingSignal = (signal, currentPrice) => {
|
|
|
6420
6420
|
}
|
|
6421
6421
|
}
|
|
6422
6422
|
if (errors.length > 0) {
|
|
6423
|
-
throw new Error(`Invalid signal for ${signal.position} position:\n${errors.join("\n")}`);
|
|
6423
|
+
throw new Error(`Invalid signal for ${signal.position} position (${signal.symbol || "empty symbol"}):\n${errors.join("\n")}`);
|
|
6424
6424
|
}
|
|
6425
6425
|
validateCommonSignal(signal);
|
|
6426
6426
|
// ЗАЩИТА ОТ МОМЕНТАЛЬНОГО ЗАКРЫТИЯ: проверяем что позиция не закроется сразу после открытия
|
|
@@ -6468,7 +6468,7 @@ const validatePendingSignal = (signal, currentPrice) => {
|
|
|
6468
6468
|
}
|
|
6469
6469
|
}
|
|
6470
6470
|
if (errors.length > 0) {
|
|
6471
|
-
throw new Error(`Invalid signal for ${signal.position} position:\n${errors.join("\n")}`);
|
|
6471
|
+
throw new Error(`Invalid signal for ${signal.position} position (${signal.symbol || "empty symbol"}):\n${errors.join("\n")}`);
|
|
6472
6472
|
}
|
|
6473
6473
|
};
|
|
6474
6474
|
|
|
@@ -6521,7 +6521,7 @@ const validateScheduledSignal = (signal, currentPrice) => {
|
|
|
6521
6521
|
}
|
|
6522
6522
|
}
|
|
6523
6523
|
if (errors.length > 0) {
|
|
6524
|
-
throw new Error(`Invalid signal for ${signal.position} position:\n${errors.join("\n")}`);
|
|
6524
|
+
throw new Error(`Invalid signal for ${signal.position} position (${signal.symbol || "empty symbol"}):\n${errors.join("\n")}`);
|
|
6525
6525
|
}
|
|
6526
6526
|
validateCommonSignal(signal);
|
|
6527
6527
|
// ЗАЩИТА ОТ МОМЕНТАЛЬНОГО ЗАКРЫТИЯ scheduled сигналов
|
|
@@ -6567,7 +6567,7 @@ const validateScheduledSignal = (signal, currentPrice) => {
|
|
|
6567
6567
|
// pendingAt === 0 is allowed for scheduled signals (set to SCHEDULED_SIGNAL_PENDING_MOCK until activation)
|
|
6568
6568
|
}
|
|
6569
6569
|
if (errors.length > 0) {
|
|
6570
|
-
throw new Error(`Invalid signal for ${signal.position} position:\n${errors.join("\n")}`);
|
|
6570
|
+
throw new Error(`Invalid signal for ${signal.position} position (${signal.symbol || "empty symbol"}):\n${errors.join("\n")}`);
|
|
6571
6571
|
}
|
|
6572
6572
|
};
|
|
6573
6573
|
|
|
@@ -7014,6 +7014,13 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
7014
7014
|
if (!signal) {
|
|
7015
7015
|
return null;
|
|
7016
7016
|
}
|
|
7017
|
+
if (signal?.symbol && signal?.symbol !== self.params.execution.context.symbol) {
|
|
7018
|
+
throw new Error(`Symbol mismatch: expected ${self.params.execution.context.symbol}, got ${signal.symbol}`);
|
|
7019
|
+
}
|
|
7020
|
+
// Whipsaw protection: skip signal if its id matches the last accepted pending id
|
|
7021
|
+
if (signal.id && signal.id === self._lastPendingId) {
|
|
7022
|
+
return null;
|
|
7023
|
+
}
|
|
7017
7024
|
if (self._isStopped) {
|
|
7018
7025
|
return null;
|
|
7019
7026
|
}
|
|
@@ -7057,6 +7064,9 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
7057
7064
|
}
|
|
7058
7065
|
// Валидируем сигнал перед возвратом
|
|
7059
7066
|
validatePendingSignal(signalRow, currentPrice);
|
|
7067
|
+
if (signal.id) {
|
|
7068
|
+
self._lastPendingId = signal.id;
|
|
7069
|
+
}
|
|
7060
7070
|
return signalRow;
|
|
7061
7071
|
}
|
|
7062
7072
|
// ОЖИДАНИЕ АКТИВАЦИИ: создаем scheduled signal (risk check при активации)
|
|
@@ -7083,6 +7093,9 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
7083
7093
|
};
|
|
7084
7094
|
// Валидируем сигнал перед возвратом
|
|
7085
7095
|
validateScheduledSignal(scheduledSignalRow, currentPrice);
|
|
7096
|
+
if (signal.id) {
|
|
7097
|
+
self._lastPendingId = signal.id;
|
|
7098
|
+
}
|
|
7086
7099
|
return scheduledSignalRow;
|
|
7087
7100
|
}
|
|
7088
7101
|
const signalRow = {
|
|
@@ -7110,6 +7123,9 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
7110
7123
|
}
|
|
7111
7124
|
// Валидируем сигнал перед возвратом
|
|
7112
7125
|
validatePendingSignal(signalRow, currentPrice);
|
|
7126
|
+
if (signal.id) {
|
|
7127
|
+
self._lastPendingId = signal.id;
|
|
7128
|
+
}
|
|
7113
7129
|
return signalRow;
|
|
7114
7130
|
}, {
|
|
7115
7131
|
defaultValue: null,
|
|
@@ -7139,6 +7155,13 @@ const WAIT_FOR_INIT_FN$4 = async (self) => {
|
|
|
7139
7155
|
if (self.params.execution.context.backtest) {
|
|
7140
7156
|
return;
|
|
7141
7157
|
}
|
|
7158
|
+
// Restore last pending signal id for whipsaw protection in GET_SIGNAL_FN
|
|
7159
|
+
{
|
|
7160
|
+
const recentSignal = await PersistRecentAdapter.readRecentData(self.params.execution.context.symbol, self.params.strategyName, self.params.exchangeName, self.params.method.context.frameName, false);
|
|
7161
|
+
if (recentSignal?.id) {
|
|
7162
|
+
self._lastPendingId = recentSignal.id;
|
|
7163
|
+
}
|
|
7164
|
+
}
|
|
7142
7165
|
// Restore pending signal
|
|
7143
7166
|
const pendingSignal = await PersistSignalAdapter.readSignalData(self.params.execution.context.symbol, self.params.strategyName, self.params.exchangeName);
|
|
7144
7167
|
if (pendingSignal) {
|
|
@@ -9279,6 +9302,7 @@ class ClientStrategy {
|
|
|
9279
9302
|
this._isStopped = false;
|
|
9280
9303
|
this._pendingSignal = null;
|
|
9281
9304
|
this._lastSignalTimestamp = null;
|
|
9305
|
+
this._lastPendingId = null;
|
|
9282
9306
|
this._scheduledSignal = null;
|
|
9283
9307
|
this._cancelledSignal = null;
|
|
9284
9308
|
this._closedSignal = null;
|
|
@@ -12068,7 +12092,7 @@ const RISK_METHOD_NAME_CHECK_SIGNAL_AND_RESERVE = "MergeRisk.checkSignalAndReser
|
|
|
12068
12092
|
const RISK_METHOD_NAME_ADD_SIGNAL = "MergeRisk.addSignal";
|
|
12069
12093
|
const RISK_METHOD_NAME_REMOVE_SIGNAL = "MergeRisk.removeSignal";
|
|
12070
12094
|
/** Logger service injected as DI singleton */
|
|
12071
|
-
const LOGGER_SERVICE$
|
|
12095
|
+
const LOGGER_SERVICE$6 = new LoggerService();
|
|
12072
12096
|
/**
|
|
12073
12097
|
* Composite risk management class that combines multiple risk profiles.
|
|
12074
12098
|
*
|
|
@@ -12124,7 +12148,7 @@ class MergeRisk {
|
|
|
12124
12148
|
* @returns Promise resolving to true if all risks approve, false if any risk rejects
|
|
12125
12149
|
*/
|
|
12126
12150
|
async checkSignal(params, options = {}) {
|
|
12127
|
-
LOGGER_SERVICE$
|
|
12151
|
+
LOGGER_SERVICE$6.info(RISK_METHOD_NAME_CHECK_SIGNAL, {
|
|
12128
12152
|
params,
|
|
12129
12153
|
});
|
|
12130
12154
|
for (const [riskName, risk] of Object.entries(this._riskMap)) {
|
|
@@ -12154,7 +12178,7 @@ class MergeRisk {
|
|
|
12154
12178
|
* @returns Promise resolving to true if all risks approve (and reserved), false if any risk rejects
|
|
12155
12179
|
*/
|
|
12156
12180
|
async checkSignalAndReserve(params) {
|
|
12157
|
-
LOGGER_SERVICE$
|
|
12181
|
+
LOGGER_SERVICE$6.info(RISK_METHOD_NAME_CHECK_SIGNAL_AND_RESERVE, {
|
|
12158
12182
|
params,
|
|
12159
12183
|
});
|
|
12160
12184
|
for (const [riskName, risk] of Object.entries(this._riskMap)) {
|
|
@@ -12178,7 +12202,7 @@ class MergeRisk {
|
|
|
12178
12202
|
* @returns Promise that resolves when all risks have registered the signal
|
|
12179
12203
|
*/
|
|
12180
12204
|
async addSignal(symbol, context, positionData) {
|
|
12181
|
-
LOGGER_SERVICE$
|
|
12205
|
+
LOGGER_SERVICE$6.info(RISK_METHOD_NAME_ADD_SIGNAL, {
|
|
12182
12206
|
symbol,
|
|
12183
12207
|
context,
|
|
12184
12208
|
});
|
|
@@ -12195,7 +12219,7 @@ class MergeRisk {
|
|
|
12195
12219
|
* @returns Promise that resolves when all risks have removed the signal
|
|
12196
12220
|
*/
|
|
12197
12221
|
async removeSignal(symbol, context) {
|
|
12198
|
-
LOGGER_SERVICE$
|
|
12222
|
+
LOGGER_SERVICE$6.info(RISK_METHOD_NAME_REMOVE_SIGNAL, {
|
|
12199
12223
|
symbol,
|
|
12200
12224
|
context,
|
|
12201
12225
|
});
|
|
@@ -14988,7 +15012,7 @@ class RiskConnectionService {
|
|
|
14988
15012
|
}
|
|
14989
15013
|
|
|
14990
15014
|
/** Logger service injected as DI singleton */
|
|
14991
|
-
const LOGGER_SERVICE$
|
|
15015
|
+
const LOGGER_SERVICE$5 = new LoggerService();
|
|
14992
15016
|
/**
|
|
14993
15017
|
* Wrapper to call init method with error capture.
|
|
14994
15018
|
*/
|
|
@@ -15003,7 +15027,7 @@ const CALL_INIT_FN = functoolsKit.trycatch(async (self) => {
|
|
|
15003
15027
|
error: functoolsKit.errorData(error),
|
|
15004
15028
|
message: functoolsKit.getErrorMessage(error),
|
|
15005
15029
|
};
|
|
15006
|
-
LOGGER_SERVICE$
|
|
15030
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15007
15031
|
console.warn(message, payload);
|
|
15008
15032
|
errorEmitter.next(error);
|
|
15009
15033
|
},
|
|
@@ -15023,7 +15047,7 @@ const CALL_SIGNAL_FN = functoolsKit.trycatch(async (event, self) => {
|
|
|
15023
15047
|
error: functoolsKit.errorData(error),
|
|
15024
15048
|
message: functoolsKit.getErrorMessage(error),
|
|
15025
15049
|
};
|
|
15026
|
-
LOGGER_SERVICE$
|
|
15050
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15027
15051
|
console.warn(message, payload);
|
|
15028
15052
|
errorEmitter.next(error);
|
|
15029
15053
|
},
|
|
@@ -15043,7 +15067,7 @@ const CALL_SIGNAL_LIVE_FN = functoolsKit.trycatch(async (event, self) => {
|
|
|
15043
15067
|
error: functoolsKit.errorData(error),
|
|
15044
15068
|
message: functoolsKit.getErrorMessage(error),
|
|
15045
15069
|
};
|
|
15046
|
-
LOGGER_SERVICE$
|
|
15070
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15047
15071
|
console.warn(message, payload);
|
|
15048
15072
|
errorEmitter.next(error);
|
|
15049
15073
|
},
|
|
@@ -15063,7 +15087,7 @@ const CALL_SIGNAL_BACKTEST_FN = functoolsKit.trycatch(async (event, self) => {
|
|
|
15063
15087
|
error: functoolsKit.errorData(error),
|
|
15064
15088
|
message: functoolsKit.getErrorMessage(error),
|
|
15065
15089
|
};
|
|
15066
|
-
LOGGER_SERVICE$
|
|
15090
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15067
15091
|
console.warn(message, payload);
|
|
15068
15092
|
errorEmitter.next(error);
|
|
15069
15093
|
},
|
|
@@ -15091,7 +15115,7 @@ const CALL_BREAKEVEN_AVAILABLE_FN = functoolsKit.trycatch(async (event, self) =>
|
|
|
15091
15115
|
error: functoolsKit.errorData(error),
|
|
15092
15116
|
message: functoolsKit.getErrorMessage(error),
|
|
15093
15117
|
};
|
|
15094
|
-
LOGGER_SERVICE$
|
|
15118
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15095
15119
|
console.warn(message, payload);
|
|
15096
15120
|
errorEmitter.next(error);
|
|
15097
15121
|
},
|
|
@@ -15119,7 +15143,7 @@ const CALL_PARTIAL_PROFIT_AVAILABLE_FN = functoolsKit.trycatch(async (event, sel
|
|
|
15119
15143
|
error: functoolsKit.errorData(error),
|
|
15120
15144
|
message: functoolsKit.getErrorMessage(error),
|
|
15121
15145
|
};
|
|
15122
|
-
LOGGER_SERVICE$
|
|
15146
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15123
15147
|
console.warn(message, payload);
|
|
15124
15148
|
errorEmitter.next(error);
|
|
15125
15149
|
},
|
|
@@ -15147,7 +15171,7 @@ const CALL_PARTIAL_LOSS_AVAILABLE_FN = functoolsKit.trycatch(async (event, self)
|
|
|
15147
15171
|
error: functoolsKit.errorData(error),
|
|
15148
15172
|
message: functoolsKit.getErrorMessage(error),
|
|
15149
15173
|
};
|
|
15150
|
-
LOGGER_SERVICE$
|
|
15174
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15151
15175
|
console.warn(message, payload);
|
|
15152
15176
|
errorEmitter.next(error);
|
|
15153
15177
|
},
|
|
@@ -15175,7 +15199,7 @@ const CALL_PING_SCHEDULED_FN = functoolsKit.trycatch(async (event, self) => {
|
|
|
15175
15199
|
error: functoolsKit.errorData(error),
|
|
15176
15200
|
message: functoolsKit.getErrorMessage(error),
|
|
15177
15201
|
};
|
|
15178
|
-
LOGGER_SERVICE$
|
|
15202
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15179
15203
|
console.warn(message, payload);
|
|
15180
15204
|
errorEmitter.next(error);
|
|
15181
15205
|
},
|
|
@@ -15203,7 +15227,7 @@ const CALL_PING_IDLE_FN = functoolsKit.trycatch(async (event, self) => {
|
|
|
15203
15227
|
error: functoolsKit.errorData(error),
|
|
15204
15228
|
message: functoolsKit.getErrorMessage(error),
|
|
15205
15229
|
};
|
|
15206
|
-
LOGGER_SERVICE$
|
|
15230
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15207
15231
|
console.warn(message, payload);
|
|
15208
15232
|
errorEmitter.next(error);
|
|
15209
15233
|
},
|
|
@@ -15231,7 +15255,7 @@ const CALL_PING_ACTIVE_FN = functoolsKit.trycatch(async (event, self) => {
|
|
|
15231
15255
|
error: functoolsKit.errorData(error),
|
|
15232
15256
|
message: functoolsKit.getErrorMessage(error),
|
|
15233
15257
|
};
|
|
15234
|
-
LOGGER_SERVICE$
|
|
15258
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15235
15259
|
console.warn(message, payload);
|
|
15236
15260
|
errorEmitter.next(error);
|
|
15237
15261
|
},
|
|
@@ -15251,7 +15275,7 @@ const CALL_RISK_REJECTION_FN = functoolsKit.trycatch(async (event, self) => {
|
|
|
15251
15275
|
error: functoolsKit.errorData(error),
|
|
15252
15276
|
message: functoolsKit.getErrorMessage(error),
|
|
15253
15277
|
};
|
|
15254
|
-
LOGGER_SERVICE$
|
|
15278
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15255
15279
|
console.warn(message, payload);
|
|
15256
15280
|
errorEmitter.next(error);
|
|
15257
15281
|
},
|
|
@@ -15271,7 +15295,7 @@ const CALL_DISPOSE_FN = functoolsKit.trycatch(async (self) => {
|
|
|
15271
15295
|
error: functoolsKit.errorData(error),
|
|
15272
15296
|
message: functoolsKit.getErrorMessage(error),
|
|
15273
15297
|
};
|
|
15274
|
-
LOGGER_SERVICE$
|
|
15298
|
+
LOGGER_SERVICE$5.warn(message, payload);
|
|
15275
15299
|
console.warn(message, payload);
|
|
15276
15300
|
errorEmitter.next(error);
|
|
15277
15301
|
},
|
|
@@ -23135,7 +23159,7 @@ const REPORT_UTILS_METHOD_NAME_USE_DUMMY$1 = "ReportUtils.useDummy";
|
|
|
23135
23159
|
const REPORT_UTILS_METHOD_NAME_USE_JSONL$1 = "ReportUtils.useJsonl";
|
|
23136
23160
|
const REPORT_UTILS_METHOD_NAME_CLEAR$1 = "ReportUtils.clear";
|
|
23137
23161
|
/** Logger service injected as DI singleton */
|
|
23138
|
-
const LOGGER_SERVICE$
|
|
23162
|
+
const LOGGER_SERVICE$4 = new LoggerService();
|
|
23139
23163
|
/** Symbol key for the singleshot waitForInit function on MarkdownFileBase instances. */
|
|
23140
23164
|
const WAIT_FOR_INIT_SYMBOL$1 = Symbol("wait-for-init");
|
|
23141
23165
|
/** Symbol key for the timeout-protected write function on MarkdownFileBase instances. */
|
|
@@ -23216,7 +23240,7 @@ class MarkdownFileBase {
|
|
|
23216
23240
|
* @throws Error if stream not initialized or write timeout exceeded
|
|
23217
23241
|
*/
|
|
23218
23242
|
async dump(data, options) {
|
|
23219
|
-
LOGGER_SERVICE$
|
|
23243
|
+
LOGGER_SERVICE$4.debug(MARKDOWN_METHOD_NAME_FILE_DUMP, {
|
|
23220
23244
|
markdownName: this.markdownName,
|
|
23221
23245
|
options,
|
|
23222
23246
|
});
|
|
@@ -23296,7 +23320,7 @@ class MarkdownFolderBase {
|
|
|
23296
23320
|
* @throws Error if directory creation or file write fails
|
|
23297
23321
|
*/
|
|
23298
23322
|
async dump(content, options) {
|
|
23299
|
-
LOGGER_SERVICE$
|
|
23323
|
+
LOGGER_SERVICE$4.debug(MARKDOWN_METHOD_NAME_FOLDER_DUMP, {
|
|
23300
23324
|
markdownName: this.markdownName,
|
|
23301
23325
|
options,
|
|
23302
23326
|
});
|
|
@@ -23361,7 +23385,7 @@ class MarkdownWriterAdapter {
|
|
|
23361
23385
|
* @param Ctor - Constructor for markdown storage adapter
|
|
23362
23386
|
*/
|
|
23363
23387
|
useMarkdownAdapter(Ctor) {
|
|
23364
|
-
LOGGER_SERVICE$
|
|
23388
|
+
LOGGER_SERVICE$4.info(MARKDOWN_METHOD_NAME_USE_ADAPTER$1);
|
|
23365
23389
|
this.MarkdownFactory = Ctor;
|
|
23366
23390
|
}
|
|
23367
23391
|
/**
|
|
@@ -23375,7 +23399,7 @@ class MarkdownWriterAdapter {
|
|
|
23375
23399
|
* @throws Error if write fails or storage initialization fails
|
|
23376
23400
|
*/
|
|
23377
23401
|
async writeData(markdownName, content, options) {
|
|
23378
|
-
LOGGER_SERVICE$
|
|
23402
|
+
LOGGER_SERVICE$4.debug(MARKDOWN_METHOD_NAME_WRITE_DATA, {
|
|
23379
23403
|
markdownName,
|
|
23380
23404
|
options,
|
|
23381
23405
|
});
|
|
@@ -23389,7 +23413,7 @@ class MarkdownWriterAdapter {
|
|
|
23389
23413
|
* Each report is written as a separate .md file.
|
|
23390
23414
|
*/
|
|
23391
23415
|
useMd() {
|
|
23392
|
-
LOGGER_SERVICE$
|
|
23416
|
+
LOGGER_SERVICE$4.debug(MARKDOWN_METHOD_NAME_USE_MD$1);
|
|
23393
23417
|
this.useMarkdownAdapter(MarkdownFolderBase);
|
|
23394
23418
|
}
|
|
23395
23419
|
/**
|
|
@@ -23397,7 +23421,7 @@ class MarkdownWriterAdapter {
|
|
|
23397
23421
|
* All reports are appended to a single .jsonl file per markdown type.
|
|
23398
23422
|
*/
|
|
23399
23423
|
useJsonl() {
|
|
23400
|
-
LOGGER_SERVICE$
|
|
23424
|
+
LOGGER_SERVICE$4.debug(MARKDOWN_METHOD_NAME_USE_JSONL$1);
|
|
23401
23425
|
this.useMarkdownAdapter(MarkdownFileBase);
|
|
23402
23426
|
}
|
|
23403
23427
|
/**
|
|
@@ -23406,7 +23430,7 @@ class MarkdownWriterAdapter {
|
|
|
23406
23430
|
* so new storage instances are created with the updated base path.
|
|
23407
23431
|
*/
|
|
23408
23432
|
clear() {
|
|
23409
|
-
LOGGER_SERVICE$
|
|
23433
|
+
LOGGER_SERVICE$4.log(MARKDOWN_METHOD_NAME_CLEAR$1);
|
|
23410
23434
|
this.getMarkdownStorage.clear();
|
|
23411
23435
|
}
|
|
23412
23436
|
/**
|
|
@@ -23414,7 +23438,7 @@ class MarkdownWriterAdapter {
|
|
|
23414
23438
|
* All future markdown writes will be no-ops.
|
|
23415
23439
|
*/
|
|
23416
23440
|
useDummy() {
|
|
23417
|
-
LOGGER_SERVICE$
|
|
23441
|
+
LOGGER_SERVICE$4.debug(MARKDOWN_METHOD_NAME_USE_DUMMY$1);
|
|
23418
23442
|
this.useMarkdownAdapter(MarkdownDummy);
|
|
23419
23443
|
}
|
|
23420
23444
|
}
|
|
@@ -23475,7 +23499,7 @@ class ReportBase {
|
|
|
23475
23499
|
});
|
|
23476
23500
|
}
|
|
23477
23501
|
}, 15000));
|
|
23478
|
-
LOGGER_SERVICE$
|
|
23502
|
+
LOGGER_SERVICE$4.debug(REPORT_BASE_METHOD_NAME_CTOR, {
|
|
23479
23503
|
reportName: this.reportName,
|
|
23480
23504
|
baseDir,
|
|
23481
23505
|
});
|
|
@@ -23489,7 +23513,7 @@ class ReportBase {
|
|
|
23489
23513
|
* @returns Promise that resolves when initialization is complete
|
|
23490
23514
|
*/
|
|
23491
23515
|
async waitForInit(initial) {
|
|
23492
|
-
LOGGER_SERVICE$
|
|
23516
|
+
LOGGER_SERVICE$4.debug(REPORT_BASE_METHOD_NAME_WAIT_FOR_INIT, {
|
|
23493
23517
|
reportName: this.reportName,
|
|
23494
23518
|
initial,
|
|
23495
23519
|
});
|
|
@@ -23508,7 +23532,7 @@ class ReportBase {
|
|
|
23508
23532
|
* @throws Error if stream not initialized or write timeout exceeded
|
|
23509
23533
|
*/
|
|
23510
23534
|
async write(data, options) {
|
|
23511
|
-
LOGGER_SERVICE$
|
|
23535
|
+
LOGGER_SERVICE$4.debug(REPORT_BASE_METHOD_NAME_WRITE, {
|
|
23512
23536
|
reportName: this.reportName,
|
|
23513
23537
|
options,
|
|
23514
23538
|
});
|
|
@@ -23605,7 +23629,7 @@ class ReportWriterAdapter {
|
|
|
23605
23629
|
* @internal - Automatically called by report services, not for direct use
|
|
23606
23630
|
*/
|
|
23607
23631
|
this.writeData = async (reportName, data, options) => {
|
|
23608
|
-
LOGGER_SERVICE$
|
|
23632
|
+
LOGGER_SERVICE$4.info(REPORT_UTILS_METHOD_NAME_WRITE_DATA, {
|
|
23609
23633
|
reportName,
|
|
23610
23634
|
options,
|
|
23611
23635
|
});
|
|
@@ -23622,7 +23646,7 @@ class ReportWriterAdapter {
|
|
|
23622
23646
|
* @param Ctor - Constructor for report storage adapter
|
|
23623
23647
|
*/
|
|
23624
23648
|
useReportAdapter(Ctor) {
|
|
23625
|
-
LOGGER_SERVICE$
|
|
23649
|
+
LOGGER_SERVICE$4.info(REPORT_UTILS_METHOD_NAME_USE_REPORT_ADAPTER$1);
|
|
23626
23650
|
this.ReportFactory = Ctor;
|
|
23627
23651
|
}
|
|
23628
23652
|
/**
|
|
@@ -23631,7 +23655,7 @@ class ReportWriterAdapter {
|
|
|
23631
23655
|
* so new storage instances are created with the updated base path.
|
|
23632
23656
|
*/
|
|
23633
23657
|
clear() {
|
|
23634
|
-
LOGGER_SERVICE$
|
|
23658
|
+
LOGGER_SERVICE$4.log(REPORT_UTILS_METHOD_NAME_CLEAR$1);
|
|
23635
23659
|
this.getReportStorage.clear();
|
|
23636
23660
|
}
|
|
23637
23661
|
/**
|
|
@@ -23639,7 +23663,7 @@ class ReportWriterAdapter {
|
|
|
23639
23663
|
* All future report writes will be no-ops.
|
|
23640
23664
|
*/
|
|
23641
23665
|
useDummy() {
|
|
23642
|
-
LOGGER_SERVICE$
|
|
23666
|
+
LOGGER_SERVICE$4.log(REPORT_UTILS_METHOD_NAME_USE_DUMMY$1);
|
|
23643
23667
|
this.useReportAdapter(ReportDummy);
|
|
23644
23668
|
}
|
|
23645
23669
|
/**
|
|
@@ -23647,7 +23671,7 @@ class ReportWriterAdapter {
|
|
|
23647
23671
|
* All future report writes will use JSONL storage.
|
|
23648
23672
|
*/
|
|
23649
23673
|
useJsonl() {
|
|
23650
|
-
LOGGER_SERVICE$
|
|
23674
|
+
LOGGER_SERVICE$4.log(REPORT_UTILS_METHOD_NAME_USE_JSONL$1);
|
|
23651
23675
|
this.useReportAdapter(ReportBase);
|
|
23652
23676
|
}
|
|
23653
23677
|
}
|
|
@@ -53948,7 +53972,7 @@ const REPORT_UTILS_METHOD_NAME_USE_DUMMY = "ReportUtils.useDummy";
|
|
|
53948
53972
|
const REPORT_UTILS_METHOD_NAME_USE_JSONL = "ReportUtils.useJsonl";
|
|
53949
53973
|
const REPORT_UTILS_METHOD_NAME_CLEAR = "ReportUtils.clear";
|
|
53950
53974
|
/** Logger service injected as DI singleton */
|
|
53951
|
-
const LOGGER_SERVICE$
|
|
53975
|
+
const LOGGER_SERVICE$3 = new LoggerService();
|
|
53952
53976
|
/**
|
|
53953
53977
|
* Default configuration that enables all report services.
|
|
53954
53978
|
* Used when no specific configuration is provided to enable().
|
|
@@ -54005,7 +54029,7 @@ class ReportUtils {
|
|
|
54005
54029
|
* @returns Cleanup function that unsubscribes from all enabled services
|
|
54006
54030
|
*/
|
|
54007
54031
|
this.enable = functoolsKit.singleshot(({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, schedule = false, walker = false, strategy = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$2) => {
|
|
54008
|
-
LOGGER_SERVICE$
|
|
54032
|
+
LOGGER_SERVICE$3.debug(REPORT_UTILS_METHOD_NAME_ENABLE, {
|
|
54009
54033
|
backtest: bt,
|
|
54010
54034
|
breakeven,
|
|
54011
54035
|
heat,
|
|
@@ -54100,7 +54124,7 @@ class ReportUtils {
|
|
|
54100
54124
|
* ```
|
|
54101
54125
|
*/
|
|
54102
54126
|
this.disable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, schedule = false, walker = false, strategy = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$2) => {
|
|
54103
|
-
LOGGER_SERVICE$
|
|
54127
|
+
LOGGER_SERVICE$3.debug(REPORT_UTILS_METHOD_NAME_DISABLE, {
|
|
54104
54128
|
backtest: bt,
|
|
54105
54129
|
breakeven,
|
|
54106
54130
|
heat,
|
|
@@ -54180,7 +54204,7 @@ class ReportAdapter extends ReportUtils {
|
|
|
54180
54204
|
* @param Ctor - Constructor for report storage adapter
|
|
54181
54205
|
*/
|
|
54182
54206
|
useReportAdapter(Ctor) {
|
|
54183
|
-
LOGGER_SERVICE$
|
|
54207
|
+
LOGGER_SERVICE$3.info(REPORT_UTILS_METHOD_NAME_USE_REPORT_ADAPTER);
|
|
54184
54208
|
ReportWriter.useReportAdapter(Ctor);
|
|
54185
54209
|
}
|
|
54186
54210
|
/**
|
|
@@ -54189,7 +54213,7 @@ class ReportAdapter extends ReportUtils {
|
|
|
54189
54213
|
* so new storage instances are created with the updated base path.
|
|
54190
54214
|
*/
|
|
54191
54215
|
clear() {
|
|
54192
|
-
LOGGER_SERVICE$
|
|
54216
|
+
LOGGER_SERVICE$3.log(REPORT_UTILS_METHOD_NAME_CLEAR);
|
|
54193
54217
|
ReportWriter.clear();
|
|
54194
54218
|
}
|
|
54195
54219
|
/**
|
|
@@ -54197,7 +54221,7 @@ class ReportAdapter extends ReportUtils {
|
|
|
54197
54221
|
* All future report writes will be no-ops.
|
|
54198
54222
|
*/
|
|
54199
54223
|
useDummy() {
|
|
54200
|
-
LOGGER_SERVICE$
|
|
54224
|
+
LOGGER_SERVICE$3.log(REPORT_UTILS_METHOD_NAME_USE_DUMMY);
|
|
54201
54225
|
ReportWriter.useDummy();
|
|
54202
54226
|
}
|
|
54203
54227
|
/**
|
|
@@ -54205,7 +54229,7 @@ class ReportAdapter extends ReportUtils {
|
|
|
54205
54229
|
* All future report writes will use JSONL storage.
|
|
54206
54230
|
*/
|
|
54207
54231
|
useJsonl() {
|
|
54208
|
-
LOGGER_SERVICE$
|
|
54232
|
+
LOGGER_SERVICE$3.log(REPORT_UTILS_METHOD_NAME_USE_JSONL);
|
|
54209
54233
|
ReportWriter.useJsonl();
|
|
54210
54234
|
}
|
|
54211
54235
|
}
|
|
@@ -54223,7 +54247,7 @@ const MARKDOWN_METHOD_NAME_USE_JSONL = "MarkdownAdapter.useJsonl";
|
|
|
54223
54247
|
const MARKDOWN_METHOD_NAME_USE_DUMMY = "MarkdownAdapter.useDummy";
|
|
54224
54248
|
const MARKDOWN_METHOD_NAME_CLEAR = "MarkdownAdapter.clear";
|
|
54225
54249
|
/** Logger service injected as DI singleton */
|
|
54226
|
-
const LOGGER_SERVICE$
|
|
54250
|
+
const LOGGER_SERVICE$2 = new LoggerService();
|
|
54227
54251
|
/**
|
|
54228
54252
|
* Default configuration that enables all markdown services.
|
|
54229
54253
|
* Used when no specific configuration is provided to `enable()`.
|
|
@@ -54280,7 +54304,7 @@ class MarkdownUtils {
|
|
|
54280
54304
|
* @returns Cleanup function that unsubscribes from all enabled services
|
|
54281
54305
|
*/
|
|
54282
54306
|
this.enable = functoolsKit.singleshot(({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, strategy = false, risk = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$1) => {
|
|
54283
|
-
LOGGER_SERVICE$
|
|
54307
|
+
LOGGER_SERVICE$2.debug(MARKDOWN_METHOD_NAME_ENABLE, {
|
|
54284
54308
|
backtest: bt,
|
|
54285
54309
|
breakeven,
|
|
54286
54310
|
heat,
|
|
@@ -54377,7 +54401,7 @@ class MarkdownUtils {
|
|
|
54377
54401
|
* ```
|
|
54378
54402
|
*/
|
|
54379
54403
|
this.disable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, strategy = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$1) => {
|
|
54380
|
-
LOGGER_SERVICE$
|
|
54404
|
+
LOGGER_SERVICE$2.debug(MARKDOWN_METHOD_NAME_DISABLE, {
|
|
54381
54405
|
backtest: bt,
|
|
54382
54406
|
breakeven,
|
|
54383
54407
|
heat,
|
|
@@ -54463,7 +54487,7 @@ class MarkdownUtils {
|
|
|
54463
54487
|
* @param config.max_drawdown - Clear max drawdown report data
|
|
54464
54488
|
*/
|
|
54465
54489
|
this.clear = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, strategy = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$1) => {
|
|
54466
|
-
LOGGER_SERVICE$
|
|
54490
|
+
LOGGER_SERVICE$2.debug(MARKDOWN_METHOD_NAME_CLEAR, {
|
|
54467
54491
|
backtest: bt,
|
|
54468
54492
|
breakeven,
|
|
54469
54493
|
heat,
|
|
@@ -54538,7 +54562,7 @@ class MarkdownAdapter extends MarkdownUtils {
|
|
|
54538
54562
|
* @param Ctor - Constructor for markdown storage adapter
|
|
54539
54563
|
*/
|
|
54540
54564
|
useMarkdownAdapter(Ctor) {
|
|
54541
|
-
LOGGER_SERVICE$
|
|
54565
|
+
LOGGER_SERVICE$2.info(MARKDOWN_METHOD_NAME_USE_ADAPTER);
|
|
54542
54566
|
return MarkdownWriter.useMarkdownAdapter(Ctor);
|
|
54543
54567
|
}
|
|
54544
54568
|
/**
|
|
@@ -54547,7 +54571,7 @@ class MarkdownAdapter extends MarkdownUtils {
|
|
|
54547
54571
|
* Each dump creates a separate .md file.
|
|
54548
54572
|
*/
|
|
54549
54573
|
useMd() {
|
|
54550
|
-
LOGGER_SERVICE$
|
|
54574
|
+
LOGGER_SERVICE$2.debug(MARKDOWN_METHOD_NAME_USE_MD);
|
|
54551
54575
|
MarkdownWriter.useMd();
|
|
54552
54576
|
}
|
|
54553
54577
|
/**
|
|
@@ -54556,7 +54580,7 @@ class MarkdownAdapter extends MarkdownUtils {
|
|
|
54556
54580
|
* All dumps append to a single .jsonl file per markdown type.
|
|
54557
54581
|
*/
|
|
54558
54582
|
useJsonl() {
|
|
54559
|
-
LOGGER_SERVICE$
|
|
54583
|
+
LOGGER_SERVICE$2.debug(MARKDOWN_METHOD_NAME_USE_JSONL);
|
|
54560
54584
|
MarkdownWriter.useJsonl();
|
|
54561
54585
|
}
|
|
54562
54586
|
/**
|
|
@@ -54564,7 +54588,7 @@ class MarkdownAdapter extends MarkdownUtils {
|
|
|
54564
54588
|
* All future markdown writes will be no-ops.
|
|
54565
54589
|
*/
|
|
54566
54590
|
useDummy() {
|
|
54567
|
-
LOGGER_SERVICE$
|
|
54591
|
+
LOGGER_SERVICE$2.debug(MARKDOWN_METHOD_NAME_USE_DUMMY);
|
|
54568
54592
|
MarkdownWriter.useDummy();
|
|
54569
54593
|
}
|
|
54570
54594
|
}
|
|
@@ -63253,6 +63277,470 @@ class IntervalUtils {
|
|
|
63253
63277
|
*/
|
|
63254
63278
|
const Interval = new IntervalUtils();
|
|
63255
63279
|
|
|
63280
|
+
const CRON_METHOD_NAME_REGISTER = "CronUtils.register";
|
|
63281
|
+
const CRON_METHOD_NAME_UNREGISTER = "CronUtils.unregister";
|
|
63282
|
+
const CRON_METHOD_NAME_CLEAR = "CronUtils.clear";
|
|
63283
|
+
const CRON_METHOD_NAME_TICK = "CronUtils._tick";
|
|
63284
|
+
const CRON_METHOD_NAME_ENABLE = "CronUtils.enable";
|
|
63285
|
+
const CRON_METHOD_NAME_DISABLE = "CronUtils.disable";
|
|
63286
|
+
/**
|
|
63287
|
+
* Local logger instance.
|
|
63288
|
+
*
|
|
63289
|
+
* Created directly rather than resolved from the DI container so that
|
|
63290
|
+
* `CronUtils` has no compile-time dependency on the rest of the framework
|
|
63291
|
+
* being bootstrapped — `Cron` can be imported and used in isolation.
|
|
63292
|
+
*/
|
|
63293
|
+
const LOGGER_SERVICE$1 = new LoggerService();
|
|
63294
|
+
/**
|
|
63295
|
+
* Utility class for registering periodic tasks that fire on candle-interval
|
|
63296
|
+
* boundaries of the virtual time produced by parallel backtests.
|
|
63297
|
+
*
|
|
63298
|
+
* Exported as singleton instance `Cron` for convenient usage.
|
|
63299
|
+
*
|
|
63300
|
+
* Key property — **singleshot coordination across parallel backtests**:
|
|
63301
|
+
* when several `Backtest.background(symbol, ...)` runs hit the same aligned
|
|
63302
|
+
* boundary concurrently, the handler is invoked exactly once. Every parallel
|
|
63303
|
+
* `tick` for that boundary awaits the same in-flight promise and is released
|
|
63304
|
+
* together when the promise settles. After settlement the slot is cleared and
|
|
63305
|
+
* the next boundary produces a fresh promise.
|
|
63306
|
+
*
|
|
63307
|
+
* Typical wiring:
|
|
63308
|
+
*
|
|
63309
|
+
* @example
|
|
63310
|
+
* ```typescript
|
|
63311
|
+
* import { Cron, Backtest } from "backtest-kit";
|
|
63312
|
+
*
|
|
63313
|
+
* Cron.register({
|
|
63314
|
+
* name: "tg-signal-parser",
|
|
63315
|
+
* interval: "1h",
|
|
63316
|
+
* handler: async (symbol, when, backtest) => {
|
|
63317
|
+
* await parseTelegramSignalsToMongo(when);
|
|
63318
|
+
* },
|
|
63319
|
+
* });
|
|
63320
|
+
*
|
|
63321
|
+
* // Subscribe Cron to the engine's lifecycle subjects (beforeStart,
|
|
63322
|
+
* // idlePing, activePing, schedulePing) once at startup. After this every
|
|
63323
|
+
* // strategy tick is forwarded into Cron automatically.
|
|
63324
|
+
* Cron.enable();
|
|
63325
|
+
*
|
|
63326
|
+
* for (const symbol of ["BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "TRXUSDT"]) {
|
|
63327
|
+
* Backtest.background(symbol, { strategyName, exchangeName, frameName });
|
|
63328
|
+
* }
|
|
63329
|
+
*
|
|
63330
|
+
* // On shutdown:
|
|
63331
|
+
* // Cron.disable();
|
|
63332
|
+
* ```
|
|
63333
|
+
*/
|
|
63334
|
+
class CronUtils {
|
|
63335
|
+
constructor() {
|
|
63336
|
+
/**
|
|
63337
|
+
* Registered entries by `name`.
|
|
63338
|
+
*
|
|
63339
|
+
* Each record carries a monotonically increasing `generation` counter that
|
|
63340
|
+
* is bumped on every `register(entry)` call for the same name. The
|
|
63341
|
+
* generation participates in `firedKey` so writes from a still-in-flight
|
|
63342
|
+
* handler of a previous incarnation cannot poison `_firedOnce` for the
|
|
63343
|
+
* current incarnation — their key has a different generation suffix and
|
|
63344
|
+
* is simply ignored on lookup.
|
|
63345
|
+
*/
|
|
63346
|
+
this._entries = new Map();
|
|
63347
|
+
/** Monotonic counter used to mint new entry generations on `register`. */
|
|
63348
|
+
this._generationCounter = 0;
|
|
63349
|
+
/**
|
|
63350
|
+
* In-flight handler slots.
|
|
63351
|
+
*
|
|
63352
|
+
* Slot key shape (always includes the generation suffix `:g${generation}`;
|
|
63353
|
+
* the `:${symbol}` scope is present only in fan-out mode):
|
|
63354
|
+
* - Periodic global: `${name}:${alignedMs}:g${generation}`.
|
|
63355
|
+
* - Periodic fan-out: `${name}:${alignedMs}:${symbol}:g${generation}`.
|
|
63356
|
+
* - Fire-once global: `${name}:once:g${generation}`.
|
|
63357
|
+
* - Fire-once fan-out: `${name}:once:${symbol}:g${generation}`.
|
|
63358
|
+
*
|
|
63359
|
+
* Value is the shared in-flight handler promise. Every parallel `tick` for
|
|
63360
|
+
* the same slot key awaits this exact promise (mutex semantics) and is
|
|
63361
|
+
* released together when it settles. `_inFlight` is owned exclusively by
|
|
63362
|
+
* `_runEntry` — `clear()` does **not** touch it, so the singleshot promise
|
|
63363
|
+
* survives concurrent `clear` calls and continues to coordinate parallel
|
|
63364
|
+
* ticks until it settles.
|
|
63365
|
+
*/
|
|
63366
|
+
this._inFlight = new Map();
|
|
63367
|
+
/**
|
|
63368
|
+
* Keys of fire-once entries whose handler has already settled successfully.
|
|
63369
|
+
*
|
|
63370
|
+
* Key shape (always includes the entry generation suffix `:g${generation}`):
|
|
63371
|
+
* - Global fire-once: `${name}:g${generation}`.
|
|
63372
|
+
* - Fan-out fire-once: `${name}:${symbol}:g${generation}` — one entry per
|
|
63373
|
+
* whitelisted symbol.
|
|
63374
|
+
*
|
|
63375
|
+
* The generation suffix isolates incarnations of the same `name`: writes
|
|
63376
|
+
* landing from a still-in-flight handler of a previous `register()` carry
|
|
63377
|
+
* the old generation and are never matched by the new entry's lookup.
|
|
63378
|
+
* Stale entries are pruned by `_clearFiredOnceFor` on `register`/`unregister`
|
|
63379
|
+
* and wiped by `clear()`.
|
|
63380
|
+
*
|
|
63381
|
+
* Looked up by `_tick` to decide whether to skip; written by `_runEntry`
|
|
63382
|
+
* on successful settle.
|
|
63383
|
+
*/
|
|
63384
|
+
this._firedOnce = new Set();
|
|
63385
|
+
/**
|
|
63386
|
+
* Register a periodic cron entry.
|
|
63387
|
+
*
|
|
63388
|
+
* Idempotent on `name`: re-registering the same name replaces the previous
|
|
63389
|
+
* entry (interval/symbols/handler can all change). Re-registration does
|
|
63390
|
+
* **not** clear in-flight promises — entries still resolving complete with
|
|
63391
|
+
* the previous handler.
|
|
63392
|
+
*
|
|
63393
|
+
* @param entry - Entry configuration; see {@link CronEntry}.
|
|
63394
|
+
* @returns Disposer function — call it to unregister the entry.
|
|
63395
|
+
*
|
|
63396
|
+
* @example
|
|
63397
|
+
* ```typescript
|
|
63398
|
+
* const dispose = Cron.register({
|
|
63399
|
+
* name: "fetch-funding",
|
|
63400
|
+
* interval: "8h",
|
|
63401
|
+
* symbols: ["BTCUSDT", "ETHUSDT"],
|
|
63402
|
+
* handler: async (symbol, when, backtest) => { ... },
|
|
63403
|
+
* });
|
|
63404
|
+
* // Later:
|
|
63405
|
+
* dispose();
|
|
63406
|
+
* ```
|
|
63407
|
+
*/
|
|
63408
|
+
this.register = (entry) => {
|
|
63409
|
+
LOGGER_SERVICE$1.info(CRON_METHOD_NAME_REGISTER, {
|
|
63410
|
+
name: entry.name,
|
|
63411
|
+
interval: entry.interval,
|
|
63412
|
+
symbols: entry.symbols,
|
|
63413
|
+
});
|
|
63414
|
+
if (!entry.name) {
|
|
63415
|
+
throw new Error("CronUtils.register requires a non-empty name");
|
|
63416
|
+
}
|
|
63417
|
+
if (entry.name.includes(":")) {
|
|
63418
|
+
throw new Error(`CronUtils.register: name must not contain ':' (got "${entry.name}"). ` +
|
|
63419
|
+
`':' is reserved as the segment separator in slot keys.`);
|
|
63420
|
+
}
|
|
63421
|
+
if (entry.symbols) {
|
|
63422
|
+
for (const symbol of entry.symbols) {
|
|
63423
|
+
if (symbol.includes(":")) {
|
|
63424
|
+
throw new Error(`CronUtils.register: symbols[] entry must not contain ':' (got "${symbol}"). ` +
|
|
63425
|
+
`':' is reserved as the segment separator in slot keys.`);
|
|
63426
|
+
}
|
|
63427
|
+
}
|
|
63428
|
+
}
|
|
63429
|
+
this._clearFiredOnceFor(entry.name);
|
|
63430
|
+
const generation = ++this._generationCounter;
|
|
63431
|
+
this._entries.set(entry.name, { entry, generation });
|
|
63432
|
+
return () => this.unregister(entry.name);
|
|
63433
|
+
};
|
|
63434
|
+
/**
|
|
63435
|
+
* Remove a registered entry by name.
|
|
63436
|
+
*
|
|
63437
|
+
* Does not cancel handlers already in flight — those resolve on their own
|
|
63438
|
+
* and clear their slot via `.finally()`.
|
|
63439
|
+
*
|
|
63440
|
+
* @param name - Name passed to `register`.
|
|
63441
|
+
*/
|
|
63442
|
+
this.unregister = (name) => {
|
|
63443
|
+
LOGGER_SERVICE$1.info(CRON_METHOD_NAME_UNREGISTER, { name });
|
|
63444
|
+
this._entries.delete(name);
|
|
63445
|
+
this._clearFiredOnceFor(name);
|
|
63446
|
+
};
|
|
63447
|
+
/**
|
|
63448
|
+
* Clear fire-once marks so that fire-once entries can fire again.
|
|
63449
|
+
*
|
|
63450
|
+
* Does **not** touch `_inFlight` — that map holds shared in-flight handler
|
|
63451
|
+
* promises through which parallel `tick`s coordinate. Wiping it mid-flight
|
|
63452
|
+
* would let a new `tick` start a second handler for a boundary that's
|
|
63453
|
+
* already running, breaking the singleshot contract.
|
|
63454
|
+
*
|
|
63455
|
+
* Two modes:
|
|
63456
|
+
* - **Per-symbol** (`symbol` provided): clears only fan-out fire-once
|
|
63457
|
+
* marks for that symbol — keys of the shape `${name}:${symbol}:g${gen}`.
|
|
63458
|
+
* Global fire-once marks (`${name}:g${gen}`, no symbol component) are
|
|
63459
|
+
* left intact, since they are not attributable to a single symbol.
|
|
63460
|
+
* Useful for re-arming fan-out fire-once entries when a particular
|
|
63461
|
+
* symbol's run finishes and you want a future re-run to fire again.
|
|
63462
|
+
* - **All** (no argument): wipes every fire-once mark across all entries
|
|
63463
|
+
* and symbols. Registered entries are not removed — use `unregister`
|
|
63464
|
+
* (or the disposer returned by `register`) for that.
|
|
63465
|
+
*
|
|
63466
|
+
* **Race with in-flight handlers.** `_firedOnce` is written in
|
|
63467
|
+
* `_runEntry`'s `.finally()`, which can run *after* a concurrent
|
|
63468
|
+
* `clear()` call. In that case the fire-once mark reappears immediately
|
|
63469
|
+
* after being wiped, and the next tick will treat the entry as already
|
|
63470
|
+
* fired. This is consistent with the singleshot promise itself surviving
|
|
63471
|
+
* `clear()` — the handler is allowed to finish — and the entry's
|
|
63472
|
+
* generation suffix in `firedKey` guarantees the stale mark cannot
|
|
63473
|
+
* outlive a subsequent `register()` of the same name. If you need a hard
|
|
63474
|
+
* re-arm, `unregister` + `register` bumps the generation and makes any
|
|
63475
|
+
* late write a no-op.
|
|
63476
|
+
*
|
|
63477
|
+
* @param symbol - Optional symbol filter; if omitted, clears all fire-once
|
|
63478
|
+
* marks.
|
|
63479
|
+
*/
|
|
63480
|
+
this.clear = (symbol) => {
|
|
63481
|
+
LOGGER_SERVICE$1.info(CRON_METHOD_NAME_CLEAR, { symbol });
|
|
63482
|
+
if (!symbol) {
|
|
63483
|
+
this._firedOnce.clear();
|
|
63484
|
+
return;
|
|
63485
|
+
}
|
|
63486
|
+
const symbolSegment = `:${symbol}:`;
|
|
63487
|
+
for (const key of this._firedOnce) {
|
|
63488
|
+
if (key.includes(symbolSegment)) {
|
|
63489
|
+
this._firedOnce.delete(key);
|
|
63490
|
+
}
|
|
63491
|
+
}
|
|
63492
|
+
};
|
|
63493
|
+
/**
|
|
63494
|
+
* Process a virtual-time tick for `symbol` and fire any due cron entries.
|
|
63495
|
+
*
|
|
63496
|
+
* **Private.** Invoked exclusively by the lifecycle bridge installed in
|
|
63497
|
+
* {@link enable} — `beforeStart` / `idlePing` / `activePing` / `schedulePing`
|
|
63498
|
+
* are funneled here through a shared `singlerun` queue, so calls to
|
|
63499
|
+
* `_tick` are serialised end-to-end. Do not call directly.
|
|
63500
|
+
*
|
|
63501
|
+
* Algorithm (per registered entry):
|
|
63502
|
+
* 0. Base-align the incoming `when` down to the 1-minute boundary (`ts`).
|
|
63503
|
+
* Lifecycle subjects may emit with sub-second jitter; rounding here
|
|
63504
|
+
* guarantees that `beforeStart` / `idlePing` / `activePing` /
|
|
63505
|
+
* `schedulePing` for the same virtual minute all hash to the same
|
|
63506
|
+
* slot key.
|
|
63507
|
+
* 1. If `entry.symbols` is non-empty and does not include `symbol`, skip.
|
|
63508
|
+
* 2. Decide scope from `entry.symbols`:
|
|
63509
|
+
* - Empty/undefined → **global** (slot key has no symbol component).
|
|
63510
|
+
* - Non-empty → **fan-out**, slot key carries `:${symbol}` so each
|
|
63511
|
+
* whitelisted symbol gets its own slot and handler invocation.
|
|
63512
|
+
* 3. Append the current entry generation suffix `:g${generation}` to both
|
|
63513
|
+
* slot key and fired-once key. This isolates incarnations of the same
|
|
63514
|
+
* `name`: a `register()` after an in-flight handler bumps the
|
|
63515
|
+
* generation, so the late `_firedOnce` write from the old handler can
|
|
63516
|
+
* never block the new entry.
|
|
63517
|
+
* 4. **Fire-once** (`entry.interval === undefined`):
|
|
63518
|
+
* - If the entry's fired-once key is already in `_firedOnce`, skip.
|
|
63519
|
+
* - Slot key: `${name}:once` (+ scope) (+ gen).
|
|
63520
|
+
* - `aligned` = the 1-minute-aligned `when` from step 0.
|
|
63521
|
+
* 5. **Periodic** (`entry.interval` set):
|
|
63522
|
+
* - Align `when` further to the entry's interval via {@link alignToInterval}.
|
|
63523
|
+
* - If `ts !== alignedMs`, the tick is mid-interval — skip.
|
|
63524
|
+
* (This is the "remainder === 0" boundary check from the spec;
|
|
63525
|
+
* since `ts` is already on the 1-minute boundary, the check is exact
|
|
63526
|
+
* for `1m` and consistent for higher intervals.)
|
|
63527
|
+
* - Slot key: `${name}:${alignedMs}` (+ scope) (+ gen).
|
|
63528
|
+
* 6. Singleshot per slot key: look up the slot in `_inFlight`. If a promise
|
|
63529
|
+
* already exists, `await` the same promise. Otherwise invoke
|
|
63530
|
+
* `entry.handler`, store the promise, and `await` it. The slot is
|
|
63531
|
+
* removed in `.finally()` so the next boundary creates a fresh promise;
|
|
63532
|
+
* for fire-once entries the fired-once key is also added to
|
|
63533
|
+
* `_firedOnce` on success so subsequent ticks skip it.
|
|
63534
|
+
*
|
|
63535
|
+
* Errors thrown by `handler` are caught, logged via `console.error`, and
|
|
63536
|
+
* **not** rethrown — a failing handler must not break the per-symbol
|
|
63537
|
+
* tick loop or unblock other parallel backtests with an unhandled
|
|
63538
|
+
* rejection. A failed fire-once handler is **not** marked as fired and
|
|
63539
|
+
* will retry on the next tick.
|
|
63540
|
+
*
|
|
63541
|
+
* Requires active method context and execution context.
|
|
63542
|
+
*
|
|
63543
|
+
* @param symbol - Trading symbol from the current tick.
|
|
63544
|
+
* @param when - Virtual time of the current tick.
|
|
63545
|
+
* @param backtest - `true` for backtest ticks, `false` for live ticks.
|
|
63546
|
+
* Forwarded as the third argument to `entry.handler`. Only the value
|
|
63547
|
+
* from the tick that **opens** a given slot is observed by all parallel
|
|
63548
|
+
* awaiters of that slot.
|
|
63549
|
+
* @throws Error if method or execution context is missing.
|
|
63550
|
+
*/
|
|
63551
|
+
this._tick = async (symbol, when, backtest) => {
|
|
63552
|
+
LOGGER_SERVICE$1.debug(CRON_METHOD_NAME_TICK, {
|
|
63553
|
+
symbol,
|
|
63554
|
+
when,
|
|
63555
|
+
});
|
|
63556
|
+
if (!MethodContextService.hasContext()) {
|
|
63557
|
+
throw new Error("CronUtils _tick requires method context");
|
|
63558
|
+
}
|
|
63559
|
+
if (!ExecutionContextService.hasContext()) {
|
|
63560
|
+
throw new Error("CronUtils _tick requires execution context");
|
|
63561
|
+
}
|
|
63562
|
+
const ts = alignToInterval(when, "1m").getTime();
|
|
63563
|
+
const taskList = [];
|
|
63564
|
+
for (const { entry, generation } of this._entries.values()) {
|
|
63565
|
+
if (entry.symbols?.length && !entry.symbols.includes(symbol)) {
|
|
63566
|
+
continue;
|
|
63567
|
+
}
|
|
63568
|
+
const perSymbol = !!entry.symbols?.length;
|
|
63569
|
+
const scope = perSymbol ? `:${symbol}` : "";
|
|
63570
|
+
const genSuffix = `:g${generation}`;
|
|
63571
|
+
let aligned;
|
|
63572
|
+
let alignedMs;
|
|
63573
|
+
let slotKey;
|
|
63574
|
+
let firedKey;
|
|
63575
|
+
if (entry.interval === undefined) {
|
|
63576
|
+
const onceKey = `${entry.name}${scope}${genSuffix}`;
|
|
63577
|
+
if (this._firedOnce.has(onceKey)) {
|
|
63578
|
+
continue;
|
|
63579
|
+
}
|
|
63580
|
+
aligned = alignToInterval(when, "1m");
|
|
63581
|
+
alignedMs = ts;
|
|
63582
|
+
slotKey = `${entry.name}:once${scope}${genSuffix}`;
|
|
63583
|
+
firedKey = onceKey;
|
|
63584
|
+
}
|
|
63585
|
+
else {
|
|
63586
|
+
aligned = alignToInterval(when, entry.interval);
|
|
63587
|
+
alignedMs = aligned.getTime();
|
|
63588
|
+
if (ts !== alignedMs) {
|
|
63589
|
+
continue;
|
|
63590
|
+
}
|
|
63591
|
+
slotKey = `${entry.name}:${alignedMs}${scope}${genSuffix}`;
|
|
63592
|
+
firedKey = null;
|
|
63593
|
+
}
|
|
63594
|
+
let pending = this._inFlight.get(slotKey);
|
|
63595
|
+
if (!pending) {
|
|
63596
|
+
pending = this._runEntry(entry, symbol, aligned, alignedMs, slotKey, firedKey, backtest);
|
|
63597
|
+
this._inFlight.set(slotKey, pending);
|
|
63598
|
+
}
|
|
63599
|
+
taskList.push(pending);
|
|
63600
|
+
}
|
|
63601
|
+
await Promise.all(taskList);
|
|
63602
|
+
};
|
|
63603
|
+
/**
|
|
63604
|
+
* Subscribe `Cron` to the engine's strategy lifecycle subjects so registered
|
|
63605
|
+
* entries fire automatically — no manual wiring of `listenTickBacktest` /
|
|
63606
|
+
* `listenSchedulePing` etc. needed.
|
|
63607
|
+
*
|
|
63608
|
+
* Subjects funneled into {@link _tick}:
|
|
63609
|
+
* - `beforeStartSubject` — first event of every run.
|
|
63610
|
+
* - `idlePingSubject` — every tick when no signal is pending or scheduled.
|
|
63611
|
+
* - `activePingSubject` — every tick while a pending signal is being monitored.
|
|
63612
|
+
* - `schedulePingSubject` — every tick while a scheduled signal is being monitored.
|
|
63613
|
+
*
|
|
63614
|
+
* All four subjects are subscribed to a single `singlerun`-wrapped
|
|
63615
|
+
* handler that builds `_tick(event.symbol, new Date(event.timestamp),
|
|
63616
|
+
* event.backtest)`. `singlerun` merges the four streams into one serial
|
|
63617
|
+
* queue: at most one `_tick` runs at a time, the next waits. This matters
|
|
63618
|
+
* because the engine can emit `beforeStart` and an immediate `idlePing`
|
|
63619
|
+
* on the very same minute, and concurrent `_tick`s on the same
|
|
63620
|
+
* `(symbol, minute)` would otherwise race to open the same `_inFlight`
|
|
63621
|
+
* slot before either commit. Together these four sources cover every
|
|
63622
|
+
* tick the engine processes for every `(symbol, virtual-minute)` pair
|
|
63623
|
+
* regardless of whether the strategy is idle, active, or scheduled.
|
|
63624
|
+
*
|
|
63625
|
+
* `enable` itself is wrapped in `singleshot`, so calling it repeatedly is
|
|
63626
|
+
* a no-op — subsequent calls return the same disposer. The disposer
|
|
63627
|
+
* unsubscribes from every subject and resets the singleshot so a future
|
|
63628
|
+
* `enable()` can re-subscribe cleanly. Equivalent to the
|
|
63629
|
+
* `RecentAdapter.enable` pattern.
|
|
63630
|
+
*
|
|
63631
|
+
* The `.subscribe` callbacks are synchronous wrappers around the
|
|
63632
|
+
* `singlerun`-async handler; `_tick`'s returned promise is awaited inside
|
|
63633
|
+
* `singlerun` to enforce ordering but not bubbled back to the subject.
|
|
63634
|
+
* Errors are caught and logged inside `_runEntry`.
|
|
63635
|
+
*
|
|
63636
|
+
* @returns Cleanup function that unsubscribes from all four subjects and
|
|
63637
|
+
* resets the singleshot. Idempotent.
|
|
63638
|
+
*
|
|
63639
|
+
* @example
|
|
63640
|
+
* ```typescript
|
|
63641
|
+
* import { Cron } from "backtest-kit";
|
|
63642
|
+
*
|
|
63643
|
+
* Cron.register({ name: "tg-parser", interval: "1h", handler });
|
|
63644
|
+
* Cron.enable(); // wire once at startup
|
|
63645
|
+
* // ... run backtests / live as usual
|
|
63646
|
+
* Cron.disable(); // on shutdown
|
|
63647
|
+
* ```
|
|
63648
|
+
*/
|
|
63649
|
+
this.enable = functoolsKit.singleshot(() => {
|
|
63650
|
+
LOGGER_SERVICE$1.info(CRON_METHOD_NAME_ENABLE);
|
|
63651
|
+
const handleTick = functoolsKit.singlerun(async (event) => {
|
|
63652
|
+
return await this._tick(event.symbol, new Date(event.timestamp), event.backtest);
|
|
63653
|
+
});
|
|
63654
|
+
const unBeforeStart = beforeStartSubject.subscribe(handleTick);
|
|
63655
|
+
const unIdlePing = idlePingSubject.subscribe(handleTick);
|
|
63656
|
+
const unActivePing = activePingSubject.subscribe(handleTick);
|
|
63657
|
+
const unSchedulePing = schedulePingSubject.subscribe(handleTick);
|
|
63658
|
+
return functoolsKit.compose(() => unBeforeStart(), () => unIdlePing(), () => unActivePing(), () => unSchedulePing(), () => this.enable.clear());
|
|
63659
|
+
});
|
|
63660
|
+
/**
|
|
63661
|
+
* Tear down the lifecycle subscriptions installed by {@link enable}.
|
|
63662
|
+
*
|
|
63663
|
+
* Safe to call multiple times and safe to call before `enable()` — both
|
|
63664
|
+
* are no-ops. Does **not** unregister entries, does **not** touch
|
|
63665
|
+
* `_inFlight`, and does **not** wipe `_firedOnce` (use `unregister` or
|
|
63666
|
+
* `clear()` for those).
|
|
63667
|
+
*/
|
|
63668
|
+
this.disable = () => {
|
|
63669
|
+
LOGGER_SERVICE$1.info(CRON_METHOD_NAME_DISABLE);
|
|
63670
|
+
if (this.enable.hasValue()) {
|
|
63671
|
+
const lastSubscription = this.enable();
|
|
63672
|
+
lastSubscription();
|
|
63673
|
+
}
|
|
63674
|
+
};
|
|
63675
|
+
}
|
|
63676
|
+
/**
|
|
63677
|
+
* Garbage-collect every `_firedOnce` key that belongs to the entry `name`
|
|
63678
|
+
* (any generation, global or fan-out).
|
|
63679
|
+
*
|
|
63680
|
+
* Called from `register`/`unregister` to free memory; **not** required
|
|
63681
|
+
* for correctness — the generation suffix already isolates re-registrations,
|
|
63682
|
+
* so leftover keys from old generations can never block a new entry.
|
|
63683
|
+
* They just sit unused until they are GC'd here or wiped by `clear()`.
|
|
63684
|
+
*/
|
|
63685
|
+
_clearFiredOnceFor(name) {
|
|
63686
|
+
if (!name) {
|
|
63687
|
+
return;
|
|
63688
|
+
}
|
|
63689
|
+
const prefix = `${name}:`;
|
|
63690
|
+
for (const key of this._firedOnce) {
|
|
63691
|
+
if (key === name || key.startsWith(prefix)) {
|
|
63692
|
+
this._firedOnce.delete(key);
|
|
63693
|
+
}
|
|
63694
|
+
}
|
|
63695
|
+
}
|
|
63696
|
+
/**
|
|
63697
|
+
* Build the singleshot promise for a single in-flight slot.
|
|
63698
|
+
*
|
|
63699
|
+
* Invokes `entry.handler(symbol, aligned, backtest)`, swallows and logs
|
|
63700
|
+
* any error via `console.error`, and clears the `_inFlight` slot
|
|
63701
|
+
* in `.finally()` so the next boundary produces a fresh promise. For
|
|
63702
|
+
* fire-once entries `firedKey` is added to `_firedOnce` on success so
|
|
63703
|
+
* subsequent ticks skip it.
|
|
63704
|
+
*
|
|
63705
|
+
* @param firedKey - Key to add to `_firedOnce` on success, or `null` for
|
|
63706
|
+
* periodic entries (which never populate `_firedOnce`).
|
|
63707
|
+
* @param backtest - Value forwarded as the third handler argument; the
|
|
63708
|
+
* "winner" tick's flag is what all parallel awaiters of this slot see.
|
|
63709
|
+
*/
|
|
63710
|
+
async _runEntry(entry, symbol, aligned, alignedMs, slotKey, firedKey, backtest) {
|
|
63711
|
+
let failed = false;
|
|
63712
|
+
try {
|
|
63713
|
+
await entry.handler(symbol, aligned, backtest);
|
|
63714
|
+
}
|
|
63715
|
+
catch (err) {
|
|
63716
|
+
failed = true;
|
|
63717
|
+
console.error(`${CRON_METHOD_NAME_TICK} entry "${entry.name}" failed`, { symbol, alignedMs, err });
|
|
63718
|
+
}
|
|
63719
|
+
finally {
|
|
63720
|
+
this._inFlight.delete(slotKey);
|
|
63721
|
+
if (!failed && firedKey !== null) {
|
|
63722
|
+
this._firedOnce.add(firedKey);
|
|
63723
|
+
}
|
|
63724
|
+
}
|
|
63725
|
+
}
|
|
63726
|
+
}
|
|
63727
|
+
/**
|
|
63728
|
+
* Singleton instance of {@link CronUtils} for registering periodic tasks
|
|
63729
|
+
* coordinated across parallel `Backtest.background` runs.
|
|
63730
|
+
*
|
|
63731
|
+
* @example
|
|
63732
|
+
* ```typescript
|
|
63733
|
+
* import { Cron } from "backtest-kit";
|
|
63734
|
+
*
|
|
63735
|
+
* Cron.register({
|
|
63736
|
+
* name: "tg-parser",
|
|
63737
|
+
* interval: "1h",
|
|
63738
|
+
* handler: async (symbol, when, backtest) => { ... },
|
|
63739
|
+
* });
|
|
63740
|
+
* ```
|
|
63741
|
+
*/
|
|
63742
|
+
const Cron = new CronUtils();
|
|
63743
|
+
|
|
63256
63744
|
const BREAKEVEN_METHOD_NAME_GET_DATA = "BreakevenUtils.getData";
|
|
63257
63745
|
const BREAKEVEN_METHOD_NAME_GET_REPORT = "BreakevenUtils.getReport";
|
|
63258
63746
|
const BREAKEVEN_METHOD_NAME_DUMP = "BreakevenUtils.dump";
|
|
@@ -64335,7 +64823,7 @@ const validateSignal = (signal, currentPrice) => {
|
|
|
64335
64823
|
}
|
|
64336
64824
|
}
|
|
64337
64825
|
if (errors.length > 0) {
|
|
64338
|
-
console.error(`Invalid signal for ${signal.position} position:\n${errors.join("\n")}`);
|
|
64826
|
+
console.error(`Invalid signal for ${signal.position} position (${signal.symbol || "empty symbol"}):\n${errors.join("\n")}`);
|
|
64339
64827
|
return false;
|
|
64340
64828
|
}
|
|
64341
64829
|
try {
|
|
@@ -64408,7 +64896,7 @@ const validateSignal = (signal, currentPrice) => {
|
|
|
64408
64896
|
}
|
|
64409
64897
|
}
|
|
64410
64898
|
if (errors.length > 0) {
|
|
64411
|
-
console.error(`Invalid signal for ${signal.position} position:\n${errors.join("\n")}`);
|
|
64899
|
+
console.error(`Invalid signal for ${signal.position} position (${signal.symbol || "empty symbol"}):\n${errors.join("\n")}`);
|
|
64412
64900
|
}
|
|
64413
64901
|
return !errors.length;
|
|
64414
64902
|
};
|
|
@@ -64420,6 +64908,7 @@ exports.Broker = Broker;
|
|
|
64420
64908
|
exports.BrokerBase = BrokerBase;
|
|
64421
64909
|
exports.Cache = Cache;
|
|
64422
64910
|
exports.Constant = Constant;
|
|
64911
|
+
exports.Cron = Cron;
|
|
64423
64912
|
exports.Dump = Dump;
|
|
64424
64913
|
exports.Exchange = Exchange;
|
|
64425
64914
|
exports.ExecutionContextService = ExecutionContextService;
|
|
@@ -64510,6 +64999,8 @@ exports.addSizingSchema = addSizingSchema;
|
|
|
64510
64999
|
exports.addStrategySchema = addStrategySchema;
|
|
64511
65000
|
exports.addWalkerSchema = addWalkerSchema;
|
|
64512
65001
|
exports.alignToInterval = alignToInterval;
|
|
65002
|
+
exports.beginContext = beginContext;
|
|
65003
|
+
exports.beginTime = beginTime;
|
|
64513
65004
|
exports.cacheCandles = cacheCandles;
|
|
64514
65005
|
exports.checkCandles = checkCandles;
|
|
64515
65006
|
exports.commitActivateScheduled = commitActivateScheduled;
|
|
@@ -64692,6 +65183,7 @@ exports.shutdown = shutdown;
|
|
|
64692
65183
|
exports.slPercentShiftToPrice = slPercentShiftToPrice;
|
|
64693
65184
|
exports.slPriceToPercentShift = slPriceToPercentShift;
|
|
64694
65185
|
exports.stopStrategy = stopStrategy;
|
|
65186
|
+
exports.toPlainString = toPlainString;
|
|
64695
65187
|
exports.toProfitLossDto = toProfitLossDto;
|
|
64696
65188
|
exports.tpPercentShiftToPrice = tpPercentShiftToPrice;
|
|
64697
65189
|
exports.tpPriceToPercentShift = tpPriceToPercentShift;
|