backtest-kit 3.0.3 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.cjs CHANGED
@@ -428,6 +428,20 @@ const GLOBAL_CONFIG = {
428
428
  * Default: 20 levels
429
429
  */
430
430
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: 1000,
431
+ /**
432
+ * Maximum number of notifications to keep in storage.
433
+ * Older notifications are removed when this limit is exceeded.
434
+ *
435
+ * Default: 500 notifications
436
+ */
437
+ CC_MAX_NOTIFICATIONS: 500,
438
+ /**
439
+ * Maximum number of signals to keep in storage.
440
+ * Older signals are removed when this limit is exceeded.
441
+ *
442
+ * Default: 50 signals
443
+ */
444
+ CC_MAX_SIGNALS: 50,
431
445
  };
432
446
  const DEFAULT_CONFIG = Object.freeze({ ...GLOBAL_CONFIG });
433
447
 
@@ -22066,6 +22080,13 @@ class ConfigValidationService {
22066
22080
  if (!Number.isInteger(GLOBAL_CONFIG.CC_ORDER_BOOK_TIME_OFFSET_MINUTES) || GLOBAL_CONFIG.CC_ORDER_BOOK_TIME_OFFSET_MINUTES < 0) {
22067
22081
  errors.push(`CC_ORDER_BOOK_TIME_OFFSET_MINUTES must be a non-negative integer, got ${GLOBAL_CONFIG.CC_ORDER_BOOK_TIME_OFFSET_MINUTES}`);
22068
22082
  }
22083
+ // Validate notification and storage limits
22084
+ if (!Number.isInteger(GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) || GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS <= 0) {
22085
+ errors.push(`CC_MAX_NOTIFICATIONS must be a positive integer, got ${GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS}`);
22086
+ }
22087
+ if (!Number.isInteger(GLOBAL_CONFIG.CC_MAX_SIGNALS) || GLOBAL_CONFIG.CC_MAX_SIGNALS <= 0) {
22088
+ errors.push(`CC_MAX_SIGNALS must be a positive integer, got ${GLOBAL_CONFIG.CC_MAX_SIGNALS}`);
22089
+ }
22069
22090
  // Throw aggregated errors if any
22070
22091
  if (errors.length > 0) {
22071
22092
  const errorMessage = `GLOBAL_CONFIG validation failed:\n${errors.map((e, i) => ` ${i + 1}. ${e}`).join('\n')}`;
@@ -32724,7 +32745,6 @@ class ConstantUtils {
32724
32745
  */
32725
32746
  const Constant = new ConstantUtils();
32726
32747
 
32727
- const MAX_SIGNALS = 25;
32728
32748
  const STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "StoragePersistBacktestUtils.waitForInit";
32729
32749
  const STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE = "StoragePersistBacktestUtils._updateStorage";
32730
32750
  const STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED = "StoragePersistBacktestUtils.handleOpened";
@@ -32789,7 +32809,7 @@ class StoragePersistBacktestUtils {
32789
32809
  const signalList = await PersistStorageAdapter.readStorageData(true);
32790
32810
  signalList.sort((a, b) => a.priority - b.priority);
32791
32811
  this._signals = new Map(signalList
32792
- .slice(-MAX_SIGNALS)
32812
+ .slice(-GLOBAL_CONFIG.CC_MAX_SIGNALS)
32793
32813
  .map((signal) => [signal.id, signal]));
32794
32814
  });
32795
32815
  /**
@@ -32813,6 +32833,7 @@ class StoragePersistBacktestUtils {
32813
32833
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32814
32834
  updatedAt: tick.createdAt,
32815
32835
  });
32836
+ this._enforceLimit();
32816
32837
  await this._updateStorage();
32817
32838
  };
32818
32839
  /**
@@ -32837,6 +32858,7 @@ class StoragePersistBacktestUtils {
32837
32858
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32838
32859
  updatedAt: tick.createdAt,
32839
32860
  });
32861
+ this._enforceLimit();
32840
32862
  await this._updateStorage();
32841
32863
  };
32842
32864
  /**
@@ -32860,6 +32882,7 @@ class StoragePersistBacktestUtils {
32860
32882
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32861
32883
  updatedAt: tick.createdAt,
32862
32884
  });
32885
+ this._enforceLimit();
32863
32886
  await this._updateStorage();
32864
32887
  };
32865
32888
  /**
@@ -32883,6 +32906,7 @@ class StoragePersistBacktestUtils {
32883
32906
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32884
32907
  updatedAt: tick.createdAt,
32885
32908
  });
32909
+ this._enforceLimit();
32886
32910
  await this._updateStorage();
32887
32911
  };
32888
32912
  /**
@@ -32905,6 +32929,17 @@ class StoragePersistBacktestUtils {
32905
32929
  return Array.from(this._signals.values());
32906
32930
  };
32907
32931
  }
32932
+ /**
32933
+ * Removes oldest signal if limit is exceeded.
32934
+ */
32935
+ _enforceLimit() {
32936
+ if (this._signals.size > GLOBAL_CONFIG.CC_MAX_SIGNALS) {
32937
+ const firstKey = this._signals.keys().next().value;
32938
+ if (firstKey) {
32939
+ this._signals.delete(firstKey);
32940
+ }
32941
+ }
32942
+ }
32908
32943
  /**
32909
32944
  * Persists the current signal map to disk storage.
32910
32945
  * Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
@@ -32917,7 +32952,7 @@ class StoragePersistBacktestUtils {
32917
32952
  }
32918
32953
  const signalList = Array.from(this._signals.values());
32919
32954
  signalList.sort((a, b) => a.priority - b.priority);
32920
- await PersistStorageAdapter.writeStorageData(signalList.slice(-MAX_SIGNALS), true);
32955
+ await PersistStorageAdapter.writeStorageData(signalList.slice(-GLOBAL_CONFIG.CC_MAX_SIGNALS), true);
32921
32956
  }
32922
32957
  }
32923
32958
  /**
@@ -32956,6 +32991,7 @@ class StorageMemoryBacktestUtils {
32956
32991
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32957
32992
  updatedAt: tick.createdAt,
32958
32993
  });
32994
+ this._enforceLimit();
32959
32995
  };
32960
32996
  /**
32961
32997
  * Handles signal closed event.
@@ -32978,6 +33014,7 @@ class StorageMemoryBacktestUtils {
32978
33014
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32979
33015
  updatedAt: tick.createdAt,
32980
33016
  });
33017
+ this._enforceLimit();
32981
33018
  };
32982
33019
  /**
32983
33020
  * Handles signal scheduled event.
@@ -32999,6 +33036,7 @@ class StorageMemoryBacktestUtils {
32999
33036
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33000
33037
  updatedAt: tick.createdAt,
33001
33038
  });
33039
+ this._enforceLimit();
33002
33040
  };
33003
33041
  /**
33004
33042
  * Handles signal cancelled event.
@@ -33020,6 +33058,7 @@ class StorageMemoryBacktestUtils {
33020
33058
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33021
33059
  updatedAt: tick.createdAt,
33022
33060
  });
33061
+ this._enforceLimit();
33023
33062
  };
33024
33063
  /**
33025
33064
  * Finds a signal by its ID.
@@ -33039,6 +33078,17 @@ class StorageMemoryBacktestUtils {
33039
33078
  return Array.from(this._signals.values());
33040
33079
  };
33041
33080
  }
33081
+ /**
33082
+ * Removes oldest signal if limit is exceeded.
33083
+ */
33084
+ _enforceLimit() {
33085
+ if (this._signals.size > GLOBAL_CONFIG.CC_MAX_SIGNALS) {
33086
+ const firstKey = this._signals.keys().next().value;
33087
+ if (firstKey) {
33088
+ this._signals.delete(firstKey);
33089
+ }
33090
+ }
33091
+ }
33042
33092
  }
33043
33093
  /**
33044
33094
  * Dummy storage adapter for backtest signals that discards all writes.
@@ -33111,7 +33161,7 @@ class StoragePersistLiveUtils {
33111
33161
  const signalList = await PersistStorageAdapter.readStorageData(false);
33112
33162
  signalList.sort((a, b) => a.priority - b.priority);
33113
33163
  this._signals = new Map(signalList
33114
- .slice(-MAX_SIGNALS)
33164
+ .slice(-GLOBAL_CONFIG.CC_MAX_SIGNALS)
33115
33165
  .map((signal) => [signal.id, signal]));
33116
33166
  });
33117
33167
  /**
@@ -33135,6 +33185,7 @@ class StoragePersistLiveUtils {
33135
33185
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33136
33186
  updatedAt: tick.createdAt,
33137
33187
  });
33188
+ this._enforceLimit();
33138
33189
  await this._updateStorage();
33139
33190
  };
33140
33191
  /**
@@ -33159,6 +33210,7 @@ class StoragePersistLiveUtils {
33159
33210
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33160
33211
  updatedAt: tick.createdAt,
33161
33212
  });
33213
+ this._enforceLimit();
33162
33214
  await this._updateStorage();
33163
33215
  };
33164
33216
  /**
@@ -33182,6 +33234,7 @@ class StoragePersistLiveUtils {
33182
33234
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33183
33235
  updatedAt: tick.createdAt,
33184
33236
  });
33237
+ this._enforceLimit();
33185
33238
  await this._updateStorage();
33186
33239
  };
33187
33240
  /**
@@ -33205,6 +33258,7 @@ class StoragePersistLiveUtils {
33205
33258
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33206
33259
  updatedAt: tick.createdAt,
33207
33260
  });
33261
+ this._enforceLimit();
33208
33262
  await this._updateStorage();
33209
33263
  };
33210
33264
  /**
@@ -33227,6 +33281,17 @@ class StoragePersistLiveUtils {
33227
33281
  return Array.from(this._signals.values());
33228
33282
  };
33229
33283
  }
33284
+ /**
33285
+ * Removes oldest signal if limit is exceeded.
33286
+ */
33287
+ _enforceLimit() {
33288
+ if (this._signals.size > GLOBAL_CONFIG.CC_MAX_SIGNALS) {
33289
+ const firstKey = this._signals.keys().next().value;
33290
+ if (firstKey) {
33291
+ this._signals.delete(firstKey);
33292
+ }
33293
+ }
33294
+ }
33230
33295
  /**
33231
33296
  * Persists the current signal map to disk storage.
33232
33297
  * Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
@@ -33239,7 +33304,7 @@ class StoragePersistLiveUtils {
33239
33304
  }
33240
33305
  const signalList = Array.from(this._signals.values());
33241
33306
  signalList.sort((a, b) => a.priority - b.priority);
33242
- await PersistStorageAdapter.writeStorageData(signalList.slice(-MAX_SIGNALS), false);
33307
+ await PersistStorageAdapter.writeStorageData(signalList.slice(-GLOBAL_CONFIG.CC_MAX_SIGNALS), false);
33243
33308
  }
33244
33309
  }
33245
33310
  /**
@@ -33278,6 +33343,7 @@ class StorageMemoryLiveUtils {
33278
33343
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33279
33344
  updatedAt: tick.createdAt,
33280
33345
  });
33346
+ this._enforceLimit();
33281
33347
  };
33282
33348
  /**
33283
33349
  * Handles signal closed event.
@@ -33300,6 +33366,7 @@ class StorageMemoryLiveUtils {
33300
33366
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33301
33367
  updatedAt: tick.createdAt,
33302
33368
  });
33369
+ this._enforceLimit();
33303
33370
  };
33304
33371
  /**
33305
33372
  * Handles signal scheduled event.
@@ -33321,6 +33388,7 @@ class StorageMemoryLiveUtils {
33321
33388
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33322
33389
  updatedAt: tick.createdAt,
33323
33390
  });
33391
+ this._enforceLimit();
33324
33392
  };
33325
33393
  /**
33326
33394
  * Handles signal cancelled event.
@@ -33342,6 +33410,7 @@ class StorageMemoryLiveUtils {
33342
33410
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33343
33411
  updatedAt: tick.createdAt,
33344
33412
  });
33413
+ this._enforceLimit();
33345
33414
  };
33346
33415
  /**
33347
33416
  * Finds a signal by its ID.
@@ -33361,6 +33430,17 @@ class StorageMemoryLiveUtils {
33361
33430
  return Array.from(this._signals.values());
33362
33431
  };
33363
33432
  }
33433
+ /**
33434
+ * Removes oldest signal if limit is exceeded.
33435
+ */
33436
+ _enforceLimit() {
33437
+ if (this._signals.size > GLOBAL_CONFIG.CC_MAX_SIGNALS) {
33438
+ const firstKey = this._signals.keys().next().value;
33439
+ if (firstKey) {
33440
+ this._signals.delete(firstKey);
33441
+ }
33442
+ }
33443
+ }
33364
33444
  }
33365
33445
  /**
33366
33446
  * Dummy storage adapter for live trading signals that discards all writes.
@@ -33740,11 +33820,6 @@ const StorageLive = new StorageLiveAdapter();
33740
33820
  */
33741
33821
  const StorageBacktest = new StorageBacktestAdapter();
33742
33822
 
33743
- /**
33744
- * Maximum number of notifications to keep in storage.
33745
- * Older notifications are removed when this limit is exceeded.
33746
- */
33747
- const MAX_NOTIFICATIONS = 250;
33748
33823
  /**
33749
33824
  * Generates a unique key for notification identification.
33750
33825
  * @returns Random string identifier
@@ -34225,7 +34300,7 @@ class NotificationMemoryBacktestUtils {
34225
34300
  */
34226
34301
  this.handleSignal = async (data) => {
34227
34302
  bt.loggerService.info(NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL, {
34228
- signalId: data.signal.id,
34303
+ signalId: data.signal?.id,
34229
34304
  action: data.action,
34230
34305
  });
34231
34306
  const notification = CREATE_SIGNAL_NOTIFICATION_FN(data);
@@ -34343,7 +34418,7 @@ class NotificationMemoryBacktestUtils {
34343
34418
  */
34344
34419
  _addNotification(notification) {
34345
34420
  this._notifications.unshift(notification);
34346
- if (this._notifications.length > MAX_NOTIFICATIONS) {
34421
+ if (this._notifications.length > GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) {
34347
34422
  this._notifications.pop();
34348
34423
  }
34349
34424
  }
@@ -34444,7 +34519,7 @@ class NotificationPersistBacktestUtils {
34444
34519
  return aTime - bTime;
34445
34520
  });
34446
34521
  this._notifications = new Map(notificationList
34447
- .slice(-MAX_NOTIFICATIONS)
34522
+ .slice(-GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS)
34448
34523
  .map((notification) => [notification.id, notification]));
34449
34524
  });
34450
34525
  /**
@@ -34454,7 +34529,7 @@ class NotificationPersistBacktestUtils {
34454
34529
  */
34455
34530
  this.handleSignal = async (data) => {
34456
34531
  bt.loggerService.info(NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL, {
34457
- signalId: data.signal.id,
34532
+ signalId: data.signal?.id,
34458
34533
  action: data.action,
34459
34534
  });
34460
34535
  await this.waitForInit();
@@ -34602,7 +34677,7 @@ class NotificationPersistBacktestUtils {
34602
34677
  const bTime = 'createdAt' in b ? b.createdAt : 0;
34603
34678
  return aTime - bTime;
34604
34679
  });
34605
- await PersistNotificationAdapter.writeNotificationData(notificationList.slice(-MAX_NOTIFICATIONS), true);
34680
+ await PersistNotificationAdapter.writeNotificationData(notificationList.slice(-GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS), true);
34606
34681
  }
34607
34682
  /**
34608
34683
  * Adds a notification to the map.
@@ -34611,7 +34686,7 @@ class NotificationPersistBacktestUtils {
34611
34686
  */
34612
34687
  _addNotification(notification) {
34613
34688
  this._notifications.set(notification.id, notification);
34614
- if (this._notifications.size > MAX_NOTIFICATIONS) {
34689
+ if (this._notifications.size > GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) {
34615
34690
  const firstKey = this._notifications.keys().next().value;
34616
34691
  if (firstKey) {
34617
34692
  this._notifications.delete(firstKey);
@@ -34642,7 +34717,7 @@ class NotificationMemoryLiveUtils {
34642
34717
  */
34643
34718
  this.handleSignal = async (data) => {
34644
34719
  bt.loggerService.info(NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL, {
34645
- signalId: data.signal.id,
34720
+ signalId: data.signal?.id,
34646
34721
  action: data.action,
34647
34722
  });
34648
34723
  const notification = CREATE_SIGNAL_NOTIFICATION_FN(data);
@@ -34760,7 +34835,7 @@ class NotificationMemoryLiveUtils {
34760
34835
  */
34761
34836
  _addNotification(notification) {
34762
34837
  this._notifications.unshift(notification);
34763
- if (this._notifications.length > MAX_NOTIFICATIONS) {
34838
+ if (this._notifications.length > GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) {
34764
34839
  this._notifications.pop();
34765
34840
  }
34766
34841
  }
@@ -34862,7 +34937,7 @@ class NotificationPersistLiveUtils {
34862
34937
  return aTime - bTime;
34863
34938
  });
34864
34939
  this._notifications = new Map(notificationList
34865
- .slice(-MAX_NOTIFICATIONS)
34940
+ .slice(-GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS)
34866
34941
  .map((notification) => [notification.id, notification]));
34867
34942
  });
34868
34943
  /**
@@ -34872,7 +34947,7 @@ class NotificationPersistLiveUtils {
34872
34947
  */
34873
34948
  this.handleSignal = async (data) => {
34874
34949
  bt.loggerService.info(NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL, {
34875
- signalId: data.signal.id,
34950
+ signalId: data.signal?.id,
34876
34951
  action: data.action,
34877
34952
  });
34878
34953
  await this.waitForInit();
@@ -35022,7 +35097,7 @@ class NotificationPersistLiveUtils {
35022
35097
  const bTime = 'createdAt' in b ? b.createdAt : 0;
35023
35098
  return aTime - bTime;
35024
35099
  });
35025
- await PersistNotificationAdapter.writeNotificationData(notificationList.slice(-MAX_NOTIFICATIONS), false);
35100
+ await PersistNotificationAdapter.writeNotificationData(notificationList.slice(-GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS), false);
35026
35101
  }
35027
35102
  /**
35028
35103
  * Adds a notification to the map.
@@ -35031,7 +35106,7 @@ class NotificationPersistLiveUtils {
35031
35106
  */
35032
35107
  _addNotification(notification) {
35033
35108
  this._notifications.set(notification.id, notification);
35034
- if (this._notifications.size > MAX_NOTIFICATIONS) {
35109
+ if (this._notifications.size > GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) {
35035
35110
  const firstKey = this._notifications.keys().next().value;
35036
35111
  if (firstKey) {
35037
35112
  this._notifications.delete(firstKey);
package/build/index.mjs CHANGED
@@ -408,6 +408,20 @@ const GLOBAL_CONFIG = {
408
408
  * Default: 20 levels
409
409
  */
410
410
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: 1000,
411
+ /**
412
+ * Maximum number of notifications to keep in storage.
413
+ * Older notifications are removed when this limit is exceeded.
414
+ *
415
+ * Default: 500 notifications
416
+ */
417
+ CC_MAX_NOTIFICATIONS: 500,
418
+ /**
419
+ * Maximum number of signals to keep in storage.
420
+ * Older signals are removed when this limit is exceeded.
421
+ *
422
+ * Default: 50 signals
423
+ */
424
+ CC_MAX_SIGNALS: 50,
411
425
  };
412
426
  const DEFAULT_CONFIG = Object.freeze({ ...GLOBAL_CONFIG });
413
427
 
@@ -22046,6 +22060,13 @@ class ConfigValidationService {
22046
22060
  if (!Number.isInteger(GLOBAL_CONFIG.CC_ORDER_BOOK_TIME_OFFSET_MINUTES) || GLOBAL_CONFIG.CC_ORDER_BOOK_TIME_OFFSET_MINUTES < 0) {
22047
22061
  errors.push(`CC_ORDER_BOOK_TIME_OFFSET_MINUTES must be a non-negative integer, got ${GLOBAL_CONFIG.CC_ORDER_BOOK_TIME_OFFSET_MINUTES}`);
22048
22062
  }
22063
+ // Validate notification and storage limits
22064
+ if (!Number.isInteger(GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) || GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS <= 0) {
22065
+ errors.push(`CC_MAX_NOTIFICATIONS must be a positive integer, got ${GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS}`);
22066
+ }
22067
+ if (!Number.isInteger(GLOBAL_CONFIG.CC_MAX_SIGNALS) || GLOBAL_CONFIG.CC_MAX_SIGNALS <= 0) {
22068
+ errors.push(`CC_MAX_SIGNALS must be a positive integer, got ${GLOBAL_CONFIG.CC_MAX_SIGNALS}`);
22069
+ }
22049
22070
  // Throw aggregated errors if any
22050
22071
  if (errors.length > 0) {
22051
22072
  const errorMessage = `GLOBAL_CONFIG validation failed:\n${errors.map((e, i) => ` ${i + 1}. ${e}`).join('\n')}`;
@@ -32704,7 +32725,6 @@ class ConstantUtils {
32704
32725
  */
32705
32726
  const Constant = new ConstantUtils();
32706
32727
 
32707
- const MAX_SIGNALS = 25;
32708
32728
  const STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "StoragePersistBacktestUtils.waitForInit";
32709
32729
  const STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE = "StoragePersistBacktestUtils._updateStorage";
32710
32730
  const STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED = "StoragePersistBacktestUtils.handleOpened";
@@ -32769,7 +32789,7 @@ class StoragePersistBacktestUtils {
32769
32789
  const signalList = await PersistStorageAdapter.readStorageData(true);
32770
32790
  signalList.sort((a, b) => a.priority - b.priority);
32771
32791
  this._signals = new Map(signalList
32772
- .slice(-MAX_SIGNALS)
32792
+ .slice(-GLOBAL_CONFIG.CC_MAX_SIGNALS)
32773
32793
  .map((signal) => [signal.id, signal]));
32774
32794
  });
32775
32795
  /**
@@ -32793,6 +32813,7 @@ class StoragePersistBacktestUtils {
32793
32813
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32794
32814
  updatedAt: tick.createdAt,
32795
32815
  });
32816
+ this._enforceLimit();
32796
32817
  await this._updateStorage();
32797
32818
  };
32798
32819
  /**
@@ -32817,6 +32838,7 @@ class StoragePersistBacktestUtils {
32817
32838
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32818
32839
  updatedAt: tick.createdAt,
32819
32840
  });
32841
+ this._enforceLimit();
32820
32842
  await this._updateStorage();
32821
32843
  };
32822
32844
  /**
@@ -32840,6 +32862,7 @@ class StoragePersistBacktestUtils {
32840
32862
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32841
32863
  updatedAt: tick.createdAt,
32842
32864
  });
32865
+ this._enforceLimit();
32843
32866
  await this._updateStorage();
32844
32867
  };
32845
32868
  /**
@@ -32863,6 +32886,7 @@ class StoragePersistBacktestUtils {
32863
32886
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32864
32887
  updatedAt: tick.createdAt,
32865
32888
  });
32889
+ this._enforceLimit();
32866
32890
  await this._updateStorage();
32867
32891
  };
32868
32892
  /**
@@ -32885,6 +32909,17 @@ class StoragePersistBacktestUtils {
32885
32909
  return Array.from(this._signals.values());
32886
32910
  };
32887
32911
  }
32912
+ /**
32913
+ * Removes oldest signal if limit is exceeded.
32914
+ */
32915
+ _enforceLimit() {
32916
+ if (this._signals.size > GLOBAL_CONFIG.CC_MAX_SIGNALS) {
32917
+ const firstKey = this._signals.keys().next().value;
32918
+ if (firstKey) {
32919
+ this._signals.delete(firstKey);
32920
+ }
32921
+ }
32922
+ }
32888
32923
  /**
32889
32924
  * Persists the current signal map to disk storage.
32890
32925
  * Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
@@ -32897,7 +32932,7 @@ class StoragePersistBacktestUtils {
32897
32932
  }
32898
32933
  const signalList = Array.from(this._signals.values());
32899
32934
  signalList.sort((a, b) => a.priority - b.priority);
32900
- await PersistStorageAdapter.writeStorageData(signalList.slice(-MAX_SIGNALS), true);
32935
+ await PersistStorageAdapter.writeStorageData(signalList.slice(-GLOBAL_CONFIG.CC_MAX_SIGNALS), true);
32901
32936
  }
32902
32937
  }
32903
32938
  /**
@@ -32936,6 +32971,7 @@ class StorageMemoryBacktestUtils {
32936
32971
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32937
32972
  updatedAt: tick.createdAt,
32938
32973
  });
32974
+ this._enforceLimit();
32939
32975
  };
32940
32976
  /**
32941
32977
  * Handles signal closed event.
@@ -32958,6 +32994,7 @@ class StorageMemoryBacktestUtils {
32958
32994
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32959
32995
  updatedAt: tick.createdAt,
32960
32996
  });
32997
+ this._enforceLimit();
32961
32998
  };
32962
32999
  /**
32963
33000
  * Handles signal scheduled event.
@@ -32979,6 +33016,7 @@ class StorageMemoryBacktestUtils {
32979
33016
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
32980
33017
  updatedAt: tick.createdAt,
32981
33018
  });
33019
+ this._enforceLimit();
32982
33020
  };
32983
33021
  /**
32984
33022
  * Handles signal cancelled event.
@@ -33000,6 +33038,7 @@ class StorageMemoryBacktestUtils {
33000
33038
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33001
33039
  updatedAt: tick.createdAt,
33002
33040
  });
33041
+ this._enforceLimit();
33003
33042
  };
33004
33043
  /**
33005
33044
  * Finds a signal by its ID.
@@ -33019,6 +33058,17 @@ class StorageMemoryBacktestUtils {
33019
33058
  return Array.from(this._signals.values());
33020
33059
  };
33021
33060
  }
33061
+ /**
33062
+ * Removes oldest signal if limit is exceeded.
33063
+ */
33064
+ _enforceLimit() {
33065
+ if (this._signals.size > GLOBAL_CONFIG.CC_MAX_SIGNALS) {
33066
+ const firstKey = this._signals.keys().next().value;
33067
+ if (firstKey) {
33068
+ this._signals.delete(firstKey);
33069
+ }
33070
+ }
33071
+ }
33022
33072
  }
33023
33073
  /**
33024
33074
  * Dummy storage adapter for backtest signals that discards all writes.
@@ -33091,7 +33141,7 @@ class StoragePersistLiveUtils {
33091
33141
  const signalList = await PersistStorageAdapter.readStorageData(false);
33092
33142
  signalList.sort((a, b) => a.priority - b.priority);
33093
33143
  this._signals = new Map(signalList
33094
- .slice(-MAX_SIGNALS)
33144
+ .slice(-GLOBAL_CONFIG.CC_MAX_SIGNALS)
33095
33145
  .map((signal) => [signal.id, signal]));
33096
33146
  });
33097
33147
  /**
@@ -33115,6 +33165,7 @@ class StoragePersistLiveUtils {
33115
33165
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33116
33166
  updatedAt: tick.createdAt,
33117
33167
  });
33168
+ this._enforceLimit();
33118
33169
  await this._updateStorage();
33119
33170
  };
33120
33171
  /**
@@ -33139,6 +33190,7 @@ class StoragePersistLiveUtils {
33139
33190
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33140
33191
  updatedAt: tick.createdAt,
33141
33192
  });
33193
+ this._enforceLimit();
33142
33194
  await this._updateStorage();
33143
33195
  };
33144
33196
  /**
@@ -33162,6 +33214,7 @@ class StoragePersistLiveUtils {
33162
33214
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33163
33215
  updatedAt: tick.createdAt,
33164
33216
  });
33217
+ this._enforceLimit();
33165
33218
  await this._updateStorage();
33166
33219
  };
33167
33220
  /**
@@ -33185,6 +33238,7 @@ class StoragePersistLiveUtils {
33185
33238
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33186
33239
  updatedAt: tick.createdAt,
33187
33240
  });
33241
+ this._enforceLimit();
33188
33242
  await this._updateStorage();
33189
33243
  };
33190
33244
  /**
@@ -33207,6 +33261,17 @@ class StoragePersistLiveUtils {
33207
33261
  return Array.from(this._signals.values());
33208
33262
  };
33209
33263
  }
33264
+ /**
33265
+ * Removes oldest signal if limit is exceeded.
33266
+ */
33267
+ _enforceLimit() {
33268
+ if (this._signals.size > GLOBAL_CONFIG.CC_MAX_SIGNALS) {
33269
+ const firstKey = this._signals.keys().next().value;
33270
+ if (firstKey) {
33271
+ this._signals.delete(firstKey);
33272
+ }
33273
+ }
33274
+ }
33210
33275
  /**
33211
33276
  * Persists the current signal map to disk storage.
33212
33277
  * Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
@@ -33219,7 +33284,7 @@ class StoragePersistLiveUtils {
33219
33284
  }
33220
33285
  const signalList = Array.from(this._signals.values());
33221
33286
  signalList.sort((a, b) => a.priority - b.priority);
33222
- await PersistStorageAdapter.writeStorageData(signalList.slice(-MAX_SIGNALS), false);
33287
+ await PersistStorageAdapter.writeStorageData(signalList.slice(-GLOBAL_CONFIG.CC_MAX_SIGNALS), false);
33223
33288
  }
33224
33289
  }
33225
33290
  /**
@@ -33258,6 +33323,7 @@ class StorageMemoryLiveUtils {
33258
33323
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33259
33324
  updatedAt: tick.createdAt,
33260
33325
  });
33326
+ this._enforceLimit();
33261
33327
  };
33262
33328
  /**
33263
33329
  * Handles signal closed event.
@@ -33280,6 +33346,7 @@ class StorageMemoryLiveUtils {
33280
33346
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33281
33347
  updatedAt: tick.createdAt,
33282
33348
  });
33349
+ this._enforceLimit();
33283
33350
  };
33284
33351
  /**
33285
33352
  * Handles signal scheduled event.
@@ -33301,6 +33368,7 @@ class StorageMemoryLiveUtils {
33301
33368
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33302
33369
  updatedAt: tick.createdAt,
33303
33370
  });
33371
+ this._enforceLimit();
33304
33372
  };
33305
33373
  /**
33306
33374
  * Handles signal cancelled event.
@@ -33322,6 +33390,7 @@ class StorageMemoryLiveUtils {
33322
33390
  createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
33323
33391
  updatedAt: tick.createdAt,
33324
33392
  });
33393
+ this._enforceLimit();
33325
33394
  };
33326
33395
  /**
33327
33396
  * Finds a signal by its ID.
@@ -33341,6 +33410,17 @@ class StorageMemoryLiveUtils {
33341
33410
  return Array.from(this._signals.values());
33342
33411
  };
33343
33412
  }
33413
+ /**
33414
+ * Removes oldest signal if limit is exceeded.
33415
+ */
33416
+ _enforceLimit() {
33417
+ if (this._signals.size > GLOBAL_CONFIG.CC_MAX_SIGNALS) {
33418
+ const firstKey = this._signals.keys().next().value;
33419
+ if (firstKey) {
33420
+ this._signals.delete(firstKey);
33421
+ }
33422
+ }
33423
+ }
33344
33424
  }
33345
33425
  /**
33346
33426
  * Dummy storage adapter for live trading signals that discards all writes.
@@ -33720,11 +33800,6 @@ const StorageLive = new StorageLiveAdapter();
33720
33800
  */
33721
33801
  const StorageBacktest = new StorageBacktestAdapter();
33722
33802
 
33723
- /**
33724
- * Maximum number of notifications to keep in storage.
33725
- * Older notifications are removed when this limit is exceeded.
33726
- */
33727
- const MAX_NOTIFICATIONS = 250;
33728
33803
  /**
33729
33804
  * Generates a unique key for notification identification.
33730
33805
  * @returns Random string identifier
@@ -34205,7 +34280,7 @@ class NotificationMemoryBacktestUtils {
34205
34280
  */
34206
34281
  this.handleSignal = async (data) => {
34207
34282
  bt.loggerService.info(NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SIGNAL, {
34208
- signalId: data.signal.id,
34283
+ signalId: data.signal?.id,
34209
34284
  action: data.action,
34210
34285
  });
34211
34286
  const notification = CREATE_SIGNAL_NOTIFICATION_FN(data);
@@ -34323,7 +34398,7 @@ class NotificationMemoryBacktestUtils {
34323
34398
  */
34324
34399
  _addNotification(notification) {
34325
34400
  this._notifications.unshift(notification);
34326
- if (this._notifications.length > MAX_NOTIFICATIONS) {
34401
+ if (this._notifications.length > GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) {
34327
34402
  this._notifications.pop();
34328
34403
  }
34329
34404
  }
@@ -34424,7 +34499,7 @@ class NotificationPersistBacktestUtils {
34424
34499
  return aTime - bTime;
34425
34500
  });
34426
34501
  this._notifications = new Map(notificationList
34427
- .slice(-MAX_NOTIFICATIONS)
34502
+ .slice(-GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS)
34428
34503
  .map((notification) => [notification.id, notification]));
34429
34504
  });
34430
34505
  /**
@@ -34434,7 +34509,7 @@ class NotificationPersistBacktestUtils {
34434
34509
  */
34435
34510
  this.handleSignal = async (data) => {
34436
34511
  bt.loggerService.info(NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SIGNAL, {
34437
- signalId: data.signal.id,
34512
+ signalId: data.signal?.id,
34438
34513
  action: data.action,
34439
34514
  });
34440
34515
  await this.waitForInit();
@@ -34582,7 +34657,7 @@ class NotificationPersistBacktestUtils {
34582
34657
  const bTime = 'createdAt' in b ? b.createdAt : 0;
34583
34658
  return aTime - bTime;
34584
34659
  });
34585
- await PersistNotificationAdapter.writeNotificationData(notificationList.slice(-MAX_NOTIFICATIONS), true);
34660
+ await PersistNotificationAdapter.writeNotificationData(notificationList.slice(-GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS), true);
34586
34661
  }
34587
34662
  /**
34588
34663
  * Adds a notification to the map.
@@ -34591,7 +34666,7 @@ class NotificationPersistBacktestUtils {
34591
34666
  */
34592
34667
  _addNotification(notification) {
34593
34668
  this._notifications.set(notification.id, notification);
34594
- if (this._notifications.size > MAX_NOTIFICATIONS) {
34669
+ if (this._notifications.size > GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) {
34595
34670
  const firstKey = this._notifications.keys().next().value;
34596
34671
  if (firstKey) {
34597
34672
  this._notifications.delete(firstKey);
@@ -34622,7 +34697,7 @@ class NotificationMemoryLiveUtils {
34622
34697
  */
34623
34698
  this.handleSignal = async (data) => {
34624
34699
  bt.loggerService.info(NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SIGNAL, {
34625
- signalId: data.signal.id,
34700
+ signalId: data.signal?.id,
34626
34701
  action: data.action,
34627
34702
  });
34628
34703
  const notification = CREATE_SIGNAL_NOTIFICATION_FN(data);
@@ -34740,7 +34815,7 @@ class NotificationMemoryLiveUtils {
34740
34815
  */
34741
34816
  _addNotification(notification) {
34742
34817
  this._notifications.unshift(notification);
34743
- if (this._notifications.length > MAX_NOTIFICATIONS) {
34818
+ if (this._notifications.length > GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) {
34744
34819
  this._notifications.pop();
34745
34820
  }
34746
34821
  }
@@ -34842,7 +34917,7 @@ class NotificationPersistLiveUtils {
34842
34917
  return aTime - bTime;
34843
34918
  });
34844
34919
  this._notifications = new Map(notificationList
34845
- .slice(-MAX_NOTIFICATIONS)
34920
+ .slice(-GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS)
34846
34921
  .map((notification) => [notification.id, notification]));
34847
34922
  });
34848
34923
  /**
@@ -34852,7 +34927,7 @@ class NotificationPersistLiveUtils {
34852
34927
  */
34853
34928
  this.handleSignal = async (data) => {
34854
34929
  bt.loggerService.info(NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SIGNAL, {
34855
- signalId: data.signal.id,
34930
+ signalId: data.signal?.id,
34856
34931
  action: data.action,
34857
34932
  });
34858
34933
  await this.waitForInit();
@@ -35002,7 +35077,7 @@ class NotificationPersistLiveUtils {
35002
35077
  const bTime = 'createdAt' in b ? b.createdAt : 0;
35003
35078
  return aTime - bTime;
35004
35079
  });
35005
- await PersistNotificationAdapter.writeNotificationData(notificationList.slice(-MAX_NOTIFICATIONS), false);
35080
+ await PersistNotificationAdapter.writeNotificationData(notificationList.slice(-GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS), false);
35006
35081
  }
35007
35082
  /**
35008
35083
  * Adds a notification to the map.
@@ -35011,7 +35086,7 @@ class NotificationPersistLiveUtils {
35011
35086
  */
35012
35087
  _addNotification(notification) {
35013
35088
  this._notifications.set(notification.id, notification);
35014
- if (this._notifications.size > MAX_NOTIFICATIONS) {
35089
+ if (this._notifications.size > GLOBAL_CONFIG.CC_MAX_NOTIFICATIONS) {
35015
35090
  const firstKey = this._notifications.keys().next().value;
35016
35091
  if (firstKey) {
35017
35092
  this._notifications.delete(firstKey);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "3.0.3",
3
+ "version": "3.0.4",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
package/types.d.ts CHANGED
@@ -4209,6 +4209,20 @@ declare const GLOBAL_CONFIG: {
4209
4209
  * Default: 20 levels
4210
4210
  */
4211
4211
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: number;
4212
+ /**
4213
+ * Maximum number of notifications to keep in storage.
4214
+ * Older notifications are removed when this limit is exceeded.
4215
+ *
4216
+ * Default: 500 notifications
4217
+ */
4218
+ CC_MAX_NOTIFICATIONS: number;
4219
+ /**
4220
+ * Maximum number of signals to keep in storage.
4221
+ * Older signals are removed when this limit is exceeded.
4222
+ *
4223
+ * Default: 50 signals
4224
+ */
4225
+ CC_MAX_SIGNALS: number;
4212
4226
  };
4213
4227
  /**
4214
4228
  * Type for global configuration object.
@@ -4315,6 +4329,8 @@ declare function getConfig(): {
4315
4329
  CC_BREAKEVEN_THRESHOLD: number;
4316
4330
  CC_ORDER_BOOK_TIME_OFFSET_MINUTES: number;
4317
4331
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: number;
4332
+ CC_MAX_NOTIFICATIONS: number;
4333
+ CC_MAX_SIGNALS: number;
4318
4334
  };
4319
4335
  /**
4320
4336
  * Retrieves the default configuration object for the framework.
@@ -4349,6 +4365,8 @@ declare function getDefaultConfig(): Readonly<{
4349
4365
  CC_BREAKEVEN_THRESHOLD: number;
4350
4366
  CC_ORDER_BOOK_TIME_OFFSET_MINUTES: number;
4351
4367
  CC_ORDER_BOOK_MAX_DEPTH_LEVELS: number;
4368
+ CC_MAX_NOTIFICATIONS: number;
4369
+ CC_MAX_SIGNALS: number;
4352
4370
  }>;
4353
4371
  /**
4354
4372
  * Sets custom column configurations for markdown report generation.