backtest-kit 9.0.2 → 9.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.mjs CHANGED
@@ -1438,7 +1438,7 @@ class PersistRiskInstance {
1438
1438
  *
1439
1439
  * @returns Promise resolving to positions (empty array if none persisted)
1440
1440
  */
1441
- async readPositionData() {
1441
+ async readPositionData(_when) {
1442
1442
  if (await this._storage.hasValue(PersistRiskInstance.STORAGE_KEY)) {
1443
1443
  return await this._storage.readValue(PersistRiskInstance.STORAGE_KEY);
1444
1444
  }
@@ -1448,9 +1448,10 @@ class PersistRiskInstance {
1448
1448
  * Writes the positions array using the fixed STORAGE_KEY.
1449
1449
  *
1450
1450
  * @param riskRow - Position entries to persist
1451
+ * @param when - Logical timestamp (reserved for API consistency; not used)
1451
1452
  * @returns Promise that resolves when write is complete
1452
1453
  */
1453
- async writePositionData(riskRow) {
1454
+ async writePositionData(riskRow, _when) {
1454
1455
  await this._storage.writeValue(PersistRiskInstance.STORAGE_KEY, riskRow);
1455
1456
  }
1456
1457
  }
@@ -1475,12 +1476,12 @@ class PersistRiskDummyInstance {
1475
1476
  * Always returns empty positions array.
1476
1477
  * @returns Promise resolving to []
1477
1478
  */
1478
- async readPositionData() { return []; }
1479
+ async readPositionData(_when) { return []; }
1479
1480
  /**
1480
1481
  * No-op write (discards positions).
1481
1482
  * @returns Promise that resolves immediately
1482
1483
  */
1483
- async writePositionData(_riskRow) { }
1484
+ async writePositionData(_riskRow, _when) { }
1484
1485
  }
1485
1486
  /**
1486
1487
  * Utility class for managing risk active positions persistence.
@@ -1510,15 +1511,16 @@ class PersistRiskUtils {
1510
1511
  *
1511
1512
  * @param riskName - Risk profile identifier
1512
1513
  * @param exchangeName - Exchange identifier
1514
+ * @param when - Logical timestamp at which the read is happening (reserved for API consistency)
1513
1515
  * @returns Promise resolving to position entries (empty array if none)
1514
1516
  */
1515
- this.readPositionData = async (riskName, exchangeName) => {
1517
+ this.readPositionData = async (riskName, exchangeName, when) => {
1516
1518
  LOGGER_SERVICE$7.info(PERSIST_RISK_UTILS_METHOD_NAME_READ_DATA);
1517
1519
  const key = `${riskName}:${exchangeName}`;
1518
1520
  const isInitial = !this.getRiskStorage.has(key);
1519
1521
  const instance = this.getRiskStorage(riskName, exchangeName);
1520
1522
  await instance.waitForInit(isInitial);
1521
- return instance.readPositionData();
1523
+ return instance.readPositionData(when);
1522
1524
  };
1523
1525
  /**
1524
1526
  * Writes active positions for the given risk context.
@@ -1527,15 +1529,16 @@ class PersistRiskUtils {
1527
1529
  * @param riskRow - Position entries to persist
1528
1530
  * @param riskName - Risk profile identifier
1529
1531
  * @param exchangeName - Exchange identifier
1532
+ * @param when - Logical timestamp this write belongs to (reserved for API consistency)
1530
1533
  * @returns Promise that resolves when write is complete
1531
1534
  */
1532
- this.writePositionData = async (riskRow, riskName, exchangeName) => {
1535
+ this.writePositionData = async (riskRow, riskName, exchangeName, when) => {
1533
1536
  LOGGER_SERVICE$7.info(PERSIST_RISK_UTILS_METHOD_NAME_WRITE_DATA);
1534
1537
  const key = `${riskName}:${exchangeName}`;
1535
1538
  const isInitial = !this.getRiskStorage.has(key);
1536
1539
  const instance = this.getRiskStorage(riskName, exchangeName);
1537
1540
  await instance.waitForInit(isInitial);
1538
- return instance.writePositionData(riskRow);
1541
+ return instance.writePositionData(riskRow, when);
1539
1542
  };
1540
1543
  }
1541
1544
  /**
@@ -1829,7 +1832,7 @@ class PersistPartialInstance {
1829
1832
  * @param signalId - Signal identifier
1830
1833
  * @returns Promise resolving to partial data record (empty object if not found)
1831
1834
  */
1832
- async readPartialData(signalId) {
1835
+ async readPartialData(signalId, _when) {
1833
1836
  if (await this._storage.hasValue(signalId)) {
1834
1837
  return await this._storage.readValue(signalId);
1835
1838
  }
@@ -1840,9 +1843,10 @@ class PersistPartialInstance {
1840
1843
  *
1841
1844
  * @param data - Partial data record to persist
1842
1845
  * @param signalId - Signal identifier
1846
+ * @param when - Logical timestamp (reserved for API consistency; not used)
1843
1847
  * @returns Promise that resolves when write is complete
1844
1848
  */
1845
- async writePartialData(data, signalId) {
1849
+ async writePartialData(data, signalId, _when) {
1846
1850
  await this._storage.writeValue(signalId, data);
1847
1851
  }
1848
1852
  }
@@ -1865,12 +1869,12 @@ class PersistPartialDummyInstance {
1865
1869
  * Always returns empty partial data record.
1866
1870
  * @returns Promise resolving to {}
1867
1871
  */
1868
- async readPartialData(_signalId) { return {}; }
1872
+ async readPartialData(_signalId, _when) { return {}; }
1869
1873
  /**
1870
1874
  * No-op write (discards partial data).
1871
1875
  * @returns Promise that resolves immediately
1872
1876
  */
1873
- async writePartialData(_data, _signalId) { }
1877
+ async writePartialData(_data, _signalId, _when) { }
1874
1878
  }
1875
1879
  /**
1876
1880
  * Utility class for managing partial profit/loss levels persistence.
@@ -1903,15 +1907,16 @@ class PersistPartialUtils {
1903
1907
  * @param strategyName - Strategy identifier
1904
1908
  * @param signalId - Signal identifier
1905
1909
  * @param exchangeName - Exchange identifier
1910
+ * @param when - Logical timestamp at which the read is happening (reserved for API consistency)
1906
1911
  * @returns Promise resolving to partial data record (empty object if none)
1907
1912
  */
1908
- this.readPartialData = async (symbol, strategyName, signalId, exchangeName) => {
1913
+ this.readPartialData = async (symbol, strategyName, signalId, exchangeName, when) => {
1909
1914
  LOGGER_SERVICE$7.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_READ_DATA);
1910
1915
  const key = `${symbol}:${strategyName}:${exchangeName}`;
1911
1916
  const isInitial = !this.getPartialStorage.has(key);
1912
1917
  const instance = this.getPartialStorage(symbol, strategyName, exchangeName);
1913
1918
  await instance.waitForInit(isInitial);
1914
- return instance.readPartialData(signalId);
1919
+ return instance.readPartialData(signalId, when);
1915
1920
  };
1916
1921
  /**
1917
1922
  * Writes partial data for the given context and signalId.
@@ -1922,15 +1927,16 @@ class PersistPartialUtils {
1922
1927
  * @param strategyName - Strategy identifier
1923
1928
  * @param signalId - Signal identifier
1924
1929
  * @param exchangeName - Exchange identifier
1930
+ * @param when - Logical timestamp this write belongs to (reserved for API consistency)
1925
1931
  * @returns Promise that resolves when write is complete
1926
1932
  */
1927
- this.writePartialData = async (partialData, symbol, strategyName, signalId, exchangeName) => {
1933
+ this.writePartialData = async (partialData, symbol, strategyName, signalId, exchangeName, when) => {
1928
1934
  LOGGER_SERVICE$7.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_WRITE_DATA);
1929
1935
  const key = `${symbol}:${strategyName}:${exchangeName}`;
1930
1936
  const isInitial = !this.getPartialStorage.has(key);
1931
1937
  const instance = this.getPartialStorage(symbol, strategyName, exchangeName);
1932
1938
  await instance.waitForInit(isInitial);
1933
- return instance.writePartialData(partialData, signalId);
1939
+ return instance.writePartialData(partialData, signalId, when);
1934
1940
  };
1935
1941
  }
1936
1942
  /**
@@ -2029,7 +2035,7 @@ class PersistBreakevenInstance {
2029
2035
  * @param signalId - Signal identifier
2030
2036
  * @returns Promise resolving to breakeven data record (empty object if not found)
2031
2037
  */
2032
- async readBreakevenData(signalId) {
2038
+ async readBreakevenData(signalId, _when) {
2033
2039
  if (await this._storage.hasValue(signalId)) {
2034
2040
  return await this._storage.readValue(signalId);
2035
2041
  }
@@ -2040,9 +2046,10 @@ class PersistBreakevenInstance {
2040
2046
  *
2041
2047
  * @param data - Breakeven data record to persist
2042
2048
  * @param signalId - Signal identifier
2049
+ * @param when - Logical timestamp (reserved for API consistency; not used)
2043
2050
  * @returns Promise that resolves when write is complete
2044
2051
  */
2045
- async writeBreakevenData(data, signalId) {
2052
+ async writeBreakevenData(data, signalId, _when) {
2046
2053
  await this._storage.writeValue(signalId, data);
2047
2054
  }
2048
2055
  }
@@ -2065,12 +2072,12 @@ class PersistBreakevenDummyInstance {
2065
2072
  * Always returns empty breakeven data record.
2066
2073
  * @returns Promise resolving to {}
2067
2074
  */
2068
- async readBreakevenData(_signalId) { return {}; }
2075
+ async readBreakevenData(_signalId, _when) { return {}; }
2069
2076
  /**
2070
2077
  * No-op write (discards breakeven data).
2071
2078
  * @returns Promise that resolves immediately
2072
2079
  */
2073
- async writeBreakevenData(_data, _signalId) { }
2080
+ async writeBreakevenData(_data, _signalId, _when) { }
2074
2081
  }
2075
2082
  /**
2076
2083
  * Persistence utility class for breakeven state management.
@@ -2123,15 +2130,16 @@ class PersistBreakevenUtils {
2123
2130
  * @param strategyName - Strategy identifier
2124
2131
  * @param signalId - Signal identifier
2125
2132
  * @param exchangeName - Exchange identifier
2133
+ * @param when - Logical timestamp at which the read is happening (reserved for API consistency)
2126
2134
  * @returns Promise resolving to breakeven data record (empty object if none)
2127
2135
  */
2128
- this.readBreakevenData = async (symbol, strategyName, signalId, exchangeName) => {
2136
+ this.readBreakevenData = async (symbol, strategyName, signalId, exchangeName, when) => {
2129
2137
  LOGGER_SERVICE$7.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_READ_DATA);
2130
2138
  const key = `${symbol}:${strategyName}:${exchangeName}`;
2131
2139
  const isInitial = !this.getBreakevenStorage.has(key);
2132
2140
  const instance = this.getBreakevenStorage(symbol, strategyName, exchangeName);
2133
2141
  await instance.waitForInit(isInitial);
2134
- return instance.readBreakevenData(signalId);
2142
+ return instance.readBreakevenData(signalId, when);
2135
2143
  };
2136
2144
  /**
2137
2145
  * Writes breakeven data for the given context and signalId.
@@ -2142,15 +2150,16 @@ class PersistBreakevenUtils {
2142
2150
  * @param strategyName - Strategy identifier
2143
2151
  * @param signalId - Signal identifier
2144
2152
  * @param exchangeName - Exchange identifier
2153
+ * @param when - Logical timestamp this write belongs to (reserved for API consistency)
2145
2154
  * @returns Promise that resolves when write is complete
2146
2155
  */
2147
- this.writeBreakevenData = async (breakevenData, symbol, strategyName, signalId, exchangeName) => {
2156
+ this.writeBreakevenData = async (breakevenData, symbol, strategyName, signalId, exchangeName, when) => {
2148
2157
  LOGGER_SERVICE$7.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_WRITE_DATA);
2149
2158
  const key = `${symbol}:${strategyName}:${exchangeName}`;
2150
2159
  const isInitial = !this.getBreakevenStorage.has(key);
2151
2160
  const instance = this.getBreakevenStorage(symbol, strategyName, exchangeName);
2152
2161
  await instance.waitForInit(isInitial);
2153
- return instance.writeBreakevenData(breakevenData, signalId);
2162
+ return instance.writeBreakevenData(breakevenData, signalId, when);
2154
2163
  };
2155
2164
  }
2156
2165
  /**
@@ -14136,57 +14145,10 @@ const get = (object, path) => {
14136
14145
  return pathArrayFlat.reduce((obj, key) => obj && obj[key], object);
14137
14146
  };
14138
14147
 
14139
- const MS_PER_MINUTE$6 = 60000;
14140
- const INTERVAL_MINUTES$6 = {
14141
- "1m": 1,
14142
- "3m": 3,
14143
- "5m": 5,
14144
- "15m": 15,
14145
- "30m": 30,
14146
- "1h": 60,
14147
- "2h": 120,
14148
- "4h": 240,
14149
- "6h": 360,
14150
- "8h": 480,
14151
- "1d": 1440,
14152
- };
14153
- /**
14154
- * Aligns timestamp down to the nearest interval boundary.
14155
- * For example, for 15m interval: 00:17 -> 00:15, 00:44 -> 00:30
14156
- *
14157
- * Candle timestamp convention:
14158
- * - Candle timestamp = openTime (when candle opens)
14159
- * - Candle with timestamp 00:00 covers period [00:00, 00:15) for 15m interval
14160
- *
14161
- * Adapter contract:
14162
- * - Adapter must return candles with timestamp = openTime
14163
- * - First returned candle.timestamp must equal aligned since
14164
- * - Adapter must return exactly `limit` candles
14165
- *
14166
- * @param date - Date to align
14167
- * @param interval - Candle interval (e.g., "1m", "15m", "1h")
14168
- * @returns New Date aligned down to interval boundary
14169
- */
14170
- const alignToInterval = (date, interval) => {
14171
- const minutes = INTERVAL_MINUTES$6[interval];
14172
- if (minutes === undefined) {
14173
- throw new Error(`alignToInterval: unknown interval=${interval}`);
14174
- }
14175
- const intervalMs = minutes * MS_PER_MINUTE$6;
14176
- return new Date(Math.floor(date.getTime() / intervalMs) * intervalMs);
14177
- };
14178
-
14179
14148
  /** Used to prevent race confition between concurent strategies */
14180
14149
  const RISK_LOCK = new Lock();
14181
14150
  /** Symbol indicating that positions need to be fetched from persistence */
14182
14151
  const POSITION_NEED_FETCH = Symbol("risk-need-fetch");
14183
- /** Get timestamp from execution context or fallback to aligned current time */
14184
- const GET_CONTEXT_TIMESTAMP_FN = (self) => {
14185
- if (ExecutionContextService.hasContext()) {
14186
- return self.params.execution.context.when.getTime();
14187
- }
14188
- return alignToInterval(new Date(), "1m").getTime();
14189
- };
14190
14152
  /** Zero PNL constant for scheduled signals (which don't have priceOpen or PNL yet) */
14191
14153
  const ZERO_PNL = { pnlPercentage: 0, priceOpen: 0, priceClose: 0, pnlCost: 0, pnlEntries: 0 };
14192
14154
  /**
@@ -14312,7 +14274,7 @@ const CALL_ALLOWED_CALLBACKS_FN = trycatch(async (self, symbol, params) => {
14312
14274
  *
14313
14275
  * In backtest mode, initializes with empty Map. In live mode, reads from persist storage.
14314
14276
  */
14315
- const WAIT_FOR_INIT_FN$3 = async (self) => {
14277
+ const WAIT_FOR_INIT_FN$3 = async (when, self) => {
14316
14278
  self.params.logger.debug("ClientRisk waitForInit", {
14317
14279
  backtest: self.params.backtest,
14318
14280
  });
@@ -14320,7 +14282,7 @@ const WAIT_FOR_INIT_FN$3 = async (self) => {
14320
14282
  self._activePositions = new Map();
14321
14283
  return;
14322
14284
  }
14323
- const persistedPositions = await PersistRiskAdapter.readPositionData(self.params.riskName, self.params.exchangeName);
14285
+ const persistedPositions = await PersistRiskAdapter.readPositionData(self.params.riskName, self.params.exchangeName, when);
14324
14286
  self._activePositions = new Map(persistedPositions);
14325
14287
  };
14326
14288
  /**
@@ -14349,7 +14311,7 @@ class ClientRisk {
14349
14311
  * Uses singleshot pattern to ensure initialization happens exactly once.
14350
14312
  * Skips persistence in backtest mode.
14351
14313
  */
14352
- this.waitForInit = singleshot(async () => await WAIT_FOR_INIT_FN$3(this));
14314
+ this.waitForInit = singleshot(async (when) => await WAIT_FOR_INIT_FN$3(when, this));
14353
14315
  /**
14354
14316
  * Checks if a signal should be allowed based on risk limits.
14355
14317
  *
@@ -14371,11 +14333,15 @@ class ClientRisk {
14371
14333
  });
14372
14334
  await RISK_LOCK.acquireLock();
14373
14335
  try {
14336
+ const timestamp = await this.params.time.getTimestamp(params.symbol, {
14337
+ strategyName: params.strategyName,
14338
+ exchangeName: params.exchangeName,
14339
+ frameName: params.frameName,
14340
+ }, this.params.backtest);
14374
14341
  if (this._activePositions === POSITION_NEED_FETCH) {
14375
- await this.waitForInit();
14342
+ await this.waitForInit(new Date(timestamp));
14376
14343
  }
14377
14344
  const riskMap = this._activePositions;
14378
- const timestamp = GET_CONTEXT_TIMESTAMP_FN(this);
14379
14345
  const payload = {
14380
14346
  ...params,
14381
14347
  currentSignal: TO_RISK_SIGNAL(params.currentSignal, params.currentPrice, timestamp),
@@ -14478,14 +14444,14 @@ class ClientRisk {
14478
14444
  * Persists current active positions to disk.
14479
14445
  * Skips in backtest mode.
14480
14446
  */
14481
- async _updatePositions() {
14447
+ async _updatePositions(when) {
14482
14448
  if (this.params.backtest) {
14483
14449
  return;
14484
14450
  }
14485
14451
  if (this._activePositions === POSITION_NEED_FETCH) {
14486
- await this.waitForInit();
14452
+ await this.waitForInit(when);
14487
14453
  }
14488
- await PersistRiskAdapter.writePositionData(Array.from(this._activePositions), this.params.riskName, this.params.exchangeName);
14454
+ await PersistRiskAdapter.writePositionData(Array.from(this._activePositions), this.params.riskName, this.params.exchangeName, when);
14489
14455
  }
14490
14456
  /**
14491
14457
  * Registers a new opened signal.
@@ -14500,8 +14466,9 @@ class ClientRisk {
14500
14466
  });
14501
14467
  await RISK_LOCK.acquireLock();
14502
14468
  try {
14469
+ const timestamp = await this.params.time.getTimestamp(symbol, context, this.params.backtest);
14503
14470
  if (this._activePositions === POSITION_NEED_FETCH) {
14504
- await this.waitForInit();
14471
+ await this.waitForInit(new Date(timestamp));
14505
14472
  }
14506
14473
  const key = CREATE_NAME_FN(context.strategyName, context.exchangeName, symbol);
14507
14474
  const riskMap = this._activePositions;
@@ -14517,7 +14484,7 @@ class ClientRisk {
14517
14484
  minuteEstimatedTime: positionData.minuteEstimatedTime,
14518
14485
  openTimestamp: positionData.openTimestamp,
14519
14486
  });
14520
- await this._updatePositions();
14487
+ await this._updatePositions(new Date(timestamp));
14521
14488
  }
14522
14489
  finally {
14523
14490
  await RISK_LOCK.releaseLock();
@@ -14535,13 +14502,14 @@ class ClientRisk {
14535
14502
  });
14536
14503
  await RISK_LOCK.acquireLock();
14537
14504
  try {
14505
+ const timestamp = await this.params.time.getTimestamp(symbol, context, this.params.backtest);
14538
14506
  if (this._activePositions === POSITION_NEED_FETCH) {
14539
- await this.waitForInit();
14507
+ await this.waitForInit(new Date(timestamp));
14540
14508
  }
14541
14509
  const key = CREATE_NAME_FN(context.strategyName, context.exchangeName, symbol);
14542
14510
  const riskMap = this._activePositions;
14543
14511
  riskMap.delete(key);
14544
- await this._updatePositions();
14512
+ await this._updatePositions(new Date(timestamp));
14545
14513
  }
14546
14514
  finally {
14547
14515
  await RISK_LOCK.releaseLock();
@@ -14641,7 +14609,7 @@ class RiskConnectionService {
14641
14609
  constructor() {
14642
14610
  this.loggerService = inject(TYPES.loggerService);
14643
14611
  this.riskSchemaService = inject(TYPES.riskSchemaService);
14644
- this.executionContextService = inject(TYPES.executionContextService);
14612
+ this.timeMetaService = inject(TYPES.timeMetaService);
14645
14613
  /**
14646
14614
  * Action core service injected from DI container.
14647
14615
  */
@@ -14663,7 +14631,7 @@ class RiskConnectionService {
14663
14631
  return new ClientRisk({
14664
14632
  ...schema,
14665
14633
  logger: this.loggerService,
14666
- execution: this.executionContextService,
14634
+ time: this.timeMetaService,
14667
14635
  backtest,
14668
14636
  exchangeName,
14669
14637
  onRejected: CREATE_COMMIT_REJECTION_FN(this, exchangeName, frameName),
@@ -19654,8 +19622,8 @@ class BacktestLogicPrivateService {
19654
19622
  }
19655
19623
 
19656
19624
  const EMITTER_CHECK_INTERVAL = 5000;
19657
- const MS_PER_MINUTE$5 = 60000;
19658
- const INTERVAL_MINUTES$5 = {
19625
+ const MS_PER_MINUTE$6 = 60000;
19626
+ const INTERVAL_MINUTES$6 = {
19659
19627
  "1m": 1,
19660
19628
  "3m": 3,
19661
19629
  "5m": 5,
@@ -19670,7 +19638,7 @@ const INTERVAL_MINUTES$5 = {
19670
19638
  };
19671
19639
  const createEmitter = memoize(([interval]) => `${interval}`, (interval) => {
19672
19640
  const tickSubject = new Subject();
19673
- const intervalMs = INTERVAL_MINUTES$5[interval] * MS_PER_MINUTE$5;
19641
+ const intervalMs = INTERVAL_MINUTES$6[interval] * MS_PER_MINUTE$6;
19674
19642
  {
19675
19643
  let lastAligned = Math.floor(Date.now() / intervalMs) * intervalMs;
19676
19644
  Source.fromInterval(EMITTER_CHECK_INTERVAL)
@@ -19697,6 +19665,46 @@ const waitForCandle = async (interval) => {
19697
19665
  return emitter.toPromise();
19698
19666
  };
19699
19667
 
19668
+ const MS_PER_MINUTE$5 = 60000;
19669
+ const INTERVAL_MINUTES$5 = {
19670
+ "1m": 1,
19671
+ "3m": 3,
19672
+ "5m": 5,
19673
+ "15m": 15,
19674
+ "30m": 30,
19675
+ "1h": 60,
19676
+ "2h": 120,
19677
+ "4h": 240,
19678
+ "6h": 360,
19679
+ "8h": 480,
19680
+ "1d": 1440,
19681
+ };
19682
+ /**
19683
+ * Aligns timestamp down to the nearest interval boundary.
19684
+ * For example, for 15m interval: 00:17 -> 00:15, 00:44 -> 00:30
19685
+ *
19686
+ * Candle timestamp convention:
19687
+ * - Candle timestamp = openTime (when candle opens)
19688
+ * - Candle with timestamp 00:00 covers period [00:00, 00:15) for 15m interval
19689
+ *
19690
+ * Adapter contract:
19691
+ * - Adapter must return candles with timestamp = openTime
19692
+ * - First returned candle.timestamp must equal aligned since
19693
+ * - Adapter must return exactly `limit` candles
19694
+ *
19695
+ * @param date - Date to align
19696
+ * @param interval - Candle interval (e.g., "1m", "15m", "1h")
19697
+ * @returns New Date aligned down to interval boundary
19698
+ */
19699
+ const alignToInterval = (date, interval) => {
19700
+ const minutes = INTERVAL_MINUTES$5[interval];
19701
+ if (minutes === undefined) {
19702
+ throw new Error(`alignToInterval: unknown interval=${interval}`);
19703
+ }
19704
+ const intervalMs = minutes * MS_PER_MINUTE$5;
19705
+ return new Date(Math.floor(date.getTime() / intervalMs) * intervalMs);
19706
+ };
19707
+
19700
19708
  /**
19701
19709
  * Private service for live trading orchestration using async generators.
19702
19710
  *
@@ -27195,7 +27203,7 @@ const HANDLE_PROFIT_FN = async (symbol, data, currentPrice, revenuePercent, back
27195
27203
  }
27196
27204
  }
27197
27205
  if (shouldPersist) {
27198
- await self._persistState(symbol, data.strategyName, data.exchangeName, self.params.signalId);
27206
+ await self._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, self.params.signalId);
27199
27207
  }
27200
27208
  };
27201
27209
  /**
@@ -27245,7 +27253,7 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
27245
27253
  }
27246
27254
  }
27247
27255
  if (shouldPersist) {
27248
- await self._persistState(symbol, data.strategyName, data.exchangeName, self.params.signalId);
27256
+ await self._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, self.params.signalId);
27249
27257
  }
27250
27258
  };
27251
27259
  /**
@@ -27262,7 +27270,7 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
27262
27270
  * @param backtest - True if backtest mode, false if live mode
27263
27271
  * @param self - ClientPartial instance reference
27264
27272
  */
27265
- const WAIT_FOR_INIT_FN$1 = async (symbol, strategyName, exchangeName, backtest, self) => {
27273
+ const WAIT_FOR_INIT_FN$1 = async (symbol, strategyName, exchangeName, frameName, backtest, self) => {
27266
27274
  self.params.logger.debug("ClientPartial waitForInit", {
27267
27275
  symbol,
27268
27276
  backtest,
@@ -27278,7 +27286,12 @@ const WAIT_FOR_INIT_FN$1 = async (symbol, strategyName, exchangeName, backtest,
27278
27286
  self.params.logger.debug("ClientPartial waitForInit: skipping persist read in backtest mode");
27279
27287
  return;
27280
27288
  }
27281
- const partialData = await PersistPartialAdapter.readPartialData(symbol, strategyName, self.params.signalId, exchangeName);
27289
+ const timestamp = await self.params.time.getTimestamp(symbol, {
27290
+ strategyName,
27291
+ exchangeName,
27292
+ frameName,
27293
+ }, self.params.backtest);
27294
+ const partialData = await PersistPartialAdapter.readPartialData(symbol, strategyName, self.params.signalId, exchangeName, new Date(timestamp));
27282
27295
  for (const [signalId, data] of Object.entries(partialData)) {
27283
27296
  const state = {
27284
27297
  profitLevels: new Set(data.profitLevels),
@@ -27386,7 +27399,7 @@ class ClientPartial {
27386
27399
  * // Now profit()/loss() can be called
27387
27400
  * ```
27388
27401
  */
27389
- this.waitForInit = singleshot(async (symbol, strategyName, exchangeName, backtest) => await WAIT_FOR_INIT_FN$1(symbol, strategyName, exchangeName, backtest, this));
27402
+ this.waitForInit = singleshot(async (symbol, strategyName, exchangeName, frameName, backtest) => await WAIT_FOR_INIT_FN$1(symbol, strategyName, exchangeName, frameName, backtest, this));
27390
27403
  }
27391
27404
  /**
27392
27405
  * Persists current partial state to disk.
@@ -27404,7 +27417,7 @@ class ClientPartial {
27404
27417
  * @param signalId - Signal identifier
27405
27418
  * @returns Promise that resolves when persistence is complete
27406
27419
  */
27407
- async _persistState(symbol, strategyName, exchangeName, signalId) {
27420
+ async _persistState(symbol, strategyName, exchangeName, frameName, signalId) {
27408
27421
  if (this.params.backtest) {
27409
27422
  return;
27410
27423
  }
@@ -27419,7 +27432,12 @@ class ClientPartial {
27419
27432
  lossLevels: Array.from(state.lossLevels),
27420
27433
  };
27421
27434
  }
27422
- await PersistPartialAdapter.writePartialData(partialData, symbol, strategyName, signalId, exchangeName);
27435
+ const timestamp = await this.params.time.getTimestamp(symbol, {
27436
+ strategyName,
27437
+ exchangeName,
27438
+ frameName,
27439
+ }, this.params.backtest);
27440
+ await PersistPartialAdapter.writePartialData(partialData, symbol, strategyName, signalId, exchangeName, new Date(timestamp));
27423
27441
  }
27424
27442
  /**
27425
27443
  * Processes profit state and emits events for newly reached profit levels.
@@ -27544,7 +27562,7 @@ class ClientPartial {
27544
27562
  throw new Error(`Signal ID mismatch: expected ${this.params.signalId}, got ${data.id}`);
27545
27563
  }
27546
27564
  this._states.delete(data.id);
27547
- await this._persistState(symbol, data.strategyName, data.exchangeName, this.params.signalId);
27565
+ await this._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, this.params.signalId);
27548
27566
  }
27549
27567
  }
27550
27568
 
@@ -27669,6 +27687,7 @@ class PartialConnectionService {
27669
27687
  * Action core service injected from DI container.
27670
27688
  */
27671
27689
  this.actionCoreService = inject(TYPES.actionCoreService);
27690
+ this.timeMetaService = inject(TYPES.timeMetaService);
27672
27691
  /**
27673
27692
  * Memoized factory function for ClientPartial instances.
27674
27693
  *
@@ -27682,6 +27701,7 @@ class PartialConnectionService {
27682
27701
  return new ClientPartial({
27683
27702
  signalId,
27684
27703
  logger: this.loggerService,
27704
+ time: this.timeMetaService,
27685
27705
  backtest,
27686
27706
  onProfit: CREATE_COMMIT_PROFIT_FN(this),
27687
27707
  onLoss: CREATE_COMMIT_LOSS_FN(this),
@@ -27711,7 +27731,7 @@ class PartialConnectionService {
27711
27731
  when,
27712
27732
  });
27713
27733
  const partial = this.getPartial(data.id, backtest);
27714
- await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
27734
+ await partial.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
27715
27735
  return await partial.profit(symbol, data, currentPrice, revenuePercent, backtest, when);
27716
27736
  };
27717
27737
  /**
@@ -27738,7 +27758,7 @@ class PartialConnectionService {
27738
27758
  when,
27739
27759
  });
27740
27760
  const partial = this.getPartial(data.id, backtest);
27741
- await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
27761
+ await partial.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
27742
27762
  return await partial.loss(symbol, data, currentPrice, lossPercent, backtest, when);
27743
27763
  };
27744
27764
  /**
@@ -27766,7 +27786,7 @@ class PartialConnectionService {
27766
27786
  backtest,
27767
27787
  });
27768
27788
  const partial = this.getPartial(data.id, backtest);
27769
- await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
27789
+ await partial.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
27770
27790
  await partial.clear(symbol, data, priceClose, backtest);
27771
27791
  const key = CREATE_KEY_FN$l(data.id, backtest);
27772
27792
  this.getPartial.clear(key);
@@ -28492,7 +28512,7 @@ const HANDLE_BREAKEVEN_FN = async (symbol, data, currentPrice, backtest, when, s
28492
28512
  // Emit event
28493
28513
  await self.params.onBreakeven(symbol, data.strategyName, data.exchangeName, data.frameName, data, currentPrice, backtest, when.getTime());
28494
28514
  // Persist state
28495
- await self._persistState(symbol, data.strategyName, data.exchangeName, self.params.signalId);
28515
+ await self._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, self.params.signalId);
28496
28516
  return true;
28497
28517
  };
28498
28518
  /**
@@ -28507,7 +28527,7 @@ const HANDLE_BREAKEVEN_FN = async (symbol, data, currentPrice, backtest, when, s
28507
28527
  * @param exchangeName - Exchange identifier
28508
28528
  * @param self - ClientBreakeven instance reference
28509
28529
  */
28510
- const WAIT_FOR_INIT_FN = async (symbol, strategyName, exchangeName, backtest, self) => {
28530
+ const WAIT_FOR_INIT_FN = async (symbol, strategyName, exchangeName, frameName, backtest, self) => {
28511
28531
  self.params.logger.debug("ClientBreakeven waitForInit", {
28512
28532
  symbol,
28513
28533
  strategyName,
@@ -28523,7 +28543,12 @@ const WAIT_FOR_INIT_FN = async (symbol, strategyName, exchangeName, backtest, se
28523
28543
  self.params.logger.debug("ClientBreakeven waitForInit: skipping persist read in backtest mode");
28524
28544
  return;
28525
28545
  }
28526
- const breakevenData = await PersistBreakevenAdapter.readBreakevenData(symbol, strategyName, self.params.signalId, exchangeName);
28546
+ const timestamp = await self.params.time.getTimestamp(symbol, {
28547
+ strategyName,
28548
+ exchangeName,
28549
+ frameName,
28550
+ }, self.params.backtest);
28551
+ const breakevenData = await PersistBreakevenAdapter.readBreakevenData(symbol, strategyName, self.params.signalId, exchangeName, new Date(timestamp));
28527
28552
  for (const [signalId, data] of Object.entries(breakevenData)) {
28528
28553
  const state = {
28529
28554
  reached: data.reached,
@@ -28628,7 +28653,7 @@ class ClientBreakeven {
28628
28653
  * // Now check() can be called
28629
28654
  * ```
28630
28655
  */
28631
- this.waitForInit = singleshot(async (symbol, strategyName, exchangeName, backtest) => await WAIT_FOR_INIT_FN(symbol, strategyName, exchangeName, backtest, this));
28656
+ this.waitForInit = singleshot(async (symbol, strategyName, exchangeName, frameName, backtest) => await WAIT_FOR_INIT_FN(symbol, strategyName, exchangeName, frameName, backtest, this));
28632
28657
  }
28633
28658
  /**
28634
28659
  * Persists current breakeven state to disk.
@@ -28645,7 +28670,7 @@ class ClientBreakeven {
28645
28670
  * @param signalId - Signal identifier
28646
28671
  * @returns Promise that resolves when persistence is complete
28647
28672
  */
28648
- async _persistState(symbol, strategyName, exchangeName, signalId) {
28673
+ async _persistState(symbol, strategyName, exchangeName, frameName, signalId) {
28649
28674
  if (this.params.backtest) {
28650
28675
  return;
28651
28676
  }
@@ -28659,7 +28684,12 @@ class ClientBreakeven {
28659
28684
  reached: state.reached,
28660
28685
  };
28661
28686
  }
28662
- await PersistBreakevenAdapter.writeBreakevenData(breakevenData, symbol, strategyName, signalId, exchangeName);
28687
+ const timestamp = await this.params.time.getTimestamp(symbol, {
28688
+ strategyName,
28689
+ exchangeName,
28690
+ frameName,
28691
+ }, this.params.backtest);
28692
+ await PersistBreakevenAdapter.writeBreakevenData(breakevenData, symbol, strategyName, signalId, exchangeName, new Date(timestamp));
28663
28693
  }
28664
28694
  /**
28665
28695
  * Checks if breakeven should be triggered and emits event if conditions met.
@@ -28750,7 +28780,7 @@ class ClientBreakeven {
28750
28780
  throw new Error(`Signal ID mismatch: expected ${this.params.signalId}, got ${data.id}`);
28751
28781
  }
28752
28782
  this._states.delete(data.id);
28753
- await this._persistState(symbol, data.strategyName, data.exchangeName, this.params.signalId);
28783
+ await this._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, this.params.signalId);
28754
28784
  }
28755
28785
  }
28756
28786
 
@@ -28839,6 +28869,7 @@ class BreakevenConnectionService {
28839
28869
  * Action core service injected from DI container.
28840
28870
  */
28841
28871
  this.actionCoreService = inject(TYPES.actionCoreService);
28872
+ this.timeMetaService = inject(TYPES.timeMetaService);
28842
28873
  /**
28843
28874
  * Memoized factory function for ClientBreakeven instances.
28844
28875
  *
@@ -28852,6 +28883,7 @@ class BreakevenConnectionService {
28852
28883
  return new ClientBreakeven({
28853
28884
  signalId,
28854
28885
  logger: this.loggerService,
28886
+ time: this.timeMetaService,
28855
28887
  backtest,
28856
28888
  onBreakeven: CREATE_COMMIT_BREAKEVEN_FN(this),
28857
28889
  });
@@ -28878,7 +28910,7 @@ class BreakevenConnectionService {
28878
28910
  when,
28879
28911
  });
28880
28912
  const breakeven = this.getBreakeven(data.id, backtest);
28881
- await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
28913
+ await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
28882
28914
  return await breakeven.check(symbol, data, currentPrice, backtest, when);
28883
28915
  };
28884
28916
  /**
@@ -28907,7 +28939,7 @@ class BreakevenConnectionService {
28907
28939
  backtest,
28908
28940
  });
28909
28941
  const breakeven = this.getBreakeven(data.id, backtest);
28910
- await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
28942
+ await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
28911
28943
  await breakeven.clear(symbol, data, priceClose, backtest);
28912
28944
  const key = CREATE_KEY_FN$i(data.id, backtest);
28913
28945
  this.getBreakeven.clear(key);
@@ -36520,6 +36552,80 @@ function getActionSchema(actionName) {
36520
36552
  return backtest.actionSchemaService.get(actionName);
36521
36553
  }
36522
36554
 
36555
+ const WAIT_FOR_READY_METHOD_NAME = "init.waitForReady";
36556
+ const MAX_WAIT_SECONDS = 10;
36557
+ const SECOND_DELAY = 1000;
36558
+ /**
36559
+ * Blocks until the schema registries needed to start trading are populated.
36560
+ *
36561
+ * Polls `exchangeValidationService`, `frameValidationService` and
36562
+ * `strategyValidationService` once per second for up to `MAX_WAIT_SECONDS`
36563
+ * seconds. The loop exits as soon as the required registries are non-empty
36564
+ * for the given mode:
36565
+ *
36566
+ * - Backtest mode (`isBacktest = true`): exchange, frame and strategy schemas
36567
+ * must all be registered (frames define the historical window).
36568
+ * - Live mode (`isBacktest = false`): only exchange and strategy schemas are
36569
+ * required — frames are unused.
36570
+ *
36571
+ * Useful at startup when schemas are registered asynchronously (lazy imports,
36572
+ * remote config, plugin loading) and the caller wants to delay `Backtest`/
36573
+ * `Live` invocation until everything is ready. If the timeout elapses without
36574
+ * the registries filling in, the function returns silently — the caller is
36575
+ * expected to surface a clearer error from the subsequent `Backtest`/`Live`
36576
+ * call (e.g. "no strategy registered").
36577
+ *
36578
+ * @param isBacktest - Whether to additionally require a registered frame schema. Defaults to `true`.
36579
+ * @returns Promise that resolves when the registries are ready or the timeout elapses.
36580
+ *
36581
+ * @example
36582
+ * ```typescript
36583
+ * import { waitForReady, Backtest } from "backtest-kit";
36584
+ *
36585
+ * import "./schemas/exchange";
36586
+ * import "./schemas/strategy";
36587
+ * import "./schemas/frame";
36588
+ *
36589
+ * await waitForReady();
36590
+ * Backtest.background("BTCUSDT", { strategyName, exchangeName, frameName });
36591
+ * ```
36592
+ */
36593
+ async function waitForReady(isBacktest = true) {
36594
+ backtest.loggerService.info(WAIT_FOR_READY_METHOD_NAME, { isBacktest });
36595
+ for (let i = 0; i !== MAX_WAIT_SECONDS; i++) {
36596
+ const [exchangeList, frameList, strategyList] = await Promise.all([
36597
+ backtest.exchangeValidationService.list(),
36598
+ backtest.frameValidationService.list(),
36599
+ backtest.strategyValidationService.list(),
36600
+ ]);
36601
+ if (isBacktest && !frameList.length) {
36602
+ backtest.loggerService.debug(WAIT_FOR_READY_METHOD_NAME, {
36603
+ reason: "no frames registered",
36604
+ attempt: i + 1,
36605
+ });
36606
+ await sleep(SECOND_DELAY);
36607
+ continue;
36608
+ }
36609
+ if (!exchangeList.length) {
36610
+ backtest.loggerService.debug(WAIT_FOR_READY_METHOD_NAME, {
36611
+ reason: "no exchanges registered",
36612
+ attempt: i + 1,
36613
+ });
36614
+ await sleep(SECOND_DELAY);
36615
+ continue;
36616
+ }
36617
+ if (!strategyList.length) {
36618
+ backtest.loggerService.debug(WAIT_FOR_READY_METHOD_NAME, {
36619
+ reason: "no strategies registered",
36620
+ attempt: i + 1,
36621
+ });
36622
+ await sleep(SECOND_DELAY);
36623
+ continue;
36624
+ }
36625
+ break;
36626
+ }
36627
+ }
36628
+
36523
36629
  const GET_CANDLES_METHOD_NAME = "exchange.getCandles";
36524
36630
  const GET_AVERAGE_PRICE_METHOD_NAME = "exchange.getAveragePrice";
36525
36631
  const GET_CLOSE_PRICE_METHOD_NAME = "exchange.getClosePrice";
@@ -63523,4 +63629,4 @@ const validateSignal = (signal, currentPrice) => {
63523
63629
  return !errors.length;
63524
63630
  };
63525
63631
 
63526
- export { ActionBase, Backtest, Breakeven, Broker, BrokerBase, Cache, Constant, Dump, Exchange, ExecutionContextService, Heat, HighestProfit, Interval, Live, Log, Markdown, MarkdownFileBase, MarkdownFolderBase, MarkdownWriter, MaxDrawdown, Memory, MemoryBacktest, MemoryBacktestAdapter, MemoryLive, MemoryLiveAdapter, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistBreakevenInstance, PersistCandleAdapter, PersistCandleInstance, PersistIntervalAdapter, PersistIntervalInstance, PersistLogAdapter, PersistLogInstance, PersistMeasureAdapter, PersistMeasureInstance, PersistMemoryAdapter, PersistMemoryInstance, PersistNotificationAdapter, PersistNotificationInstance, PersistPartialAdapter, PersistPartialInstance, PersistRecentAdapter, PersistRecentInstance, PersistRiskAdapter, PersistRiskInstance, PersistScheduleAdapter, PersistScheduleInstance, PersistSessionAdapter, PersistSessionInstance, PersistSignalAdapter, PersistSignalInstance, PersistStateAdapter, PersistStateInstance, PersistStorageAdapter, PersistStorageInstance, Position, PositionSize, Recent, RecentBacktest, RecentLive, Reflect$1 as Reflect, Report, ReportBase, ReportWriter, Risk, Schedule, Session, SessionBacktest, SessionLive, State, StateBacktest, StateBacktestAdapter, StateLive, StateLiveAdapter, Storage, StorageBacktest, StorageLive, Strategy, Sync, System, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialLossCost, commitPartialProfit, commitPartialProfitCost, commitSignalNotify, commitTrailingStop, commitTrailingStopCost, commitTrailingTake, commitTrailingTakeCost, createSignalState, dumpAgentAnswer, dumpError, dumpJson, dumpRecord, dumpTable, dumpText, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getBreakeven, getCandles, getClosePrice, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getEffectivePriceOpen, getExchangeSchema, getFrameSchema, getLatestSignal, getMaxDrawdownDistancePnlCost, getMaxDrawdownDistancePnlPercentage, getMinutesSinceLatestSignalCreated, getMode, getNextCandles, getOrderBook, getPendingSignal, getPositionActiveMinutes, getPositionCountdownMinutes, getPositionDrawdownMinutes, getPositionEffectivePrice, getPositionEntries, getPositionEntryOverlap, getPositionEstimateMinutes, getPositionHighestMaxDrawdownPnlCost, getPositionHighestMaxDrawdownPnlPercentage, getPositionHighestPnlCost, getPositionHighestPnlPercentage, getPositionHighestProfitBreakeven, getPositionHighestProfitDistancePnlCost, getPositionHighestProfitDistancePnlPercentage, getPositionHighestProfitMinutes, getPositionHighestProfitPrice, getPositionHighestProfitTimestamp, getPositionInvestedCost, getPositionInvestedCount, getPositionLevels, getPositionMaxDrawdownMinutes, getPositionMaxDrawdownPnlCost, getPositionMaxDrawdownPnlPercentage, getPositionMaxDrawdownPrice, getPositionMaxDrawdownTimestamp, getPositionPartialOverlap, getPositionPartials, getPositionPnlCost, getPositionPnlPercent, getPositionWaitingMinutes, getRawCandles, getRiskSchema, getScheduledSignal, getSessionData, getSignalState, getSizingSchema, getStrategySchema, getSymbol, getTimestamp, getTotalClosed, getTotalCostClosed, getTotalPercentClosed, getWalkerSchema, hasNoPendingSignal, hasNoScheduledSignal, hasTradeContext, intervalStepMs, investedCostToPercent, backtest as lib, listExchangeSchema, listFrameSchema, listMemory, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenHighestProfit, listenHighestProfitOnce, listenIdlePing, listenIdlePingOnce, listenMaxDrawdown, listenMaxDrawdownOnce, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalNotify, listenSignalNotifyOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenSync, listenSyncOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, percentDiff, percentToCloseCost, percentValue, readMemory, removeMemory, roundTicks, runInMockContext, searchMemory, set, setColumns, setConfig, setLogger, setSessionData, setSignalState, shutdown, slPercentShiftToPrice, slPriceToPercentShift, stopStrategy, toProfitLossDto, tpPercentShiftToPrice, tpPriceToPercentShift, validate, validateCommonSignal, validatePendingSignal, validateScheduledSignal, validateSignal, waitForCandle, warmCandles, writeMemory };
63632
+ export { ActionBase, Backtest, Breakeven, Broker, BrokerBase, Cache, Constant, Dump, Exchange, ExecutionContextService, Heat, HighestProfit, Interval, Live, Log, Markdown, MarkdownFileBase, MarkdownFolderBase, MarkdownWriter, MaxDrawdown, Memory, MemoryBacktest, MemoryBacktestAdapter, MemoryLive, MemoryLiveAdapter, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistBreakevenInstance, PersistCandleAdapter, PersistCandleInstance, PersistIntervalAdapter, PersistIntervalInstance, PersistLogAdapter, PersistLogInstance, PersistMeasureAdapter, PersistMeasureInstance, PersistMemoryAdapter, PersistMemoryInstance, PersistNotificationAdapter, PersistNotificationInstance, PersistPartialAdapter, PersistPartialInstance, PersistRecentAdapter, PersistRecentInstance, PersistRiskAdapter, PersistRiskInstance, PersistScheduleAdapter, PersistScheduleInstance, PersistSessionAdapter, PersistSessionInstance, PersistSignalAdapter, PersistSignalInstance, PersistStateAdapter, PersistStateInstance, PersistStorageAdapter, PersistStorageInstance, Position, PositionSize, Recent, RecentBacktest, RecentLive, Reflect$1 as Reflect, Report, ReportBase, ReportWriter, Risk, Schedule, Session, SessionBacktest, SessionLive, State, StateBacktest, StateBacktestAdapter, StateLive, StateLiveAdapter, Storage, StorageBacktest, StorageLive, Strategy, Sync, System, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialLossCost, commitPartialProfit, commitPartialProfitCost, commitSignalNotify, commitTrailingStop, commitTrailingStopCost, commitTrailingTake, commitTrailingTakeCost, createSignalState, dumpAgentAnswer, dumpError, dumpJson, dumpRecord, dumpTable, dumpText, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getBreakeven, getCandles, getClosePrice, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getEffectivePriceOpen, getExchangeSchema, getFrameSchema, getLatestSignal, getMaxDrawdownDistancePnlCost, getMaxDrawdownDistancePnlPercentage, getMinutesSinceLatestSignalCreated, getMode, getNextCandles, getOrderBook, getPendingSignal, getPositionActiveMinutes, getPositionCountdownMinutes, getPositionDrawdownMinutes, getPositionEffectivePrice, getPositionEntries, getPositionEntryOverlap, getPositionEstimateMinutes, getPositionHighestMaxDrawdownPnlCost, getPositionHighestMaxDrawdownPnlPercentage, getPositionHighestPnlCost, getPositionHighestPnlPercentage, getPositionHighestProfitBreakeven, getPositionHighestProfitDistancePnlCost, getPositionHighestProfitDistancePnlPercentage, getPositionHighestProfitMinutes, getPositionHighestProfitPrice, getPositionHighestProfitTimestamp, getPositionInvestedCost, getPositionInvestedCount, getPositionLevels, getPositionMaxDrawdownMinutes, getPositionMaxDrawdownPnlCost, getPositionMaxDrawdownPnlPercentage, getPositionMaxDrawdownPrice, getPositionMaxDrawdownTimestamp, getPositionPartialOverlap, getPositionPartials, getPositionPnlCost, getPositionPnlPercent, getPositionWaitingMinutes, getRawCandles, getRiskSchema, getScheduledSignal, getSessionData, getSignalState, getSizingSchema, getStrategySchema, getSymbol, getTimestamp, getTotalClosed, getTotalCostClosed, getTotalPercentClosed, getWalkerSchema, hasNoPendingSignal, hasNoScheduledSignal, hasTradeContext, intervalStepMs, investedCostToPercent, backtest as lib, listExchangeSchema, listFrameSchema, listMemory, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenHighestProfit, listenHighestProfitOnce, listenIdlePing, listenIdlePingOnce, listenMaxDrawdown, listenMaxDrawdownOnce, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalNotify, listenSignalNotifyOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenSync, listenSyncOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, percentDiff, percentToCloseCost, percentValue, readMemory, removeMemory, roundTicks, runInMockContext, searchMemory, set, setColumns, setConfig, setLogger, setSessionData, setSignalState, shutdown, slPercentShiftToPrice, slPriceToPercentShift, stopStrategy, toProfitLossDto, tpPercentShiftToPrice, tpPriceToPercentShift, validate, validateCommonSignal, validatePendingSignal, validateScheduledSignal, validateSignal, waitForCandle, waitForReady, warmCandles, writeMemory };