backtest-kit 9.0.1 → 9.0.3

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.cjs CHANGED
@@ -1458,7 +1458,7 @@ class PersistRiskInstance {
1458
1458
  *
1459
1459
  * @returns Promise resolving to positions (empty array if none persisted)
1460
1460
  */
1461
- async readPositionData() {
1461
+ async readPositionData(_when) {
1462
1462
  if (await this._storage.hasValue(PersistRiskInstance.STORAGE_KEY)) {
1463
1463
  return await this._storage.readValue(PersistRiskInstance.STORAGE_KEY);
1464
1464
  }
@@ -1468,9 +1468,10 @@ class PersistRiskInstance {
1468
1468
  * Writes the positions array using the fixed STORAGE_KEY.
1469
1469
  *
1470
1470
  * @param riskRow - Position entries to persist
1471
+ * @param when - Logical timestamp (reserved for API consistency; not used)
1471
1472
  * @returns Promise that resolves when write is complete
1472
1473
  */
1473
- async writePositionData(riskRow) {
1474
+ async writePositionData(riskRow, _when) {
1474
1475
  await this._storage.writeValue(PersistRiskInstance.STORAGE_KEY, riskRow);
1475
1476
  }
1476
1477
  }
@@ -1495,12 +1496,12 @@ class PersistRiskDummyInstance {
1495
1496
  * Always returns empty positions array.
1496
1497
  * @returns Promise resolving to []
1497
1498
  */
1498
- async readPositionData() { return []; }
1499
+ async readPositionData(_when) { return []; }
1499
1500
  /**
1500
1501
  * No-op write (discards positions).
1501
1502
  * @returns Promise that resolves immediately
1502
1503
  */
1503
- async writePositionData(_riskRow) { }
1504
+ async writePositionData(_riskRow, _when) { }
1504
1505
  }
1505
1506
  /**
1506
1507
  * Utility class for managing risk active positions persistence.
@@ -1530,15 +1531,16 @@ class PersistRiskUtils {
1530
1531
  *
1531
1532
  * @param riskName - Risk profile identifier
1532
1533
  * @param exchangeName - Exchange identifier
1534
+ * @param when - Logical timestamp at which the read is happening (reserved for API consistency)
1533
1535
  * @returns Promise resolving to position entries (empty array if none)
1534
1536
  */
1535
- this.readPositionData = async (riskName, exchangeName) => {
1537
+ this.readPositionData = async (riskName, exchangeName, when) => {
1536
1538
  LOGGER_SERVICE$7.info(PERSIST_RISK_UTILS_METHOD_NAME_READ_DATA);
1537
1539
  const key = `${riskName}:${exchangeName}`;
1538
1540
  const isInitial = !this.getRiskStorage.has(key);
1539
1541
  const instance = this.getRiskStorage(riskName, exchangeName);
1540
1542
  await instance.waitForInit(isInitial);
1541
- return instance.readPositionData();
1543
+ return instance.readPositionData(when);
1542
1544
  };
1543
1545
  /**
1544
1546
  * Writes active positions for the given risk context.
@@ -1547,15 +1549,16 @@ class PersistRiskUtils {
1547
1549
  * @param riskRow - Position entries to persist
1548
1550
  * @param riskName - Risk profile identifier
1549
1551
  * @param exchangeName - Exchange identifier
1552
+ * @param when - Logical timestamp this write belongs to (reserved for API consistency)
1550
1553
  * @returns Promise that resolves when write is complete
1551
1554
  */
1552
- this.writePositionData = async (riskRow, riskName, exchangeName) => {
1555
+ this.writePositionData = async (riskRow, riskName, exchangeName, when) => {
1553
1556
  LOGGER_SERVICE$7.info(PERSIST_RISK_UTILS_METHOD_NAME_WRITE_DATA);
1554
1557
  const key = `${riskName}:${exchangeName}`;
1555
1558
  const isInitial = !this.getRiskStorage.has(key);
1556
1559
  const instance = this.getRiskStorage(riskName, exchangeName);
1557
1560
  await instance.waitForInit(isInitial);
1558
- return instance.writePositionData(riskRow);
1561
+ return instance.writePositionData(riskRow, when);
1559
1562
  };
1560
1563
  }
1561
1564
  /**
@@ -1849,7 +1852,7 @@ class PersistPartialInstance {
1849
1852
  * @param signalId - Signal identifier
1850
1853
  * @returns Promise resolving to partial data record (empty object if not found)
1851
1854
  */
1852
- async readPartialData(signalId) {
1855
+ async readPartialData(signalId, _when) {
1853
1856
  if (await this._storage.hasValue(signalId)) {
1854
1857
  return await this._storage.readValue(signalId);
1855
1858
  }
@@ -1860,9 +1863,10 @@ class PersistPartialInstance {
1860
1863
  *
1861
1864
  * @param data - Partial data record to persist
1862
1865
  * @param signalId - Signal identifier
1866
+ * @param when - Logical timestamp (reserved for API consistency; not used)
1863
1867
  * @returns Promise that resolves when write is complete
1864
1868
  */
1865
- async writePartialData(data, signalId) {
1869
+ async writePartialData(data, signalId, _when) {
1866
1870
  await this._storage.writeValue(signalId, data);
1867
1871
  }
1868
1872
  }
@@ -1885,12 +1889,12 @@ class PersistPartialDummyInstance {
1885
1889
  * Always returns empty partial data record.
1886
1890
  * @returns Promise resolving to {}
1887
1891
  */
1888
- async readPartialData(_signalId) { return {}; }
1892
+ async readPartialData(_signalId, _when) { return {}; }
1889
1893
  /**
1890
1894
  * No-op write (discards partial data).
1891
1895
  * @returns Promise that resolves immediately
1892
1896
  */
1893
- async writePartialData(_data, _signalId) { }
1897
+ async writePartialData(_data, _signalId, _when) { }
1894
1898
  }
1895
1899
  /**
1896
1900
  * Utility class for managing partial profit/loss levels persistence.
@@ -1923,15 +1927,16 @@ class PersistPartialUtils {
1923
1927
  * @param strategyName - Strategy identifier
1924
1928
  * @param signalId - Signal identifier
1925
1929
  * @param exchangeName - Exchange identifier
1930
+ * @param when - Logical timestamp at which the read is happening (reserved for API consistency)
1926
1931
  * @returns Promise resolving to partial data record (empty object if none)
1927
1932
  */
1928
- this.readPartialData = async (symbol, strategyName, signalId, exchangeName) => {
1933
+ this.readPartialData = async (symbol, strategyName, signalId, exchangeName, when) => {
1929
1934
  LOGGER_SERVICE$7.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_READ_DATA);
1930
1935
  const key = `${symbol}:${strategyName}:${exchangeName}`;
1931
1936
  const isInitial = !this.getPartialStorage.has(key);
1932
1937
  const instance = this.getPartialStorage(symbol, strategyName, exchangeName);
1933
1938
  await instance.waitForInit(isInitial);
1934
- return instance.readPartialData(signalId);
1939
+ return instance.readPartialData(signalId, when);
1935
1940
  };
1936
1941
  /**
1937
1942
  * Writes partial data for the given context and signalId.
@@ -1942,15 +1947,16 @@ class PersistPartialUtils {
1942
1947
  * @param strategyName - Strategy identifier
1943
1948
  * @param signalId - Signal identifier
1944
1949
  * @param exchangeName - Exchange identifier
1950
+ * @param when - Logical timestamp this write belongs to (reserved for API consistency)
1945
1951
  * @returns Promise that resolves when write is complete
1946
1952
  */
1947
- this.writePartialData = async (partialData, symbol, strategyName, signalId, exchangeName) => {
1953
+ this.writePartialData = async (partialData, symbol, strategyName, signalId, exchangeName, when) => {
1948
1954
  LOGGER_SERVICE$7.info(PERSIST_PARTIAL_UTILS_METHOD_NAME_WRITE_DATA);
1949
1955
  const key = `${symbol}:${strategyName}:${exchangeName}`;
1950
1956
  const isInitial = !this.getPartialStorage.has(key);
1951
1957
  const instance = this.getPartialStorage(symbol, strategyName, exchangeName);
1952
1958
  await instance.waitForInit(isInitial);
1953
- return instance.writePartialData(partialData, signalId);
1959
+ return instance.writePartialData(partialData, signalId, when);
1954
1960
  };
1955
1961
  }
1956
1962
  /**
@@ -2049,7 +2055,7 @@ class PersistBreakevenInstance {
2049
2055
  * @param signalId - Signal identifier
2050
2056
  * @returns Promise resolving to breakeven data record (empty object if not found)
2051
2057
  */
2052
- async readBreakevenData(signalId) {
2058
+ async readBreakevenData(signalId, _when) {
2053
2059
  if (await this._storage.hasValue(signalId)) {
2054
2060
  return await this._storage.readValue(signalId);
2055
2061
  }
@@ -2060,9 +2066,10 @@ class PersistBreakevenInstance {
2060
2066
  *
2061
2067
  * @param data - Breakeven data record to persist
2062
2068
  * @param signalId - Signal identifier
2069
+ * @param when - Logical timestamp (reserved for API consistency; not used)
2063
2070
  * @returns Promise that resolves when write is complete
2064
2071
  */
2065
- async writeBreakevenData(data, signalId) {
2072
+ async writeBreakevenData(data, signalId, _when) {
2066
2073
  await this._storage.writeValue(signalId, data);
2067
2074
  }
2068
2075
  }
@@ -2085,12 +2092,12 @@ class PersistBreakevenDummyInstance {
2085
2092
  * Always returns empty breakeven data record.
2086
2093
  * @returns Promise resolving to {}
2087
2094
  */
2088
- async readBreakevenData(_signalId) { return {}; }
2095
+ async readBreakevenData(_signalId, _when) { return {}; }
2089
2096
  /**
2090
2097
  * No-op write (discards breakeven data).
2091
2098
  * @returns Promise that resolves immediately
2092
2099
  */
2093
- async writeBreakevenData(_data, _signalId) { }
2100
+ async writeBreakevenData(_data, _signalId, _when) { }
2094
2101
  }
2095
2102
  /**
2096
2103
  * Persistence utility class for breakeven state management.
@@ -2143,15 +2150,16 @@ class PersistBreakevenUtils {
2143
2150
  * @param strategyName - Strategy identifier
2144
2151
  * @param signalId - Signal identifier
2145
2152
  * @param exchangeName - Exchange identifier
2153
+ * @param when - Logical timestamp at which the read is happening (reserved for API consistency)
2146
2154
  * @returns Promise resolving to breakeven data record (empty object if none)
2147
2155
  */
2148
- this.readBreakevenData = async (symbol, strategyName, signalId, exchangeName) => {
2156
+ this.readBreakevenData = async (symbol, strategyName, signalId, exchangeName, when) => {
2149
2157
  LOGGER_SERVICE$7.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_READ_DATA);
2150
2158
  const key = `${symbol}:${strategyName}:${exchangeName}`;
2151
2159
  const isInitial = !this.getBreakevenStorage.has(key);
2152
2160
  const instance = this.getBreakevenStorage(symbol, strategyName, exchangeName);
2153
2161
  await instance.waitForInit(isInitial);
2154
- return instance.readBreakevenData(signalId);
2162
+ return instance.readBreakevenData(signalId, when);
2155
2163
  };
2156
2164
  /**
2157
2165
  * Writes breakeven data for the given context and signalId.
@@ -2162,15 +2170,16 @@ class PersistBreakevenUtils {
2162
2170
  * @param strategyName - Strategy identifier
2163
2171
  * @param signalId - Signal identifier
2164
2172
  * @param exchangeName - Exchange identifier
2173
+ * @param when - Logical timestamp this write belongs to (reserved for API consistency)
2165
2174
  * @returns Promise that resolves when write is complete
2166
2175
  */
2167
- this.writeBreakevenData = async (breakevenData, symbol, strategyName, signalId, exchangeName) => {
2176
+ this.writeBreakevenData = async (breakevenData, symbol, strategyName, signalId, exchangeName, when) => {
2168
2177
  LOGGER_SERVICE$7.info(PERSIST_BREAKEVEN_UTILS_METHOD_NAME_WRITE_DATA);
2169
2178
  const key = `${symbol}:${strategyName}:${exchangeName}`;
2170
2179
  const isInitial = !this.getBreakevenStorage.has(key);
2171
2180
  const instance = this.getBreakevenStorage(symbol, strategyName, exchangeName);
2172
2181
  await instance.waitForInit(isInitial);
2173
- return instance.writeBreakevenData(breakevenData, signalId);
2182
+ return instance.writeBreakevenData(breakevenData, signalId, when);
2174
2183
  };
2175
2184
  }
2176
2185
  /**
@@ -3581,7 +3590,7 @@ class PersistMemoryInstance {
3581
3590
  * @param memoryId - Memory entry identifier
3582
3591
  * @returns Promise that resolves when write is complete
3583
3592
  */
3584
- async writeMemoryData(data, memoryId) {
3593
+ async writeMemoryData(data, memoryId, _when) {
3585
3594
  await this._storage.writeValue(memoryId, data);
3586
3595
  }
3587
3596
  /**
@@ -3646,7 +3655,7 @@ class PersistMemoryDummyInstance {
3646
3655
  * No-op write (discards entry).
3647
3656
  * @returns Promise that resolves immediately
3648
3657
  */
3649
- async writeMemoryData(_data, _memoryId) { }
3658
+ async writeMemoryData(_data, _memoryId, _when) { }
3650
3659
  /**
3651
3660
  * No-op remove.
3652
3661
  * @returns Promise that resolves immediately
@@ -3739,19 +3748,20 @@ class PersistMemoryUtils {
3739
3748
  * Writes a memory entry for the given context.
3740
3749
  * Lazily initializes the instance on first access.
3741
3750
  *
3742
- * @param data - Entry data to persist
3751
+ * @param data - Entry data to persist (already carries `data.when`)
3743
3752
  * @param signalId - Signal identifier
3744
3753
  * @param bucketName - Bucket name
3745
3754
  * @param memoryId - Memory entry identifier
3755
+ * @param when - Logical timestamp this entry belongs to (duplicates `data.when` for API consistency)
3746
3756
  * @returns Promise that resolves when write is complete
3747
3757
  */
3748
- this.writeMemoryData = async (data, signalId, bucketName, memoryId) => {
3758
+ this.writeMemoryData = async (data, signalId, bucketName, memoryId, when) => {
3749
3759
  LOGGER_SERVICE$7.info(PERSIST_MEMORY_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName, memoryId });
3750
3760
  const key = `${signalId}:${bucketName}`;
3751
3761
  const isInitial = !this.getMemoryStorage.has(key);
3752
3762
  const instance = this.getMemoryStorage(signalId, bucketName);
3753
3763
  await instance.waitForInit(isInitial);
3754
- return instance.writeMemoryData(data, memoryId);
3764
+ return instance.writeMemoryData(data, memoryId, when);
3755
3765
  };
3756
3766
  /**
3757
3767
  * Soft-deletes a memory entry for the given context.
@@ -3915,7 +3925,7 @@ class PersistRecentInstance {
3915
3925
  * @param signalRow - Recent signal data to persist
3916
3926
  * @returns Promise that resolves when write is complete
3917
3927
  */
3918
- async writeRecentData(signalRow) {
3928
+ async writeRecentData(signalRow, _when) {
3919
3929
  await this._storage.writeValue(this.symbol, signalRow);
3920
3930
  }
3921
3931
  }
@@ -3943,7 +3953,7 @@ class PersistRecentDummyInstance {
3943
3953
  * No-op write (discards recent signal).
3944
3954
  * @returns Promise that resolves immediately
3945
3955
  */
3946
- async writeRecentData(_signalRow) { }
3956
+ async writeRecentData(_signalRow, _when) { }
3947
3957
  }
3948
3958
  /**
3949
3959
  * Utility class for managing recent signal persistence.
@@ -3990,21 +4000,22 @@ class PersistRecentUtils {
3990
4000
  * Writes the latest recent signal for the given context.
3991
4001
  * Lazily initializes the instance on first access.
3992
4002
  *
3993
- * @param signalRow - Recent signal data to persist
4003
+ * @param signalRow - Recent signal data to persist (already carries `signalRow.timestamp`)
3994
4004
  * @param symbol - Trading pair symbol
3995
4005
  * @param strategyName - Strategy identifier
3996
4006
  * @param exchangeName - Exchange identifier
3997
4007
  * @param frameName - Frame identifier (may be empty)
3998
4008
  * @param backtest - True for backtest mode, false for live mode
4009
+ * @param when - Logical timestamp this signal belongs to (duplicates `signalRow.timestamp` for API consistency)
3999
4010
  * @returns Promise that resolves when write is complete
4000
4011
  */
4001
- this.writeRecentData = async (signalRow, symbol, strategyName, exchangeName, frameName, backtest) => {
4012
+ this.writeRecentData = async (signalRow, symbol, strategyName, exchangeName, frameName, backtest, when) => {
4002
4013
  LOGGER_SERVICE$7.info(PERSIST_RECENT_UTILS_METHOD_NAME_WRITE_DATA);
4003
4014
  const key = this.createKey(symbol, strategyName, exchangeName, frameName, backtest);
4004
4015
  const isInitial = !this.getStorage.has(key);
4005
4016
  const instance = this.getStorage(symbol, strategyName, exchangeName, frameName, backtest);
4006
4017
  await instance.waitForInit(isInitial);
4007
- return instance.writeRecentData(signalRow);
4018
+ return instance.writeRecentData(signalRow, when);
4008
4019
  };
4009
4020
  }
4010
4021
  /**
@@ -4118,7 +4129,7 @@ class PersistStateInstance {
4118
4129
  * @param data - State data to persist
4119
4130
  * @returns Promise that resolves when write is complete
4120
4131
  */
4121
- async writeStateData(data) {
4132
+ async writeStateData(data, _when) {
4122
4133
  await this._storage.writeValue(this.bucketName, data);
4123
4134
  }
4124
4135
  /**
@@ -4151,7 +4162,7 @@ class PersistStateDummyInstance {
4151
4162
  * No-op write (discards state).
4152
4163
  * @returns Promise that resolves immediately
4153
4164
  */
4154
- async writeStateData(_data) { }
4165
+ async writeStateData(_data, _when) { }
4155
4166
  /**
4156
4167
  * No-op dispose.
4157
4168
  */
@@ -4216,18 +4227,19 @@ class PersistStateUtils {
4216
4227
  * Writes state for the given context.
4217
4228
  * Lazily initializes the instance on first access.
4218
4229
  *
4219
- * @param data - State data to persist
4230
+ * @param data - State data to persist (already carries `data.when`)
4220
4231
  * @param signalId - Signal identifier
4221
4232
  * @param bucketName - Bucket name
4233
+ * @param when - Logical timestamp this value belongs to (duplicates `data.when` for API consistency)
4222
4234
  * @returns Promise that resolves when write is complete
4223
4235
  */
4224
- this.writeStateData = async (data, signalId, bucketName) => {
4236
+ this.writeStateData = async (data, signalId, bucketName, when) => {
4225
4237
  LOGGER_SERVICE$7.info(PERSIST_STATE_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName });
4226
4238
  const key = `${signalId}:${bucketName}`;
4227
4239
  const isInitial = !this.getStateStorage.has(key);
4228
4240
  const instance = this.getStateStorage(signalId, bucketName);
4229
4241
  await instance.waitForInit(isInitial);
4230
- return instance.writeStateData(data);
4242
+ return instance.writeStateData(data, when);
4231
4243
  };
4232
4244
  /**
4233
4245
  * Switches to PersistStateDummyInstance (all operations are no-ops).
@@ -4337,7 +4349,7 @@ class PersistSessionInstance {
4337
4349
  * @param data - Session data to persist
4338
4350
  * @returns Promise that resolves when write is complete
4339
4351
  */
4340
- async writeSessionData(data) {
4352
+ async writeSessionData(data, _when) {
4341
4353
  await this._storage.writeValue(this.frameName, data);
4342
4354
  }
4343
4355
  /**
@@ -4370,7 +4382,7 @@ class PersistSessionDummyInstance {
4370
4382
  * No-op write (discards session data).
4371
4383
  * @returns Promise that resolves immediately
4372
4384
  */
4373
- async writeSessionData(_data) { }
4385
+ async writeSessionData(_data, _when) { }
4374
4386
  /**
4375
4387
  * No-op dispose.
4376
4388
  */
@@ -4438,19 +4450,20 @@ class PersistSessionUtils {
4438
4450
  * Writes session data for the given context.
4439
4451
  * Lazily initializes the instance on first access.
4440
4452
  *
4441
- * @param data - Session data to persist
4453
+ * @param data - Session data to persist (already carries `data.when`)
4442
4454
  * @param strategyName - Strategy identifier
4443
4455
  * @param exchangeName - Exchange identifier
4444
4456
  * @param frameName - Frame identifier
4457
+ * @param when - Logical timestamp this value belongs to (duplicates `data.when` for API consistency)
4445
4458
  * @returns Promise that resolves when write is complete
4446
4459
  */
4447
- this.writeSessionData = async (data, strategyName, exchangeName, frameName) => {
4460
+ this.writeSessionData = async (data, strategyName, exchangeName, frameName, when) => {
4448
4461
  LOGGER_SERVICE$7.info(PERSIST_SESSION_UTILS_METHOD_NAME_WRITE_DATA, { strategyName, exchangeName, frameName });
4449
4462
  const key = `${strategyName}:${exchangeName}:${frameName}`;
4450
4463
  const isInitial = !this.getSessionStorage.has(key);
4451
4464
  const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
4452
4465
  await instance.waitForInit(isInitial);
4453
- return instance.writeSessionData(data);
4466
+ return instance.writeSessionData(data, when);
4454
4467
  };
4455
4468
  /**
4456
4469
  * Switches to PersistSessionDummyInstance (all operations are no-ops).
@@ -14152,57 +14165,10 @@ const get = (object, path) => {
14152
14165
  return pathArrayFlat.reduce((obj, key) => obj && obj[key], object);
14153
14166
  };
14154
14167
 
14155
- const MS_PER_MINUTE$6 = 60000;
14156
- const INTERVAL_MINUTES$6 = {
14157
- "1m": 1,
14158
- "3m": 3,
14159
- "5m": 5,
14160
- "15m": 15,
14161
- "30m": 30,
14162
- "1h": 60,
14163
- "2h": 120,
14164
- "4h": 240,
14165
- "6h": 360,
14166
- "8h": 480,
14167
- "1d": 1440,
14168
- };
14169
- /**
14170
- * Aligns timestamp down to the nearest interval boundary.
14171
- * For example, for 15m interval: 00:17 -> 00:15, 00:44 -> 00:30
14172
- *
14173
- * Candle timestamp convention:
14174
- * - Candle timestamp = openTime (when candle opens)
14175
- * - Candle with timestamp 00:00 covers period [00:00, 00:15) for 15m interval
14176
- *
14177
- * Adapter contract:
14178
- * - Adapter must return candles with timestamp = openTime
14179
- * - First returned candle.timestamp must equal aligned since
14180
- * - Adapter must return exactly `limit` candles
14181
- *
14182
- * @param date - Date to align
14183
- * @param interval - Candle interval (e.g., "1m", "15m", "1h")
14184
- * @returns New Date aligned down to interval boundary
14185
- */
14186
- const alignToInterval = (date, interval) => {
14187
- const minutes = INTERVAL_MINUTES$6[interval];
14188
- if (minutes === undefined) {
14189
- throw new Error(`alignToInterval: unknown interval=${interval}`);
14190
- }
14191
- const intervalMs = minutes * MS_PER_MINUTE$6;
14192
- return new Date(Math.floor(date.getTime() / intervalMs) * intervalMs);
14193
- };
14194
-
14195
14168
  /** Used to prevent race confition between concurent strategies */
14196
14169
  const RISK_LOCK = new Lock();
14197
14170
  /** Symbol indicating that positions need to be fetched from persistence */
14198
14171
  const POSITION_NEED_FETCH = Symbol("risk-need-fetch");
14199
- /** Get timestamp from execution context or fallback to aligned current time */
14200
- const GET_CONTEXT_TIMESTAMP_FN = (self) => {
14201
- if (ExecutionContextService.hasContext()) {
14202
- return self.params.execution.context.when.getTime();
14203
- }
14204
- return alignToInterval(new Date(), "1m").getTime();
14205
- };
14206
14172
  /** Zero PNL constant for scheduled signals (which don't have priceOpen or PNL yet) */
14207
14173
  const ZERO_PNL = { pnlPercentage: 0, priceOpen: 0, priceClose: 0, pnlCost: 0, pnlEntries: 0 };
14208
14174
  /**
@@ -14328,7 +14294,7 @@ const CALL_ALLOWED_CALLBACKS_FN = functoolsKit.trycatch(async (self, symbol, par
14328
14294
  *
14329
14295
  * In backtest mode, initializes with empty Map. In live mode, reads from persist storage.
14330
14296
  */
14331
- const WAIT_FOR_INIT_FN$3 = async (self) => {
14297
+ const WAIT_FOR_INIT_FN$3 = async (when, self) => {
14332
14298
  self.params.logger.debug("ClientRisk waitForInit", {
14333
14299
  backtest: self.params.backtest,
14334
14300
  });
@@ -14336,7 +14302,7 @@ const WAIT_FOR_INIT_FN$3 = async (self) => {
14336
14302
  self._activePositions = new Map();
14337
14303
  return;
14338
14304
  }
14339
- const persistedPositions = await PersistRiskAdapter.readPositionData(self.params.riskName, self.params.exchangeName);
14305
+ const persistedPositions = await PersistRiskAdapter.readPositionData(self.params.riskName, self.params.exchangeName, when);
14340
14306
  self._activePositions = new Map(persistedPositions);
14341
14307
  };
14342
14308
  /**
@@ -14365,7 +14331,7 @@ class ClientRisk {
14365
14331
  * Uses singleshot pattern to ensure initialization happens exactly once.
14366
14332
  * Skips persistence in backtest mode.
14367
14333
  */
14368
- this.waitForInit = functoolsKit.singleshot(async () => await WAIT_FOR_INIT_FN$3(this));
14334
+ this.waitForInit = functoolsKit.singleshot(async (when) => await WAIT_FOR_INIT_FN$3(when, this));
14369
14335
  /**
14370
14336
  * Checks if a signal should be allowed based on risk limits.
14371
14337
  *
@@ -14387,11 +14353,15 @@ class ClientRisk {
14387
14353
  });
14388
14354
  await RISK_LOCK.acquireLock();
14389
14355
  try {
14356
+ const timestamp = await this.params.time.getTimestamp(params.symbol, {
14357
+ strategyName: params.strategyName,
14358
+ exchangeName: params.exchangeName,
14359
+ frameName: params.frameName,
14360
+ }, this.params.backtest);
14390
14361
  if (this._activePositions === POSITION_NEED_FETCH) {
14391
- await this.waitForInit();
14362
+ await this.waitForInit(new Date(timestamp));
14392
14363
  }
14393
14364
  const riskMap = this._activePositions;
14394
- const timestamp = GET_CONTEXT_TIMESTAMP_FN(this);
14395
14365
  const payload = {
14396
14366
  ...params,
14397
14367
  currentSignal: TO_RISK_SIGNAL(params.currentSignal, params.currentPrice, timestamp),
@@ -14494,14 +14464,14 @@ class ClientRisk {
14494
14464
  * Persists current active positions to disk.
14495
14465
  * Skips in backtest mode.
14496
14466
  */
14497
- async _updatePositions() {
14467
+ async _updatePositions(when) {
14498
14468
  if (this.params.backtest) {
14499
14469
  return;
14500
14470
  }
14501
14471
  if (this._activePositions === POSITION_NEED_FETCH) {
14502
- await this.waitForInit();
14472
+ await this.waitForInit(when);
14503
14473
  }
14504
- await PersistRiskAdapter.writePositionData(Array.from(this._activePositions), this.params.riskName, this.params.exchangeName);
14474
+ await PersistRiskAdapter.writePositionData(Array.from(this._activePositions), this.params.riskName, this.params.exchangeName, when);
14505
14475
  }
14506
14476
  /**
14507
14477
  * Registers a new opened signal.
@@ -14516,8 +14486,9 @@ class ClientRisk {
14516
14486
  });
14517
14487
  await RISK_LOCK.acquireLock();
14518
14488
  try {
14489
+ const timestamp = await this.params.time.getTimestamp(symbol, context, this.params.backtest);
14519
14490
  if (this._activePositions === POSITION_NEED_FETCH) {
14520
- await this.waitForInit();
14491
+ await this.waitForInit(new Date(timestamp));
14521
14492
  }
14522
14493
  const key = CREATE_NAME_FN(context.strategyName, context.exchangeName, symbol);
14523
14494
  const riskMap = this._activePositions;
@@ -14533,7 +14504,7 @@ class ClientRisk {
14533
14504
  minuteEstimatedTime: positionData.minuteEstimatedTime,
14534
14505
  openTimestamp: positionData.openTimestamp,
14535
14506
  });
14536
- await this._updatePositions();
14507
+ await this._updatePositions(new Date(timestamp));
14537
14508
  }
14538
14509
  finally {
14539
14510
  await RISK_LOCK.releaseLock();
@@ -14551,13 +14522,14 @@ class ClientRisk {
14551
14522
  });
14552
14523
  await RISK_LOCK.acquireLock();
14553
14524
  try {
14525
+ const timestamp = await this.params.time.getTimestamp(symbol, context, this.params.backtest);
14554
14526
  if (this._activePositions === POSITION_NEED_FETCH) {
14555
- await this.waitForInit();
14527
+ await this.waitForInit(new Date(timestamp));
14556
14528
  }
14557
14529
  const key = CREATE_NAME_FN(context.strategyName, context.exchangeName, symbol);
14558
14530
  const riskMap = this._activePositions;
14559
14531
  riskMap.delete(key);
14560
- await this._updatePositions();
14532
+ await this._updatePositions(new Date(timestamp));
14561
14533
  }
14562
14534
  finally {
14563
14535
  await RISK_LOCK.releaseLock();
@@ -14657,7 +14629,7 @@ class RiskConnectionService {
14657
14629
  constructor() {
14658
14630
  this.loggerService = inject(TYPES.loggerService);
14659
14631
  this.riskSchemaService = inject(TYPES.riskSchemaService);
14660
- this.executionContextService = inject(TYPES.executionContextService);
14632
+ this.timeMetaService = inject(TYPES.timeMetaService);
14661
14633
  /**
14662
14634
  * Action core service injected from DI container.
14663
14635
  */
@@ -14679,7 +14651,7 @@ class RiskConnectionService {
14679
14651
  return new ClientRisk({
14680
14652
  ...schema,
14681
14653
  logger: this.loggerService,
14682
- execution: this.executionContextService,
14654
+ time: this.timeMetaService,
14683
14655
  backtest,
14684
14656
  exchangeName,
14685
14657
  onRejected: CREATE_COMMIT_REJECTION_FN(this, exchangeName, frameName),
@@ -19670,8 +19642,8 @@ class BacktestLogicPrivateService {
19670
19642
  }
19671
19643
 
19672
19644
  const EMITTER_CHECK_INTERVAL = 5000;
19673
- const MS_PER_MINUTE$5 = 60000;
19674
- const INTERVAL_MINUTES$5 = {
19645
+ const MS_PER_MINUTE$6 = 60000;
19646
+ const INTERVAL_MINUTES$6 = {
19675
19647
  "1m": 1,
19676
19648
  "3m": 3,
19677
19649
  "5m": 5,
@@ -19686,7 +19658,7 @@ const INTERVAL_MINUTES$5 = {
19686
19658
  };
19687
19659
  const createEmitter = functoolsKit.memoize(([interval]) => `${interval}`, (interval) => {
19688
19660
  const tickSubject = new functoolsKit.Subject();
19689
- const intervalMs = INTERVAL_MINUTES$5[interval] * MS_PER_MINUTE$5;
19661
+ const intervalMs = INTERVAL_MINUTES$6[interval] * MS_PER_MINUTE$6;
19690
19662
  {
19691
19663
  let lastAligned = Math.floor(Date.now() / intervalMs) * intervalMs;
19692
19664
  functoolsKit.Source.fromInterval(EMITTER_CHECK_INTERVAL)
@@ -19713,6 +19685,46 @@ const waitForCandle = async (interval) => {
19713
19685
  return emitter.toPromise();
19714
19686
  };
19715
19687
 
19688
+ const MS_PER_MINUTE$5 = 60000;
19689
+ const INTERVAL_MINUTES$5 = {
19690
+ "1m": 1,
19691
+ "3m": 3,
19692
+ "5m": 5,
19693
+ "15m": 15,
19694
+ "30m": 30,
19695
+ "1h": 60,
19696
+ "2h": 120,
19697
+ "4h": 240,
19698
+ "6h": 360,
19699
+ "8h": 480,
19700
+ "1d": 1440,
19701
+ };
19702
+ /**
19703
+ * Aligns timestamp down to the nearest interval boundary.
19704
+ * For example, for 15m interval: 00:17 -> 00:15, 00:44 -> 00:30
19705
+ *
19706
+ * Candle timestamp convention:
19707
+ * - Candle timestamp = openTime (when candle opens)
19708
+ * - Candle with timestamp 00:00 covers period [00:00, 00:15) for 15m interval
19709
+ *
19710
+ * Adapter contract:
19711
+ * - Adapter must return candles with timestamp = openTime
19712
+ * - First returned candle.timestamp must equal aligned since
19713
+ * - Adapter must return exactly `limit` candles
19714
+ *
19715
+ * @param date - Date to align
19716
+ * @param interval - Candle interval (e.g., "1m", "15m", "1h")
19717
+ * @returns New Date aligned down to interval boundary
19718
+ */
19719
+ const alignToInterval = (date, interval) => {
19720
+ const minutes = INTERVAL_MINUTES$5[interval];
19721
+ if (minutes === undefined) {
19722
+ throw new Error(`alignToInterval: unknown interval=${interval}`);
19723
+ }
19724
+ const intervalMs = minutes * MS_PER_MINUTE$5;
19725
+ return new Date(Math.floor(date.getTime() / intervalMs) * intervalMs);
19726
+ };
19727
+
19716
19728
  /**
19717
19729
  * Private service for live trading orchestration using async generators.
19718
19730
  *
@@ -27211,7 +27223,7 @@ const HANDLE_PROFIT_FN = async (symbol, data, currentPrice, revenuePercent, back
27211
27223
  }
27212
27224
  }
27213
27225
  if (shouldPersist) {
27214
- await self._persistState(symbol, data.strategyName, data.exchangeName, self.params.signalId);
27226
+ await self._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, self.params.signalId);
27215
27227
  }
27216
27228
  };
27217
27229
  /**
@@ -27261,7 +27273,7 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
27261
27273
  }
27262
27274
  }
27263
27275
  if (shouldPersist) {
27264
- await self._persistState(symbol, data.strategyName, data.exchangeName, self.params.signalId);
27276
+ await self._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, self.params.signalId);
27265
27277
  }
27266
27278
  };
27267
27279
  /**
@@ -27278,7 +27290,7 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
27278
27290
  * @param backtest - True if backtest mode, false if live mode
27279
27291
  * @param self - ClientPartial instance reference
27280
27292
  */
27281
- const WAIT_FOR_INIT_FN$1 = async (symbol, strategyName, exchangeName, backtest, self) => {
27293
+ const WAIT_FOR_INIT_FN$1 = async (symbol, strategyName, exchangeName, frameName, backtest, self) => {
27282
27294
  self.params.logger.debug("ClientPartial waitForInit", {
27283
27295
  symbol,
27284
27296
  backtest,
@@ -27294,7 +27306,12 @@ const WAIT_FOR_INIT_FN$1 = async (symbol, strategyName, exchangeName, backtest,
27294
27306
  self.params.logger.debug("ClientPartial waitForInit: skipping persist read in backtest mode");
27295
27307
  return;
27296
27308
  }
27297
- const partialData = await PersistPartialAdapter.readPartialData(symbol, strategyName, self.params.signalId, exchangeName);
27309
+ const timestamp = await self.params.time.getTimestamp(symbol, {
27310
+ strategyName,
27311
+ exchangeName,
27312
+ frameName,
27313
+ }, self.params.backtest);
27314
+ const partialData = await PersistPartialAdapter.readPartialData(symbol, strategyName, self.params.signalId, exchangeName, new Date(timestamp));
27298
27315
  for (const [signalId, data] of Object.entries(partialData)) {
27299
27316
  const state = {
27300
27317
  profitLevels: new Set(data.profitLevels),
@@ -27402,7 +27419,7 @@ class ClientPartial {
27402
27419
  * // Now profit()/loss() can be called
27403
27420
  * ```
27404
27421
  */
27405
- this.waitForInit = functoolsKit.singleshot(async (symbol, strategyName, exchangeName, backtest) => await WAIT_FOR_INIT_FN$1(symbol, strategyName, exchangeName, backtest, this));
27422
+ this.waitForInit = functoolsKit.singleshot(async (symbol, strategyName, exchangeName, frameName, backtest) => await WAIT_FOR_INIT_FN$1(symbol, strategyName, exchangeName, frameName, backtest, this));
27406
27423
  }
27407
27424
  /**
27408
27425
  * Persists current partial state to disk.
@@ -27420,7 +27437,7 @@ class ClientPartial {
27420
27437
  * @param signalId - Signal identifier
27421
27438
  * @returns Promise that resolves when persistence is complete
27422
27439
  */
27423
- async _persistState(symbol, strategyName, exchangeName, signalId) {
27440
+ async _persistState(symbol, strategyName, exchangeName, frameName, signalId) {
27424
27441
  if (this.params.backtest) {
27425
27442
  return;
27426
27443
  }
@@ -27435,7 +27452,12 @@ class ClientPartial {
27435
27452
  lossLevels: Array.from(state.lossLevels),
27436
27453
  };
27437
27454
  }
27438
- await PersistPartialAdapter.writePartialData(partialData, symbol, strategyName, signalId, exchangeName);
27455
+ const timestamp = await this.params.time.getTimestamp(symbol, {
27456
+ strategyName,
27457
+ exchangeName,
27458
+ frameName,
27459
+ }, this.params.backtest);
27460
+ await PersistPartialAdapter.writePartialData(partialData, symbol, strategyName, signalId, exchangeName, new Date(timestamp));
27439
27461
  }
27440
27462
  /**
27441
27463
  * Processes profit state and emits events for newly reached profit levels.
@@ -27560,7 +27582,7 @@ class ClientPartial {
27560
27582
  throw new Error(`Signal ID mismatch: expected ${this.params.signalId}, got ${data.id}`);
27561
27583
  }
27562
27584
  this._states.delete(data.id);
27563
- await this._persistState(symbol, data.strategyName, data.exchangeName, this.params.signalId);
27585
+ await this._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, this.params.signalId);
27564
27586
  }
27565
27587
  }
27566
27588
 
@@ -27685,6 +27707,7 @@ class PartialConnectionService {
27685
27707
  * Action core service injected from DI container.
27686
27708
  */
27687
27709
  this.actionCoreService = inject(TYPES.actionCoreService);
27710
+ this.timeMetaService = inject(TYPES.timeMetaService);
27688
27711
  /**
27689
27712
  * Memoized factory function for ClientPartial instances.
27690
27713
  *
@@ -27698,6 +27721,7 @@ class PartialConnectionService {
27698
27721
  return new ClientPartial({
27699
27722
  signalId,
27700
27723
  logger: this.loggerService,
27724
+ time: this.timeMetaService,
27701
27725
  backtest,
27702
27726
  onProfit: CREATE_COMMIT_PROFIT_FN(this),
27703
27727
  onLoss: CREATE_COMMIT_LOSS_FN(this),
@@ -27727,7 +27751,7 @@ class PartialConnectionService {
27727
27751
  when,
27728
27752
  });
27729
27753
  const partial = this.getPartial(data.id, backtest);
27730
- await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
27754
+ await partial.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
27731
27755
  return await partial.profit(symbol, data, currentPrice, revenuePercent, backtest, when);
27732
27756
  };
27733
27757
  /**
@@ -27754,7 +27778,7 @@ class PartialConnectionService {
27754
27778
  when,
27755
27779
  });
27756
27780
  const partial = this.getPartial(data.id, backtest);
27757
- await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
27781
+ await partial.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
27758
27782
  return await partial.loss(symbol, data, currentPrice, lossPercent, backtest, when);
27759
27783
  };
27760
27784
  /**
@@ -27782,7 +27806,7 @@ class PartialConnectionService {
27782
27806
  backtest,
27783
27807
  });
27784
27808
  const partial = this.getPartial(data.id, backtest);
27785
- await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
27809
+ await partial.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
27786
27810
  await partial.clear(symbol, data, priceClose, backtest);
27787
27811
  const key = CREATE_KEY_FN$l(data.id, backtest);
27788
27812
  this.getPartial.clear(key);
@@ -28508,7 +28532,7 @@ const HANDLE_BREAKEVEN_FN = async (symbol, data, currentPrice, backtest, when, s
28508
28532
  // Emit event
28509
28533
  await self.params.onBreakeven(symbol, data.strategyName, data.exchangeName, data.frameName, data, currentPrice, backtest, when.getTime());
28510
28534
  // Persist state
28511
- await self._persistState(symbol, data.strategyName, data.exchangeName, self.params.signalId);
28535
+ await self._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, self.params.signalId);
28512
28536
  return true;
28513
28537
  };
28514
28538
  /**
@@ -28523,7 +28547,7 @@ const HANDLE_BREAKEVEN_FN = async (symbol, data, currentPrice, backtest, when, s
28523
28547
  * @param exchangeName - Exchange identifier
28524
28548
  * @param self - ClientBreakeven instance reference
28525
28549
  */
28526
- const WAIT_FOR_INIT_FN = async (symbol, strategyName, exchangeName, backtest, self) => {
28550
+ const WAIT_FOR_INIT_FN = async (symbol, strategyName, exchangeName, frameName, backtest, self) => {
28527
28551
  self.params.logger.debug("ClientBreakeven waitForInit", {
28528
28552
  symbol,
28529
28553
  strategyName,
@@ -28539,7 +28563,12 @@ const WAIT_FOR_INIT_FN = async (symbol, strategyName, exchangeName, backtest, se
28539
28563
  self.params.logger.debug("ClientBreakeven waitForInit: skipping persist read in backtest mode");
28540
28564
  return;
28541
28565
  }
28542
- const breakevenData = await PersistBreakevenAdapter.readBreakevenData(symbol, strategyName, self.params.signalId, exchangeName);
28566
+ const timestamp = await self.params.time.getTimestamp(symbol, {
28567
+ strategyName,
28568
+ exchangeName,
28569
+ frameName,
28570
+ }, self.params.backtest);
28571
+ const breakevenData = await PersistBreakevenAdapter.readBreakevenData(symbol, strategyName, self.params.signalId, exchangeName, new Date(timestamp));
28543
28572
  for (const [signalId, data] of Object.entries(breakevenData)) {
28544
28573
  const state = {
28545
28574
  reached: data.reached,
@@ -28644,7 +28673,7 @@ class ClientBreakeven {
28644
28673
  * // Now check() can be called
28645
28674
  * ```
28646
28675
  */
28647
- this.waitForInit = functoolsKit.singleshot(async (symbol, strategyName, exchangeName, backtest) => await WAIT_FOR_INIT_FN(symbol, strategyName, exchangeName, backtest, this));
28676
+ this.waitForInit = functoolsKit.singleshot(async (symbol, strategyName, exchangeName, frameName, backtest) => await WAIT_FOR_INIT_FN(symbol, strategyName, exchangeName, frameName, backtest, this));
28648
28677
  }
28649
28678
  /**
28650
28679
  * Persists current breakeven state to disk.
@@ -28661,7 +28690,7 @@ class ClientBreakeven {
28661
28690
  * @param signalId - Signal identifier
28662
28691
  * @returns Promise that resolves when persistence is complete
28663
28692
  */
28664
- async _persistState(symbol, strategyName, exchangeName, signalId) {
28693
+ async _persistState(symbol, strategyName, exchangeName, frameName, signalId) {
28665
28694
  if (this.params.backtest) {
28666
28695
  return;
28667
28696
  }
@@ -28675,7 +28704,12 @@ class ClientBreakeven {
28675
28704
  reached: state.reached,
28676
28705
  };
28677
28706
  }
28678
- await PersistBreakevenAdapter.writeBreakevenData(breakevenData, symbol, strategyName, signalId, exchangeName);
28707
+ const timestamp = await this.params.time.getTimestamp(symbol, {
28708
+ strategyName,
28709
+ exchangeName,
28710
+ frameName,
28711
+ }, this.params.backtest);
28712
+ await PersistBreakevenAdapter.writeBreakevenData(breakevenData, symbol, strategyName, signalId, exchangeName, new Date(timestamp));
28679
28713
  }
28680
28714
  /**
28681
28715
  * Checks if breakeven should be triggered and emits event if conditions met.
@@ -28766,7 +28800,7 @@ class ClientBreakeven {
28766
28800
  throw new Error(`Signal ID mismatch: expected ${this.params.signalId}, got ${data.id}`);
28767
28801
  }
28768
28802
  this._states.delete(data.id);
28769
- await this._persistState(symbol, data.strategyName, data.exchangeName, this.params.signalId);
28803
+ await this._persistState(symbol, data.strategyName, data.exchangeName, data.frameName, this.params.signalId);
28770
28804
  }
28771
28805
  }
28772
28806
 
@@ -28855,6 +28889,7 @@ class BreakevenConnectionService {
28855
28889
  * Action core service injected from DI container.
28856
28890
  */
28857
28891
  this.actionCoreService = inject(TYPES.actionCoreService);
28892
+ this.timeMetaService = inject(TYPES.timeMetaService);
28858
28893
  /**
28859
28894
  * Memoized factory function for ClientBreakeven instances.
28860
28895
  *
@@ -28868,6 +28903,7 @@ class BreakevenConnectionService {
28868
28903
  return new ClientBreakeven({
28869
28904
  signalId,
28870
28905
  logger: this.loggerService,
28906
+ time: this.timeMetaService,
28871
28907
  backtest,
28872
28908
  onBreakeven: CREATE_COMMIT_BREAKEVEN_FN(this),
28873
28909
  });
@@ -28894,7 +28930,7 @@ class BreakevenConnectionService {
28894
28930
  when,
28895
28931
  });
28896
28932
  const breakeven = this.getBreakeven(data.id, backtest);
28897
- await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
28933
+ await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
28898
28934
  return await breakeven.check(symbol, data, currentPrice, backtest, when);
28899
28935
  };
28900
28936
  /**
@@ -28923,7 +28959,7 @@ class BreakevenConnectionService {
28923
28959
  backtest,
28924
28960
  });
28925
28961
  const breakeven = this.getBreakeven(data.id, backtest);
28926
- await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
28962
+ await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
28927
28963
  await breakeven.clear(symbol, data, priceClose, backtest);
28928
28964
  const key = CREATE_KEY_FN$i(data.id, backtest);
28929
28965
  this.getBreakeven.clear(key);
@@ -48520,7 +48556,7 @@ class RecentPersistBacktestUtils {
48520
48556
  backtest.loggerService.info(RECENT_PERSIST_BACKTEST_METHOD_NAME_HANDLE_ACTIVE_PING, {
48521
48557
  signalId: event.data.id,
48522
48558
  });
48523
- await PersistRecentAdapter.writeRecentData(event.data, event.symbol, event.strategyName, event.exchangeName, event.data.frameName, event.backtest);
48559
+ await PersistRecentAdapter.writeRecentData(event.data, event.symbol, event.strategyName, event.exchangeName, event.data.frameName, event.backtest, new Date(event.data.timestamp));
48524
48560
  };
48525
48561
  /**
48526
48562
  * Retrieves the latest persisted signal for the given context.
@@ -48657,7 +48693,7 @@ class RecentPersistLiveUtils {
48657
48693
  backtest.loggerService.info(RECENT_PERSIST_LIVE_METHOD_NAME_HANDLE_ACTIVE_PING, {
48658
48694
  signalId: event.data.id,
48659
48695
  });
48660
- await PersistRecentAdapter.writeRecentData(event.data, event.symbol, event.strategyName, event.exchangeName, event.data.frameName, event.backtest);
48696
+ await PersistRecentAdapter.writeRecentData(event.data, event.symbol, event.strategyName, event.exchangeName, event.data.frameName, event.backtest, new Date(event.data.timestamp));
48661
48697
  };
48662
48698
  /**
48663
48699
  * Retrieves the latest persisted signal for the given context.
@@ -49312,7 +49348,7 @@ class StatePersistInstance {
49312
49348
  }
49313
49349
  this._when = when.getTime();
49314
49350
  const id = CREATE_KEY_FN$6(this.signalId, this.bucketName);
49315
- await PersistStateAdapter.writeStateData({ id, data: this._value, when: this._when }, this.signalId, this.bucketName);
49351
+ await PersistStateAdapter.writeStateData({ id, data: this._value, when: this._when }, this.signalId, this.bucketName, when);
49316
49352
  return this._value;
49317
49353
  });
49318
49354
  }
@@ -50121,7 +50157,7 @@ class SessionPersistInstance {
50121
50157
  this._data = value;
50122
50158
  this._when = when.getTime();
50123
50159
  const id = CREATE_KEY_FN$5(this.symbol, this.strategyName, this.exchangeName, this.frameName, this.backtest);
50124
- await PersistSessionAdapter.writeSessionData({ id, data: value, when: this._when }, this.strategyName, this.exchangeName, this.frameName);
50160
+ await PersistSessionAdapter.writeSessionData({ id, data: value, when: this._when }, this.strategyName, this.exchangeName, this.frameName, when);
50125
50161
  };
50126
50162
  }
50127
50163
  /** Releases resources held by this instance. */
@@ -50905,7 +50941,7 @@ class MemoryPersistInstance {
50905
50941
  });
50906
50942
  const priority = Date.now();
50907
50943
  const whenMs = when.getTime();
50908
- await PersistMemoryAdapter.writeMemoryData({ data: value, priority, removed: false, index, when: whenMs }, this.signalId, this.bucketName, memoryId);
50944
+ await PersistMemoryAdapter.writeMemoryData({ data: value, priority, removed: false, index, when: whenMs }, this.signalId, this.bucketName, memoryId, when);
50909
50945
  this._index.upsert({
50910
50946
  id: memoryId,
50911
50947
  content: value,