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.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
  /**
@@ -3561,7 +3570,7 @@ class PersistMemoryInstance {
3561
3570
  * @param memoryId - Memory entry identifier
3562
3571
  * @returns Promise that resolves when write is complete
3563
3572
  */
3564
- async writeMemoryData(data, memoryId) {
3573
+ async writeMemoryData(data, memoryId, _when) {
3565
3574
  await this._storage.writeValue(memoryId, data);
3566
3575
  }
3567
3576
  /**
@@ -3626,7 +3635,7 @@ class PersistMemoryDummyInstance {
3626
3635
  * No-op write (discards entry).
3627
3636
  * @returns Promise that resolves immediately
3628
3637
  */
3629
- async writeMemoryData(_data, _memoryId) { }
3638
+ async writeMemoryData(_data, _memoryId, _when) { }
3630
3639
  /**
3631
3640
  * No-op remove.
3632
3641
  * @returns Promise that resolves immediately
@@ -3719,19 +3728,20 @@ class PersistMemoryUtils {
3719
3728
  * Writes a memory entry for the given context.
3720
3729
  * Lazily initializes the instance on first access.
3721
3730
  *
3722
- * @param data - Entry data to persist
3731
+ * @param data - Entry data to persist (already carries `data.when`)
3723
3732
  * @param signalId - Signal identifier
3724
3733
  * @param bucketName - Bucket name
3725
3734
  * @param memoryId - Memory entry identifier
3735
+ * @param when - Logical timestamp this entry belongs to (duplicates `data.when` for API consistency)
3726
3736
  * @returns Promise that resolves when write is complete
3727
3737
  */
3728
- this.writeMemoryData = async (data, signalId, bucketName, memoryId) => {
3738
+ this.writeMemoryData = async (data, signalId, bucketName, memoryId, when) => {
3729
3739
  LOGGER_SERVICE$7.info(PERSIST_MEMORY_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName, memoryId });
3730
3740
  const key = `${signalId}:${bucketName}`;
3731
3741
  const isInitial = !this.getMemoryStorage.has(key);
3732
3742
  const instance = this.getMemoryStorage(signalId, bucketName);
3733
3743
  await instance.waitForInit(isInitial);
3734
- return instance.writeMemoryData(data, memoryId);
3744
+ return instance.writeMemoryData(data, memoryId, when);
3735
3745
  };
3736
3746
  /**
3737
3747
  * Soft-deletes a memory entry for the given context.
@@ -3895,7 +3905,7 @@ class PersistRecentInstance {
3895
3905
  * @param signalRow - Recent signal data to persist
3896
3906
  * @returns Promise that resolves when write is complete
3897
3907
  */
3898
- async writeRecentData(signalRow) {
3908
+ async writeRecentData(signalRow, _when) {
3899
3909
  await this._storage.writeValue(this.symbol, signalRow);
3900
3910
  }
3901
3911
  }
@@ -3923,7 +3933,7 @@ class PersistRecentDummyInstance {
3923
3933
  * No-op write (discards recent signal).
3924
3934
  * @returns Promise that resolves immediately
3925
3935
  */
3926
- async writeRecentData(_signalRow) { }
3936
+ async writeRecentData(_signalRow, _when) { }
3927
3937
  }
3928
3938
  /**
3929
3939
  * Utility class for managing recent signal persistence.
@@ -3970,21 +3980,22 @@ class PersistRecentUtils {
3970
3980
  * Writes the latest recent signal for the given context.
3971
3981
  * Lazily initializes the instance on first access.
3972
3982
  *
3973
- * @param signalRow - Recent signal data to persist
3983
+ * @param signalRow - Recent signal data to persist (already carries `signalRow.timestamp`)
3974
3984
  * @param symbol - Trading pair symbol
3975
3985
  * @param strategyName - Strategy identifier
3976
3986
  * @param exchangeName - Exchange identifier
3977
3987
  * @param frameName - Frame identifier (may be empty)
3978
3988
  * @param backtest - True for backtest mode, false for live mode
3989
+ * @param when - Logical timestamp this signal belongs to (duplicates `signalRow.timestamp` for API consistency)
3979
3990
  * @returns Promise that resolves when write is complete
3980
3991
  */
3981
- this.writeRecentData = async (signalRow, symbol, strategyName, exchangeName, frameName, backtest) => {
3992
+ this.writeRecentData = async (signalRow, symbol, strategyName, exchangeName, frameName, backtest, when) => {
3982
3993
  LOGGER_SERVICE$7.info(PERSIST_RECENT_UTILS_METHOD_NAME_WRITE_DATA);
3983
3994
  const key = this.createKey(symbol, strategyName, exchangeName, frameName, backtest);
3984
3995
  const isInitial = !this.getStorage.has(key);
3985
3996
  const instance = this.getStorage(symbol, strategyName, exchangeName, frameName, backtest);
3986
3997
  await instance.waitForInit(isInitial);
3987
- return instance.writeRecentData(signalRow);
3998
+ return instance.writeRecentData(signalRow, when);
3988
3999
  };
3989
4000
  }
3990
4001
  /**
@@ -4098,7 +4109,7 @@ class PersistStateInstance {
4098
4109
  * @param data - State data to persist
4099
4110
  * @returns Promise that resolves when write is complete
4100
4111
  */
4101
- async writeStateData(data) {
4112
+ async writeStateData(data, _when) {
4102
4113
  await this._storage.writeValue(this.bucketName, data);
4103
4114
  }
4104
4115
  /**
@@ -4131,7 +4142,7 @@ class PersistStateDummyInstance {
4131
4142
  * No-op write (discards state).
4132
4143
  * @returns Promise that resolves immediately
4133
4144
  */
4134
- async writeStateData(_data) { }
4145
+ async writeStateData(_data, _when) { }
4135
4146
  /**
4136
4147
  * No-op dispose.
4137
4148
  */
@@ -4196,18 +4207,19 @@ class PersistStateUtils {
4196
4207
  * Writes state for the given context.
4197
4208
  * Lazily initializes the instance on first access.
4198
4209
  *
4199
- * @param data - State data to persist
4210
+ * @param data - State data to persist (already carries `data.when`)
4200
4211
  * @param signalId - Signal identifier
4201
4212
  * @param bucketName - Bucket name
4213
+ * @param when - Logical timestamp this value belongs to (duplicates `data.when` for API consistency)
4202
4214
  * @returns Promise that resolves when write is complete
4203
4215
  */
4204
- this.writeStateData = async (data, signalId, bucketName) => {
4216
+ this.writeStateData = async (data, signalId, bucketName, when) => {
4205
4217
  LOGGER_SERVICE$7.info(PERSIST_STATE_UTILS_METHOD_NAME_WRITE_DATA, { signalId, bucketName });
4206
4218
  const key = `${signalId}:${bucketName}`;
4207
4219
  const isInitial = !this.getStateStorage.has(key);
4208
4220
  const instance = this.getStateStorage(signalId, bucketName);
4209
4221
  await instance.waitForInit(isInitial);
4210
- return instance.writeStateData(data);
4222
+ return instance.writeStateData(data, when);
4211
4223
  };
4212
4224
  /**
4213
4225
  * Switches to PersistStateDummyInstance (all operations are no-ops).
@@ -4317,7 +4329,7 @@ class PersistSessionInstance {
4317
4329
  * @param data - Session data to persist
4318
4330
  * @returns Promise that resolves when write is complete
4319
4331
  */
4320
- async writeSessionData(data) {
4332
+ async writeSessionData(data, _when) {
4321
4333
  await this._storage.writeValue(this.frameName, data);
4322
4334
  }
4323
4335
  /**
@@ -4350,7 +4362,7 @@ class PersistSessionDummyInstance {
4350
4362
  * No-op write (discards session data).
4351
4363
  * @returns Promise that resolves immediately
4352
4364
  */
4353
- async writeSessionData(_data) { }
4365
+ async writeSessionData(_data, _when) { }
4354
4366
  /**
4355
4367
  * No-op dispose.
4356
4368
  */
@@ -4418,19 +4430,20 @@ class PersistSessionUtils {
4418
4430
  * Writes session data for the given context.
4419
4431
  * Lazily initializes the instance on first access.
4420
4432
  *
4421
- * @param data - Session data to persist
4433
+ * @param data - Session data to persist (already carries `data.when`)
4422
4434
  * @param strategyName - Strategy identifier
4423
4435
  * @param exchangeName - Exchange identifier
4424
4436
  * @param frameName - Frame identifier
4437
+ * @param when - Logical timestamp this value belongs to (duplicates `data.when` for API consistency)
4425
4438
  * @returns Promise that resolves when write is complete
4426
4439
  */
4427
- this.writeSessionData = async (data, strategyName, exchangeName, frameName) => {
4440
+ this.writeSessionData = async (data, strategyName, exchangeName, frameName, when) => {
4428
4441
  LOGGER_SERVICE$7.info(PERSIST_SESSION_UTILS_METHOD_NAME_WRITE_DATA, { strategyName, exchangeName, frameName });
4429
4442
  const key = `${strategyName}:${exchangeName}:${frameName}`;
4430
4443
  const isInitial = !this.getSessionStorage.has(key);
4431
4444
  const instance = this.getSessionStorage(strategyName, exchangeName, frameName);
4432
4445
  await instance.waitForInit(isInitial);
4433
- return instance.writeSessionData(data);
4446
+ return instance.writeSessionData(data, when);
4434
4447
  };
4435
4448
  /**
4436
4449
  * Switches to PersistSessionDummyInstance (all operations are no-ops).
@@ -14132,57 +14145,10 @@ const get = (object, path) => {
14132
14145
  return pathArrayFlat.reduce((obj, key) => obj && obj[key], object);
14133
14146
  };
14134
14147
 
14135
- const MS_PER_MINUTE$6 = 60000;
14136
- const INTERVAL_MINUTES$6 = {
14137
- "1m": 1,
14138
- "3m": 3,
14139
- "5m": 5,
14140
- "15m": 15,
14141
- "30m": 30,
14142
- "1h": 60,
14143
- "2h": 120,
14144
- "4h": 240,
14145
- "6h": 360,
14146
- "8h": 480,
14147
- "1d": 1440,
14148
- };
14149
- /**
14150
- * Aligns timestamp down to the nearest interval boundary.
14151
- * For example, for 15m interval: 00:17 -> 00:15, 00:44 -> 00:30
14152
- *
14153
- * Candle timestamp convention:
14154
- * - Candle timestamp = openTime (when candle opens)
14155
- * - Candle with timestamp 00:00 covers period [00:00, 00:15) for 15m interval
14156
- *
14157
- * Adapter contract:
14158
- * - Adapter must return candles with timestamp = openTime
14159
- * - First returned candle.timestamp must equal aligned since
14160
- * - Adapter must return exactly `limit` candles
14161
- *
14162
- * @param date - Date to align
14163
- * @param interval - Candle interval (e.g., "1m", "15m", "1h")
14164
- * @returns New Date aligned down to interval boundary
14165
- */
14166
- const alignToInterval = (date, interval) => {
14167
- const minutes = INTERVAL_MINUTES$6[interval];
14168
- if (minutes === undefined) {
14169
- throw new Error(`alignToInterval: unknown interval=${interval}`);
14170
- }
14171
- const intervalMs = minutes * MS_PER_MINUTE$6;
14172
- return new Date(Math.floor(date.getTime() / intervalMs) * intervalMs);
14173
- };
14174
-
14175
14148
  /** Used to prevent race confition between concurent strategies */
14176
14149
  const RISK_LOCK = new Lock();
14177
14150
  /** Symbol indicating that positions need to be fetched from persistence */
14178
14151
  const POSITION_NEED_FETCH = Symbol("risk-need-fetch");
14179
- /** Get timestamp from execution context or fallback to aligned current time */
14180
- const GET_CONTEXT_TIMESTAMP_FN = (self) => {
14181
- if (ExecutionContextService.hasContext()) {
14182
- return self.params.execution.context.when.getTime();
14183
- }
14184
- return alignToInterval(new Date(), "1m").getTime();
14185
- };
14186
14152
  /** Zero PNL constant for scheduled signals (which don't have priceOpen or PNL yet) */
14187
14153
  const ZERO_PNL = { pnlPercentage: 0, priceOpen: 0, priceClose: 0, pnlCost: 0, pnlEntries: 0 };
14188
14154
  /**
@@ -14308,7 +14274,7 @@ const CALL_ALLOWED_CALLBACKS_FN = trycatch(async (self, symbol, params) => {
14308
14274
  *
14309
14275
  * In backtest mode, initializes with empty Map. In live mode, reads from persist storage.
14310
14276
  */
14311
- const WAIT_FOR_INIT_FN$3 = async (self) => {
14277
+ const WAIT_FOR_INIT_FN$3 = async (when, self) => {
14312
14278
  self.params.logger.debug("ClientRisk waitForInit", {
14313
14279
  backtest: self.params.backtest,
14314
14280
  });
@@ -14316,7 +14282,7 @@ const WAIT_FOR_INIT_FN$3 = async (self) => {
14316
14282
  self._activePositions = new Map();
14317
14283
  return;
14318
14284
  }
14319
- const persistedPositions = await PersistRiskAdapter.readPositionData(self.params.riskName, self.params.exchangeName);
14285
+ const persistedPositions = await PersistRiskAdapter.readPositionData(self.params.riskName, self.params.exchangeName, when);
14320
14286
  self._activePositions = new Map(persistedPositions);
14321
14287
  };
14322
14288
  /**
@@ -14345,7 +14311,7 @@ class ClientRisk {
14345
14311
  * Uses singleshot pattern to ensure initialization happens exactly once.
14346
14312
  * Skips persistence in backtest mode.
14347
14313
  */
14348
- 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));
14349
14315
  /**
14350
14316
  * Checks if a signal should be allowed based on risk limits.
14351
14317
  *
@@ -14367,11 +14333,15 @@ class ClientRisk {
14367
14333
  });
14368
14334
  await RISK_LOCK.acquireLock();
14369
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);
14370
14341
  if (this._activePositions === POSITION_NEED_FETCH) {
14371
- await this.waitForInit();
14342
+ await this.waitForInit(new Date(timestamp));
14372
14343
  }
14373
14344
  const riskMap = this._activePositions;
14374
- const timestamp = GET_CONTEXT_TIMESTAMP_FN(this);
14375
14345
  const payload = {
14376
14346
  ...params,
14377
14347
  currentSignal: TO_RISK_SIGNAL(params.currentSignal, params.currentPrice, timestamp),
@@ -14474,14 +14444,14 @@ class ClientRisk {
14474
14444
  * Persists current active positions to disk.
14475
14445
  * Skips in backtest mode.
14476
14446
  */
14477
- async _updatePositions() {
14447
+ async _updatePositions(when) {
14478
14448
  if (this.params.backtest) {
14479
14449
  return;
14480
14450
  }
14481
14451
  if (this._activePositions === POSITION_NEED_FETCH) {
14482
- await this.waitForInit();
14452
+ await this.waitForInit(when);
14483
14453
  }
14484
- 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);
14485
14455
  }
14486
14456
  /**
14487
14457
  * Registers a new opened signal.
@@ -14496,8 +14466,9 @@ class ClientRisk {
14496
14466
  });
14497
14467
  await RISK_LOCK.acquireLock();
14498
14468
  try {
14469
+ const timestamp = await this.params.time.getTimestamp(symbol, context, this.params.backtest);
14499
14470
  if (this._activePositions === POSITION_NEED_FETCH) {
14500
- await this.waitForInit();
14471
+ await this.waitForInit(new Date(timestamp));
14501
14472
  }
14502
14473
  const key = CREATE_NAME_FN(context.strategyName, context.exchangeName, symbol);
14503
14474
  const riskMap = this._activePositions;
@@ -14513,7 +14484,7 @@ class ClientRisk {
14513
14484
  minuteEstimatedTime: positionData.minuteEstimatedTime,
14514
14485
  openTimestamp: positionData.openTimestamp,
14515
14486
  });
14516
- await this._updatePositions();
14487
+ await this._updatePositions(new Date(timestamp));
14517
14488
  }
14518
14489
  finally {
14519
14490
  await RISK_LOCK.releaseLock();
@@ -14531,13 +14502,14 @@ class ClientRisk {
14531
14502
  });
14532
14503
  await RISK_LOCK.acquireLock();
14533
14504
  try {
14505
+ const timestamp = await this.params.time.getTimestamp(symbol, context, this.params.backtest);
14534
14506
  if (this._activePositions === POSITION_NEED_FETCH) {
14535
- await this.waitForInit();
14507
+ await this.waitForInit(new Date(timestamp));
14536
14508
  }
14537
14509
  const key = CREATE_NAME_FN(context.strategyName, context.exchangeName, symbol);
14538
14510
  const riskMap = this._activePositions;
14539
14511
  riskMap.delete(key);
14540
- await this._updatePositions();
14512
+ await this._updatePositions(new Date(timestamp));
14541
14513
  }
14542
14514
  finally {
14543
14515
  await RISK_LOCK.releaseLock();
@@ -14637,7 +14609,7 @@ class RiskConnectionService {
14637
14609
  constructor() {
14638
14610
  this.loggerService = inject(TYPES.loggerService);
14639
14611
  this.riskSchemaService = inject(TYPES.riskSchemaService);
14640
- this.executionContextService = inject(TYPES.executionContextService);
14612
+ this.timeMetaService = inject(TYPES.timeMetaService);
14641
14613
  /**
14642
14614
  * Action core service injected from DI container.
14643
14615
  */
@@ -14659,7 +14631,7 @@ class RiskConnectionService {
14659
14631
  return new ClientRisk({
14660
14632
  ...schema,
14661
14633
  logger: this.loggerService,
14662
- execution: this.executionContextService,
14634
+ time: this.timeMetaService,
14663
14635
  backtest,
14664
14636
  exchangeName,
14665
14637
  onRejected: CREATE_COMMIT_REJECTION_FN(this, exchangeName, frameName),
@@ -19650,8 +19622,8 @@ class BacktestLogicPrivateService {
19650
19622
  }
19651
19623
 
19652
19624
  const EMITTER_CHECK_INTERVAL = 5000;
19653
- const MS_PER_MINUTE$5 = 60000;
19654
- const INTERVAL_MINUTES$5 = {
19625
+ const MS_PER_MINUTE$6 = 60000;
19626
+ const INTERVAL_MINUTES$6 = {
19655
19627
  "1m": 1,
19656
19628
  "3m": 3,
19657
19629
  "5m": 5,
@@ -19666,7 +19638,7 @@ const INTERVAL_MINUTES$5 = {
19666
19638
  };
19667
19639
  const createEmitter = memoize(([interval]) => `${interval}`, (interval) => {
19668
19640
  const tickSubject = new Subject();
19669
- const intervalMs = INTERVAL_MINUTES$5[interval] * MS_PER_MINUTE$5;
19641
+ const intervalMs = INTERVAL_MINUTES$6[interval] * MS_PER_MINUTE$6;
19670
19642
  {
19671
19643
  let lastAligned = Math.floor(Date.now() / intervalMs) * intervalMs;
19672
19644
  Source.fromInterval(EMITTER_CHECK_INTERVAL)
@@ -19693,6 +19665,46 @@ const waitForCandle = async (interval) => {
19693
19665
  return emitter.toPromise();
19694
19666
  };
19695
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
+
19696
19708
  /**
19697
19709
  * Private service for live trading orchestration using async generators.
19698
19710
  *
@@ -27191,7 +27203,7 @@ const HANDLE_PROFIT_FN = async (symbol, data, currentPrice, revenuePercent, back
27191
27203
  }
27192
27204
  }
27193
27205
  if (shouldPersist) {
27194
- 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);
27195
27207
  }
27196
27208
  };
27197
27209
  /**
@@ -27241,7 +27253,7 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
27241
27253
  }
27242
27254
  }
27243
27255
  if (shouldPersist) {
27244
- 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);
27245
27257
  }
27246
27258
  };
27247
27259
  /**
@@ -27258,7 +27270,7 @@ const HANDLE_LOSS_FN = async (symbol, data, currentPrice, lossPercent, backtest,
27258
27270
  * @param backtest - True if backtest mode, false if live mode
27259
27271
  * @param self - ClientPartial instance reference
27260
27272
  */
27261
- 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) => {
27262
27274
  self.params.logger.debug("ClientPartial waitForInit", {
27263
27275
  symbol,
27264
27276
  backtest,
@@ -27274,7 +27286,12 @@ const WAIT_FOR_INIT_FN$1 = async (symbol, strategyName, exchangeName, backtest,
27274
27286
  self.params.logger.debug("ClientPartial waitForInit: skipping persist read in backtest mode");
27275
27287
  return;
27276
27288
  }
27277
- 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));
27278
27295
  for (const [signalId, data] of Object.entries(partialData)) {
27279
27296
  const state = {
27280
27297
  profitLevels: new Set(data.profitLevels),
@@ -27382,7 +27399,7 @@ class ClientPartial {
27382
27399
  * // Now profit()/loss() can be called
27383
27400
  * ```
27384
27401
  */
27385
- 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));
27386
27403
  }
27387
27404
  /**
27388
27405
  * Persists current partial state to disk.
@@ -27400,7 +27417,7 @@ class ClientPartial {
27400
27417
  * @param signalId - Signal identifier
27401
27418
  * @returns Promise that resolves when persistence is complete
27402
27419
  */
27403
- async _persistState(symbol, strategyName, exchangeName, signalId) {
27420
+ async _persistState(symbol, strategyName, exchangeName, frameName, signalId) {
27404
27421
  if (this.params.backtest) {
27405
27422
  return;
27406
27423
  }
@@ -27415,7 +27432,12 @@ class ClientPartial {
27415
27432
  lossLevels: Array.from(state.lossLevels),
27416
27433
  };
27417
27434
  }
27418
- 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));
27419
27441
  }
27420
27442
  /**
27421
27443
  * Processes profit state and emits events for newly reached profit levels.
@@ -27540,7 +27562,7 @@ class ClientPartial {
27540
27562
  throw new Error(`Signal ID mismatch: expected ${this.params.signalId}, got ${data.id}`);
27541
27563
  }
27542
27564
  this._states.delete(data.id);
27543
- 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);
27544
27566
  }
27545
27567
  }
27546
27568
 
@@ -27665,6 +27687,7 @@ class PartialConnectionService {
27665
27687
  * Action core service injected from DI container.
27666
27688
  */
27667
27689
  this.actionCoreService = inject(TYPES.actionCoreService);
27690
+ this.timeMetaService = inject(TYPES.timeMetaService);
27668
27691
  /**
27669
27692
  * Memoized factory function for ClientPartial instances.
27670
27693
  *
@@ -27678,6 +27701,7 @@ class PartialConnectionService {
27678
27701
  return new ClientPartial({
27679
27702
  signalId,
27680
27703
  logger: this.loggerService,
27704
+ time: this.timeMetaService,
27681
27705
  backtest,
27682
27706
  onProfit: CREATE_COMMIT_PROFIT_FN(this),
27683
27707
  onLoss: CREATE_COMMIT_LOSS_FN(this),
@@ -27707,7 +27731,7 @@ class PartialConnectionService {
27707
27731
  when,
27708
27732
  });
27709
27733
  const partial = this.getPartial(data.id, backtest);
27710
- await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
27734
+ await partial.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
27711
27735
  return await partial.profit(symbol, data, currentPrice, revenuePercent, backtest, when);
27712
27736
  };
27713
27737
  /**
@@ -27734,7 +27758,7 @@ class PartialConnectionService {
27734
27758
  when,
27735
27759
  });
27736
27760
  const partial = this.getPartial(data.id, backtest);
27737
- await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
27761
+ await partial.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
27738
27762
  return await partial.loss(symbol, data, currentPrice, lossPercent, backtest, when);
27739
27763
  };
27740
27764
  /**
@@ -27762,7 +27786,7 @@ class PartialConnectionService {
27762
27786
  backtest,
27763
27787
  });
27764
27788
  const partial = this.getPartial(data.id, backtest);
27765
- await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
27789
+ await partial.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
27766
27790
  await partial.clear(symbol, data, priceClose, backtest);
27767
27791
  const key = CREATE_KEY_FN$l(data.id, backtest);
27768
27792
  this.getPartial.clear(key);
@@ -28488,7 +28512,7 @@ const HANDLE_BREAKEVEN_FN = async (symbol, data, currentPrice, backtest, when, s
28488
28512
  // Emit event
28489
28513
  await self.params.onBreakeven(symbol, data.strategyName, data.exchangeName, data.frameName, data, currentPrice, backtest, when.getTime());
28490
28514
  // Persist state
28491
- 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);
28492
28516
  return true;
28493
28517
  };
28494
28518
  /**
@@ -28503,7 +28527,7 @@ const HANDLE_BREAKEVEN_FN = async (symbol, data, currentPrice, backtest, when, s
28503
28527
  * @param exchangeName - Exchange identifier
28504
28528
  * @param self - ClientBreakeven instance reference
28505
28529
  */
28506
- const WAIT_FOR_INIT_FN = async (symbol, strategyName, exchangeName, backtest, self) => {
28530
+ const WAIT_FOR_INIT_FN = async (symbol, strategyName, exchangeName, frameName, backtest, self) => {
28507
28531
  self.params.logger.debug("ClientBreakeven waitForInit", {
28508
28532
  symbol,
28509
28533
  strategyName,
@@ -28519,7 +28543,12 @@ const WAIT_FOR_INIT_FN = async (symbol, strategyName, exchangeName, backtest, se
28519
28543
  self.params.logger.debug("ClientBreakeven waitForInit: skipping persist read in backtest mode");
28520
28544
  return;
28521
28545
  }
28522
- 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));
28523
28552
  for (const [signalId, data] of Object.entries(breakevenData)) {
28524
28553
  const state = {
28525
28554
  reached: data.reached,
@@ -28624,7 +28653,7 @@ class ClientBreakeven {
28624
28653
  * // Now check() can be called
28625
28654
  * ```
28626
28655
  */
28627
- 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));
28628
28657
  }
28629
28658
  /**
28630
28659
  * Persists current breakeven state to disk.
@@ -28641,7 +28670,7 @@ class ClientBreakeven {
28641
28670
  * @param signalId - Signal identifier
28642
28671
  * @returns Promise that resolves when persistence is complete
28643
28672
  */
28644
- async _persistState(symbol, strategyName, exchangeName, signalId) {
28673
+ async _persistState(symbol, strategyName, exchangeName, frameName, signalId) {
28645
28674
  if (this.params.backtest) {
28646
28675
  return;
28647
28676
  }
@@ -28655,7 +28684,12 @@ class ClientBreakeven {
28655
28684
  reached: state.reached,
28656
28685
  };
28657
28686
  }
28658
- 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));
28659
28693
  }
28660
28694
  /**
28661
28695
  * Checks if breakeven should be triggered and emits event if conditions met.
@@ -28746,7 +28780,7 @@ class ClientBreakeven {
28746
28780
  throw new Error(`Signal ID mismatch: expected ${this.params.signalId}, got ${data.id}`);
28747
28781
  }
28748
28782
  this._states.delete(data.id);
28749
- 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);
28750
28784
  }
28751
28785
  }
28752
28786
 
@@ -28835,6 +28869,7 @@ class BreakevenConnectionService {
28835
28869
  * Action core service injected from DI container.
28836
28870
  */
28837
28871
  this.actionCoreService = inject(TYPES.actionCoreService);
28872
+ this.timeMetaService = inject(TYPES.timeMetaService);
28838
28873
  /**
28839
28874
  * Memoized factory function for ClientBreakeven instances.
28840
28875
  *
@@ -28848,6 +28883,7 @@ class BreakevenConnectionService {
28848
28883
  return new ClientBreakeven({
28849
28884
  signalId,
28850
28885
  logger: this.loggerService,
28886
+ time: this.timeMetaService,
28851
28887
  backtest,
28852
28888
  onBreakeven: CREATE_COMMIT_BREAKEVEN_FN(this),
28853
28889
  });
@@ -28874,7 +28910,7 @@ class BreakevenConnectionService {
28874
28910
  when,
28875
28911
  });
28876
28912
  const breakeven = this.getBreakeven(data.id, backtest);
28877
- await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
28913
+ await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
28878
28914
  return await breakeven.check(symbol, data, currentPrice, backtest, when);
28879
28915
  };
28880
28916
  /**
@@ -28903,7 +28939,7 @@ class BreakevenConnectionService {
28903
28939
  backtest,
28904
28940
  });
28905
28941
  const breakeven = this.getBreakeven(data.id, backtest);
28906
- await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
28942
+ await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, data.frameName, backtest);
28907
28943
  await breakeven.clear(symbol, data, priceClose, backtest);
28908
28944
  const key = CREATE_KEY_FN$i(data.id, backtest);
28909
28945
  this.getBreakeven.clear(key);
@@ -48500,7 +48536,7 @@ class RecentPersistBacktestUtils {
48500
48536
  backtest.loggerService.info(RECENT_PERSIST_BACKTEST_METHOD_NAME_HANDLE_ACTIVE_PING, {
48501
48537
  signalId: event.data.id,
48502
48538
  });
48503
- await PersistRecentAdapter.writeRecentData(event.data, event.symbol, event.strategyName, event.exchangeName, event.data.frameName, event.backtest);
48539
+ await PersistRecentAdapter.writeRecentData(event.data, event.symbol, event.strategyName, event.exchangeName, event.data.frameName, event.backtest, new Date(event.data.timestamp));
48504
48540
  };
48505
48541
  /**
48506
48542
  * Retrieves the latest persisted signal for the given context.
@@ -48637,7 +48673,7 @@ class RecentPersistLiveUtils {
48637
48673
  backtest.loggerService.info(RECENT_PERSIST_LIVE_METHOD_NAME_HANDLE_ACTIVE_PING, {
48638
48674
  signalId: event.data.id,
48639
48675
  });
48640
- await PersistRecentAdapter.writeRecentData(event.data, event.symbol, event.strategyName, event.exchangeName, event.data.frameName, event.backtest);
48676
+ await PersistRecentAdapter.writeRecentData(event.data, event.symbol, event.strategyName, event.exchangeName, event.data.frameName, event.backtest, new Date(event.data.timestamp));
48641
48677
  };
48642
48678
  /**
48643
48679
  * Retrieves the latest persisted signal for the given context.
@@ -49292,7 +49328,7 @@ class StatePersistInstance {
49292
49328
  }
49293
49329
  this._when = when.getTime();
49294
49330
  const id = CREATE_KEY_FN$6(this.signalId, this.bucketName);
49295
- await PersistStateAdapter.writeStateData({ id, data: this._value, when: this._when }, this.signalId, this.bucketName);
49331
+ await PersistStateAdapter.writeStateData({ id, data: this._value, when: this._when }, this.signalId, this.bucketName, when);
49296
49332
  return this._value;
49297
49333
  });
49298
49334
  }
@@ -50101,7 +50137,7 @@ class SessionPersistInstance {
50101
50137
  this._data = value;
50102
50138
  this._when = when.getTime();
50103
50139
  const id = CREATE_KEY_FN$5(this.symbol, this.strategyName, this.exchangeName, this.frameName, this.backtest);
50104
- await PersistSessionAdapter.writeSessionData({ id, data: value, when: this._when }, this.strategyName, this.exchangeName, this.frameName);
50140
+ await PersistSessionAdapter.writeSessionData({ id, data: value, when: this._when }, this.strategyName, this.exchangeName, this.frameName, when);
50105
50141
  };
50106
50142
  }
50107
50143
  /** Releases resources held by this instance. */
@@ -50885,7 +50921,7 @@ class MemoryPersistInstance {
50885
50921
  });
50886
50922
  const priority = Date.now();
50887
50923
  const whenMs = when.getTime();
50888
- await PersistMemoryAdapter.writeMemoryData({ data: value, priority, removed: false, index, when: whenMs }, this.signalId, this.bucketName, memoryId);
50924
+ await PersistMemoryAdapter.writeMemoryData({ data: value, priority, removed: false, index, when: whenMs }, this.signalId, this.bucketName, memoryId, when);
50889
50925
  this._index.upsert({
50890
50926
  id: memoryId,
50891
50927
  content: value,