backtest-kit 2.2.16 → 2.2.18
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 +739 -209
- package/build/index.mjs +738 -210
- package/package.json +1 -1
- package/types.d.ts +240 -133
package/build/index.cjs
CHANGED
|
@@ -2867,73 +2867,78 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, timestamp) => {
|
|
|
2867
2867
|
return;
|
|
2868
2868
|
}
|
|
2869
2869
|
const queue = self._commitQueue;
|
|
2870
|
-
|
|
2870
|
+
{
|
|
2871
|
+
self._commitQueue = [];
|
|
2872
|
+
}
|
|
2871
2873
|
for (const commit of queue) {
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2874
|
+
if (commit.action === "partial-profit") {
|
|
2875
|
+
await CALL_COMMIT_FN(self, {
|
|
2876
|
+
action: "partial-profit",
|
|
2877
|
+
symbol: commit.symbol,
|
|
2878
|
+
strategyName: self.params.strategyName,
|
|
2879
|
+
exchangeName: self.params.exchangeName,
|
|
2880
|
+
frameName: self.params.frameName,
|
|
2881
|
+
backtest: commit.backtest,
|
|
2882
|
+
percentToClose: commit.percentToClose,
|
|
2883
|
+
currentPrice: commit.currentPrice,
|
|
2884
|
+
timestamp,
|
|
2885
|
+
});
|
|
2886
|
+
continue;
|
|
2887
|
+
}
|
|
2888
|
+
if (commit.action === "partial-loss") {
|
|
2889
|
+
await CALL_COMMIT_FN(self, {
|
|
2890
|
+
action: "partial-loss",
|
|
2891
|
+
symbol: commit.symbol,
|
|
2892
|
+
strategyName: self.params.strategyName,
|
|
2893
|
+
exchangeName: self.params.exchangeName,
|
|
2894
|
+
frameName: self.params.frameName,
|
|
2895
|
+
backtest: commit.backtest,
|
|
2896
|
+
percentToClose: commit.percentToClose,
|
|
2897
|
+
currentPrice: commit.currentPrice,
|
|
2898
|
+
timestamp,
|
|
2899
|
+
});
|
|
2900
|
+
continue;
|
|
2901
|
+
}
|
|
2902
|
+
if (commit.action === "breakeven") {
|
|
2903
|
+
await CALL_COMMIT_FN(self, {
|
|
2904
|
+
action: "breakeven",
|
|
2905
|
+
symbol: commit.symbol,
|
|
2906
|
+
strategyName: self.params.strategyName,
|
|
2907
|
+
exchangeName: self.params.exchangeName,
|
|
2908
|
+
frameName: self.params.frameName,
|
|
2909
|
+
backtest: commit.backtest,
|
|
2910
|
+
currentPrice: commit.currentPrice,
|
|
2911
|
+
timestamp,
|
|
2912
|
+
});
|
|
2913
|
+
continue;
|
|
2914
|
+
}
|
|
2915
|
+
if (commit.action === "trailing-stop") {
|
|
2916
|
+
await CALL_COMMIT_FN(self, {
|
|
2917
|
+
action: "trailing-stop",
|
|
2918
|
+
symbol: commit.symbol,
|
|
2919
|
+
strategyName: self.params.strategyName,
|
|
2920
|
+
exchangeName: self.params.exchangeName,
|
|
2921
|
+
frameName: self.params.frameName,
|
|
2922
|
+
backtest: commit.backtest,
|
|
2923
|
+
percentShift: commit.percentShift,
|
|
2924
|
+
currentPrice: commit.currentPrice,
|
|
2925
|
+
timestamp,
|
|
2926
|
+
});
|
|
2927
|
+
continue;
|
|
2928
|
+
}
|
|
2929
|
+
if (commit.action === "trailing-take") {
|
|
2930
|
+
await CALL_COMMIT_FN(self, {
|
|
2931
|
+
action: "trailing-take",
|
|
2932
|
+
symbol: commit.symbol,
|
|
2933
|
+
strategyName: self.params.strategyName,
|
|
2934
|
+
exchangeName: self.params.exchangeName,
|
|
2935
|
+
frameName: self.params.frameName,
|
|
2936
|
+
backtest: commit.backtest,
|
|
2937
|
+
percentShift: commit.percentShift,
|
|
2938
|
+
currentPrice: commit.currentPrice,
|
|
2939
|
+
timestamp,
|
|
2940
|
+
});
|
|
2941
|
+
continue;
|
|
2937
2942
|
}
|
|
2938
2943
|
}
|
|
2939
2944
|
};
|
|
@@ -23626,7 +23631,7 @@ class RiskReportService {
|
|
|
23626
23631
|
strategyName: data.strategyName,
|
|
23627
23632
|
exchangeName: data.exchangeName,
|
|
23628
23633
|
frameName: data.frameName,
|
|
23629
|
-
signalId: "",
|
|
23634
|
+
signalId: data.pendingSignal?.id || "",
|
|
23630
23635
|
walkerName: "",
|
|
23631
23636
|
});
|
|
23632
23637
|
};
|
|
@@ -31617,53 +31622,64 @@ class ConstantUtils {
|
|
|
31617
31622
|
const Constant = new ConstantUtils();
|
|
31618
31623
|
|
|
31619
31624
|
const MAX_SIGNALS = 25;
|
|
31620
|
-
const STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "
|
|
31621
|
-
const STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE = "
|
|
31622
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED = "
|
|
31623
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CLOSED = "
|
|
31624
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED = "
|
|
31625
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CANCELLED = "
|
|
31626
|
-
const STORAGE_BACKTEST_METHOD_NAME_FIND_BY_ID = "
|
|
31627
|
-
const STORAGE_BACKTEST_METHOD_NAME_LIST = "
|
|
31628
|
-
const STORAGE_LIVE_METHOD_NAME_WAIT_FOR_INIT = "
|
|
31629
|
-
const STORAGE_LIVE_METHOD_NAME_UPDATE_STORAGE = "
|
|
31630
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_OPENED = "
|
|
31631
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_CLOSED = "
|
|
31632
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_SCHEDULED = "
|
|
31633
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_CANCELLED = "
|
|
31634
|
-
const STORAGE_LIVE_METHOD_NAME_FIND_BY_ID = "
|
|
31635
|
-
const STORAGE_LIVE_METHOD_NAME_LIST = "
|
|
31625
|
+
const STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "StoragePersistBacktestUtils.waitForInit";
|
|
31626
|
+
const STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE = "StoragePersistBacktestUtils._updateStorage";
|
|
31627
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED = "StoragePersistBacktestUtils.handleOpened";
|
|
31628
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CLOSED = "StoragePersistBacktestUtils.handleClosed";
|
|
31629
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED = "StoragePersistBacktestUtils.handleScheduled";
|
|
31630
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CANCELLED = "StoragePersistBacktestUtils.handleCancelled";
|
|
31631
|
+
const STORAGE_BACKTEST_METHOD_NAME_FIND_BY_ID = "StoragePersistBacktestUtils.findById";
|
|
31632
|
+
const STORAGE_BACKTEST_METHOD_NAME_LIST = "StoragePersistBacktestUtils.list";
|
|
31633
|
+
const STORAGE_LIVE_METHOD_NAME_WAIT_FOR_INIT = "StoragePersistLiveUtils.waitForInit";
|
|
31634
|
+
const STORAGE_LIVE_METHOD_NAME_UPDATE_STORAGE = "StoragePersistLiveUtils._updateStorage";
|
|
31635
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_OPENED = "StoragePersistLiveUtils.handleOpened";
|
|
31636
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_CLOSED = "StoragePersistLiveUtils.handleClosed";
|
|
31637
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_SCHEDULED = "StoragePersistLiveUtils.handleScheduled";
|
|
31638
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_CANCELLED = "StoragePersistLiveUtils.handleCancelled";
|
|
31639
|
+
const STORAGE_LIVE_METHOD_NAME_FIND_BY_ID = "StoragePersistLiveUtils.findById";
|
|
31640
|
+
const STORAGE_LIVE_METHOD_NAME_LIST = "StoragePersistLiveUtils.list";
|
|
31641
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_OPENED = "StorageMemoryBacktestUtils.handleOpened";
|
|
31642
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CLOSED = "StorageMemoryBacktestUtils.handleClosed";
|
|
31643
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED = "StorageMemoryBacktestUtils.handleScheduled";
|
|
31644
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CANCELLED = "StorageMemoryBacktestUtils.handleCancelled";
|
|
31645
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_FIND_BY_ID = "StorageMemoryBacktestUtils.findById";
|
|
31646
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_LIST = "StorageMemoryBacktestUtils.list";
|
|
31647
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_OPENED = "StorageMemoryLiveUtils.handleOpened";
|
|
31648
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CLOSED = "StorageMemoryLiveUtils.handleClosed";
|
|
31649
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_SCHEDULED = "StorageMemoryLiveUtils.handleScheduled";
|
|
31650
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CANCELLED = "StorageMemoryLiveUtils.handleCancelled";
|
|
31651
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_FIND_BY_ID = "StorageMemoryLiveUtils.findById";
|
|
31652
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_LIST = "StorageMemoryLiveUtils.list";
|
|
31636
31653
|
const STORAGE_ADAPTER_METHOD_NAME_ENABLE = "StorageAdapter.enable";
|
|
31637
31654
|
const STORAGE_ADAPTER_METHOD_NAME_DISABLE = "StorageAdapter.disable";
|
|
31638
31655
|
const STORAGE_ADAPTER_METHOD_NAME_FIND_SIGNAL_BY_ID = "StorageAdapter.findSignalById";
|
|
31639
31656
|
const STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_BACKTEST = "StorageAdapter.listSignalBacktest";
|
|
31640
31657
|
const STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_LIVE = "StorageAdapter.listSignalLive";
|
|
31658
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER = "StorageBacktestAdapter.useStorageAdapter";
|
|
31659
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY = "StorageBacktestAdapter.useDummy";
|
|
31660
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST = "StorageBacktestAdapter.usePersist";
|
|
31661
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY = "StorageBacktestAdapter.useMemory";
|
|
31662
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER = "StorageLiveAdapter.useStorageAdapter";
|
|
31663
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY = "StorageLiveAdapter.useDummy";
|
|
31664
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST = "StorageLiveAdapter.usePersist";
|
|
31665
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY = "StorageLiveAdapter.useMemory";
|
|
31641
31666
|
/**
|
|
31642
|
-
*
|
|
31643
|
-
*
|
|
31644
|
-
* Stores trading signal history for admin dashboard display during backtesting
|
|
31645
|
-
* with automatic initialization, deduplication, and storage limits.
|
|
31646
|
-
*
|
|
31647
|
-
* @example
|
|
31648
|
-
* ```typescript
|
|
31649
|
-
* import { StorageBacktestUtils } from "./classes/Storage";
|
|
31667
|
+
* Persistent storage adapter for backtest signals.
|
|
31650
31668
|
*
|
|
31651
|
-
*
|
|
31652
|
-
*
|
|
31653
|
-
*
|
|
31654
|
-
*
|
|
31655
|
-
*
|
|
31669
|
+
* Features:
|
|
31670
|
+
* - Persists signals to disk using PersistStorageAdapter
|
|
31671
|
+
* - Lazy initialization with singleshot pattern
|
|
31672
|
+
* - Maintains up to MAX_SIGNALS (25) most recent signals
|
|
31673
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
31674
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31656
31675
|
*
|
|
31657
|
-
*
|
|
31658
|
-
* const signal = await storage.findById("signal-123");
|
|
31659
|
-
* const allSignals = await storage.list();
|
|
31660
|
-
* ```
|
|
31676
|
+
* Use this adapter (default) for backtest signal persistence across sessions.
|
|
31661
31677
|
*/
|
|
31662
|
-
class
|
|
31678
|
+
class StoragePersistBacktestUtils {
|
|
31663
31679
|
constructor() {
|
|
31664
31680
|
/**
|
|
31665
|
-
*
|
|
31666
|
-
*
|
|
31681
|
+
* Singleshot initialization function that loads signals from disk.
|
|
31682
|
+
* Protected by singleshot to ensure one-time execution.
|
|
31667
31683
|
*/
|
|
31668
31684
|
this.waitForInit = functoolsKit.singleshot(async () => {
|
|
31669
31685
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT);
|
|
@@ -31675,9 +31691,8 @@ class StorageBacktestUtils {
|
|
|
31675
31691
|
});
|
|
31676
31692
|
/**
|
|
31677
31693
|
* Handles signal opened event.
|
|
31678
|
-
*
|
|
31679
|
-
* @param tick -
|
|
31680
|
-
* @returns Promise resolving when storage is updated
|
|
31694
|
+
* Updates storage with opened status if not stale.
|
|
31695
|
+
* @param tick - The opened signal tick data
|
|
31681
31696
|
*/
|
|
31682
31697
|
this.handleOpened = async (tick) => {
|
|
31683
31698
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED, {
|
|
@@ -31699,9 +31714,8 @@ class StorageBacktestUtils {
|
|
|
31699
31714
|
};
|
|
31700
31715
|
/**
|
|
31701
31716
|
* Handles signal closed event.
|
|
31702
|
-
*
|
|
31703
|
-
* @param tick -
|
|
31704
|
-
* @returns Promise resolving when storage is updated
|
|
31717
|
+
* Updates storage with closed status and PnL if not stale.
|
|
31718
|
+
* @param tick - The closed signal tick data
|
|
31705
31719
|
*/
|
|
31706
31720
|
this.handleClosed = async (tick) => {
|
|
31707
31721
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_CLOSED, {
|
|
@@ -31724,9 +31738,8 @@ class StorageBacktestUtils {
|
|
|
31724
31738
|
};
|
|
31725
31739
|
/**
|
|
31726
31740
|
* Handles signal scheduled event.
|
|
31727
|
-
*
|
|
31728
|
-
* @param tick -
|
|
31729
|
-
* @returns Promise resolving when storage is updated
|
|
31741
|
+
* Updates storage with scheduled status if not stale.
|
|
31742
|
+
* @param tick - The scheduled signal tick data
|
|
31730
31743
|
*/
|
|
31731
31744
|
this.handleScheduled = async (tick) => {
|
|
31732
31745
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
@@ -31748,9 +31761,8 @@ class StorageBacktestUtils {
|
|
|
31748
31761
|
};
|
|
31749
31762
|
/**
|
|
31750
31763
|
* Handles signal cancelled event.
|
|
31751
|
-
*
|
|
31752
|
-
* @param tick -
|
|
31753
|
-
* @returns Promise resolving when storage is updated
|
|
31764
|
+
* Updates storage with cancelled status if not stale.
|
|
31765
|
+
* @param tick - The cancelled signal tick data
|
|
31754
31766
|
*/
|
|
31755
31767
|
this.handleCancelled = async (tick) => {
|
|
31756
31768
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_CANCELLED, {
|
|
@@ -31771,10 +31783,9 @@ class StorageBacktestUtils {
|
|
|
31771
31783
|
await this._updateStorage();
|
|
31772
31784
|
};
|
|
31773
31785
|
/**
|
|
31774
|
-
* Finds a signal by its
|
|
31775
|
-
*
|
|
31776
|
-
* @
|
|
31777
|
-
* @returns Promise resolving to signal row or null if not found
|
|
31786
|
+
* Finds a signal by its ID.
|
|
31787
|
+
* @param id - The signal ID to search for
|
|
31788
|
+
* @returns The signal row or null if not found
|
|
31778
31789
|
*/
|
|
31779
31790
|
this.findById = async (id) => {
|
|
31780
31791
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_FIND_BY_ID, { id });
|
|
@@ -31782,9 +31793,8 @@ class StorageBacktestUtils {
|
|
|
31782
31793
|
return this._signals.get(id) ?? null;
|
|
31783
31794
|
};
|
|
31784
31795
|
/**
|
|
31785
|
-
* Lists all stored
|
|
31786
|
-
*
|
|
31787
|
-
* @returns Promise resolving to array of signal rows
|
|
31796
|
+
* Lists all stored signals.
|
|
31797
|
+
* @returns Array of all signal rows
|
|
31788
31798
|
*/
|
|
31789
31799
|
this.list = async () => {
|
|
31790
31800
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_LIST);
|
|
@@ -31793,15 +31803,14 @@ class StorageBacktestUtils {
|
|
|
31793
31803
|
};
|
|
31794
31804
|
}
|
|
31795
31805
|
/**
|
|
31796
|
-
* Persists current signal
|
|
31797
|
-
* Sorts by priority and
|
|
31798
|
-
*
|
|
31799
|
-
* @throws Error if storage not initialized
|
|
31806
|
+
* Persists the current signal map to disk storage.
|
|
31807
|
+
* Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
|
|
31808
|
+
* @throws Error if not initialized
|
|
31800
31809
|
*/
|
|
31801
31810
|
async _updateStorage() {
|
|
31802
31811
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE);
|
|
31803
31812
|
if (!this._signals) {
|
|
31804
|
-
throw new Error("
|
|
31813
|
+
throw new Error("StoragePersistBacktestUtils not initialized. Call waitForInit first.");
|
|
31805
31814
|
}
|
|
31806
31815
|
const signalList = Array.from(this._signals.values());
|
|
31807
31816
|
signalList.sort((a, b) => a.priority - b.priority);
|
|
@@ -31809,31 +31818,190 @@ class StorageBacktestUtils {
|
|
|
31809
31818
|
}
|
|
31810
31819
|
}
|
|
31811
31820
|
/**
|
|
31812
|
-
*
|
|
31821
|
+
* In-memory storage adapter for backtest signals.
|
|
31813
31822
|
*
|
|
31814
|
-
*
|
|
31815
|
-
*
|
|
31823
|
+
* Features:
|
|
31824
|
+
* - Stores signals in memory only (no persistence)
|
|
31825
|
+
* - Fast read/write operations
|
|
31826
|
+
* - Data is lost when application restarts
|
|
31827
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
31828
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31816
31829
|
*
|
|
31817
|
-
*
|
|
31818
|
-
|
|
31819
|
-
|
|
31830
|
+
* Use this adapter for testing or when persistence is not required.
|
|
31831
|
+
*/
|
|
31832
|
+
class StorageMemoryBacktestUtils {
|
|
31833
|
+
constructor() {
|
|
31834
|
+
/** Map of signal IDs to signal rows */
|
|
31835
|
+
this._signals = new Map();
|
|
31836
|
+
/**
|
|
31837
|
+
* Handles signal opened event.
|
|
31838
|
+
* Updates in-memory storage with opened status if not stale.
|
|
31839
|
+
* @param tick - The opened signal tick data
|
|
31840
|
+
*/
|
|
31841
|
+
this.handleOpened = async (tick) => {
|
|
31842
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_OPENED, {
|
|
31843
|
+
signalId: tick.signal.id,
|
|
31844
|
+
});
|
|
31845
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
31846
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
31847
|
+
return;
|
|
31848
|
+
}
|
|
31849
|
+
this._signals.set(tick.signal.id, {
|
|
31850
|
+
...tick.signal,
|
|
31851
|
+
status: "opened",
|
|
31852
|
+
priority: Date.now(),
|
|
31853
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
31854
|
+
updatedAt: tick.createdAt,
|
|
31855
|
+
});
|
|
31856
|
+
};
|
|
31857
|
+
/**
|
|
31858
|
+
* Handles signal closed event.
|
|
31859
|
+
* Updates in-memory storage with closed status and PnL if not stale.
|
|
31860
|
+
* @param tick - The closed signal tick data
|
|
31861
|
+
*/
|
|
31862
|
+
this.handleClosed = async (tick) => {
|
|
31863
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CLOSED, {
|
|
31864
|
+
signalId: tick.signal.id,
|
|
31865
|
+
});
|
|
31866
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
31867
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
31868
|
+
return;
|
|
31869
|
+
}
|
|
31870
|
+
this._signals.set(tick.signal.id, {
|
|
31871
|
+
...tick.signal,
|
|
31872
|
+
status: "closed",
|
|
31873
|
+
priority: Date.now(),
|
|
31874
|
+
pnl: tick.pnl,
|
|
31875
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
31876
|
+
updatedAt: tick.createdAt,
|
|
31877
|
+
});
|
|
31878
|
+
};
|
|
31879
|
+
/**
|
|
31880
|
+
* Handles signal scheduled event.
|
|
31881
|
+
* Updates in-memory storage with scheduled status if not stale.
|
|
31882
|
+
* @param tick - The scheduled signal tick data
|
|
31883
|
+
*/
|
|
31884
|
+
this.handleScheduled = async (tick) => {
|
|
31885
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
31886
|
+
signalId: tick.signal.id,
|
|
31887
|
+
});
|
|
31888
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
31889
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
31890
|
+
return;
|
|
31891
|
+
}
|
|
31892
|
+
this._signals.set(tick.signal.id, {
|
|
31893
|
+
...tick.signal,
|
|
31894
|
+
status: "scheduled",
|
|
31895
|
+
priority: Date.now(),
|
|
31896
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
31897
|
+
updatedAt: tick.createdAt,
|
|
31898
|
+
});
|
|
31899
|
+
};
|
|
31900
|
+
/**
|
|
31901
|
+
* Handles signal cancelled event.
|
|
31902
|
+
* Updates in-memory storage with cancelled status if not stale.
|
|
31903
|
+
* @param tick - The cancelled signal tick data
|
|
31904
|
+
*/
|
|
31905
|
+
this.handleCancelled = async (tick) => {
|
|
31906
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CANCELLED, {
|
|
31907
|
+
signalId: tick.signal.id,
|
|
31908
|
+
});
|
|
31909
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
31910
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
31911
|
+
return;
|
|
31912
|
+
}
|
|
31913
|
+
this._signals.set(tick.signal.id, {
|
|
31914
|
+
...tick.signal,
|
|
31915
|
+
status: "cancelled",
|
|
31916
|
+
priority: Date.now(),
|
|
31917
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
31918
|
+
updatedAt: tick.createdAt,
|
|
31919
|
+
});
|
|
31920
|
+
};
|
|
31921
|
+
/**
|
|
31922
|
+
* Finds a signal by its ID.
|
|
31923
|
+
* @param id - The signal ID to search for
|
|
31924
|
+
* @returns The signal row or null if not found
|
|
31925
|
+
*/
|
|
31926
|
+
this.findById = async (id) => {
|
|
31927
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_FIND_BY_ID, { id });
|
|
31928
|
+
return this._signals.get(id) ?? null;
|
|
31929
|
+
};
|
|
31930
|
+
/**
|
|
31931
|
+
* Lists all stored signals.
|
|
31932
|
+
* @returns Array of all signal rows
|
|
31933
|
+
*/
|
|
31934
|
+
this.list = async () => {
|
|
31935
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_LIST);
|
|
31936
|
+
return Array.from(this._signals.values());
|
|
31937
|
+
};
|
|
31938
|
+
}
|
|
31939
|
+
}
|
|
31940
|
+
/**
|
|
31941
|
+
* Dummy storage adapter for backtest signals that discards all writes.
|
|
31942
|
+
*
|
|
31943
|
+
* Features:
|
|
31944
|
+
* - No-op implementation for all methods
|
|
31945
|
+
* - findById always returns null
|
|
31946
|
+
* - list always returns empty array
|
|
31820
31947
|
*
|
|
31821
|
-
*
|
|
31948
|
+
* Use this adapter to disable backtest signal storage completely.
|
|
31949
|
+
*/
|
|
31950
|
+
class StorageDummyBacktestUtils {
|
|
31951
|
+
constructor() {
|
|
31952
|
+
/**
|
|
31953
|
+
* No-op handler for signal opened event.
|
|
31954
|
+
*/
|
|
31955
|
+
this.handleOpened = async () => {
|
|
31956
|
+
};
|
|
31957
|
+
/**
|
|
31958
|
+
* No-op handler for signal closed event.
|
|
31959
|
+
*/
|
|
31960
|
+
this.handleClosed = async () => {
|
|
31961
|
+
};
|
|
31962
|
+
/**
|
|
31963
|
+
* No-op handler for signal scheduled event.
|
|
31964
|
+
*/
|
|
31965
|
+
this.handleScheduled = async () => {
|
|
31966
|
+
};
|
|
31967
|
+
/**
|
|
31968
|
+
* No-op handler for signal cancelled event.
|
|
31969
|
+
*/
|
|
31970
|
+
this.handleCancelled = async () => {
|
|
31971
|
+
};
|
|
31972
|
+
/**
|
|
31973
|
+
* Always returns null (no storage).
|
|
31974
|
+
* @returns null
|
|
31975
|
+
*/
|
|
31976
|
+
this.findById = async () => {
|
|
31977
|
+
return null;
|
|
31978
|
+
};
|
|
31979
|
+
/**
|
|
31980
|
+
* Always returns empty array (no storage).
|
|
31981
|
+
* @returns Empty array
|
|
31982
|
+
*/
|
|
31983
|
+
this.list = async () => {
|
|
31984
|
+
return [];
|
|
31985
|
+
};
|
|
31986
|
+
}
|
|
31987
|
+
}
|
|
31988
|
+
/**
|
|
31989
|
+
* Persistent storage adapter for live trading signals.
|
|
31822
31990
|
*
|
|
31823
|
-
*
|
|
31824
|
-
*
|
|
31825
|
-
*
|
|
31991
|
+
* Features:
|
|
31992
|
+
* - Persists signals to disk using PersistStorageAdapter
|
|
31993
|
+
* - Lazy initialization with singleshot pattern
|
|
31994
|
+
* - Maintains up to MAX_SIGNALS (25) most recent signals
|
|
31995
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
31996
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31826
31997
|
*
|
|
31827
|
-
*
|
|
31828
|
-
* const signal = await storage.findById("signal-123");
|
|
31829
|
-
* const allSignals = await storage.list();
|
|
31830
|
-
* ```
|
|
31998
|
+
* Use this adapter (default) for live signal persistence across sessions.
|
|
31831
31999
|
*/
|
|
31832
|
-
class
|
|
32000
|
+
class StoragePersistLiveUtils {
|
|
31833
32001
|
constructor() {
|
|
31834
32002
|
/**
|
|
31835
|
-
*
|
|
31836
|
-
*
|
|
32003
|
+
* Singleshot initialization function that loads signals from disk.
|
|
32004
|
+
* Protected by singleshot to ensure one-time execution.
|
|
31837
32005
|
*/
|
|
31838
32006
|
this.waitForInit = functoolsKit.singleshot(async () => {
|
|
31839
32007
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_WAIT_FOR_INIT);
|
|
@@ -31845,9 +32013,8 @@ class StorageLiveUtils {
|
|
|
31845
32013
|
});
|
|
31846
32014
|
/**
|
|
31847
32015
|
* Handles signal opened event.
|
|
31848
|
-
*
|
|
31849
|
-
* @param tick -
|
|
31850
|
-
* @returns Promise resolving when history is updated
|
|
32016
|
+
* Updates storage with opened status if not stale.
|
|
32017
|
+
* @param tick - The opened signal tick data
|
|
31851
32018
|
*/
|
|
31852
32019
|
this.handleOpened = async (tick) => {
|
|
31853
32020
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_OPENED, {
|
|
@@ -31869,9 +32036,8 @@ class StorageLiveUtils {
|
|
|
31869
32036
|
};
|
|
31870
32037
|
/**
|
|
31871
32038
|
* Handles signal closed event.
|
|
31872
|
-
*
|
|
31873
|
-
* @param tick -
|
|
31874
|
-
* @returns Promise resolving when history is updated
|
|
32039
|
+
* Updates storage with closed status and PnL if not stale.
|
|
32040
|
+
* @param tick - The closed signal tick data
|
|
31875
32041
|
*/
|
|
31876
32042
|
this.handleClosed = async (tick) => {
|
|
31877
32043
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_CLOSED, {
|
|
@@ -31894,9 +32060,8 @@ class StorageLiveUtils {
|
|
|
31894
32060
|
};
|
|
31895
32061
|
/**
|
|
31896
32062
|
* Handles signal scheduled event.
|
|
31897
|
-
*
|
|
31898
|
-
* @param tick -
|
|
31899
|
-
* @returns Promise resolving when history is updated
|
|
32063
|
+
* Updates storage with scheduled status if not stale.
|
|
32064
|
+
* @param tick - The scheduled signal tick data
|
|
31900
32065
|
*/
|
|
31901
32066
|
this.handleScheduled = async (tick) => {
|
|
31902
32067
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
@@ -31918,9 +32083,8 @@ class StorageLiveUtils {
|
|
|
31918
32083
|
};
|
|
31919
32084
|
/**
|
|
31920
32085
|
* Handles signal cancelled event.
|
|
31921
|
-
*
|
|
31922
|
-
* @param tick -
|
|
31923
|
-
* @returns Promise resolving when history is updated
|
|
32086
|
+
* Updates storage with cancelled status if not stale.
|
|
32087
|
+
* @param tick - The cancelled signal tick data
|
|
31924
32088
|
*/
|
|
31925
32089
|
this.handleCancelled = async (tick) => {
|
|
31926
32090
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_CANCELLED, {
|
|
@@ -31941,10 +32105,9 @@ class StorageLiveUtils {
|
|
|
31941
32105
|
await this._updateStorage();
|
|
31942
32106
|
};
|
|
31943
32107
|
/**
|
|
31944
|
-
* Finds a signal by its
|
|
31945
|
-
*
|
|
31946
|
-
* @
|
|
31947
|
-
* @returns Promise resolving to signal row or null if not found
|
|
32108
|
+
* Finds a signal by its ID.
|
|
32109
|
+
* @param id - The signal ID to search for
|
|
32110
|
+
* @returns The signal row or null if not found
|
|
31948
32111
|
*/
|
|
31949
32112
|
this.findById = async (id) => {
|
|
31950
32113
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_FIND_BY_ID, { id });
|
|
@@ -31952,9 +32115,8 @@ class StorageLiveUtils {
|
|
|
31952
32115
|
return this._signals.get(id) ?? null;
|
|
31953
32116
|
};
|
|
31954
32117
|
/**
|
|
31955
|
-
* Lists all stored
|
|
31956
|
-
*
|
|
31957
|
-
* @returns Promise resolving to array of signal rows
|
|
32118
|
+
* Lists all stored signals.
|
|
32119
|
+
* @returns Array of all signal rows
|
|
31958
32120
|
*/
|
|
31959
32121
|
this.list = async () => {
|
|
31960
32122
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_LIST);
|
|
@@ -31963,15 +32125,14 @@ class StorageLiveUtils {
|
|
|
31963
32125
|
};
|
|
31964
32126
|
}
|
|
31965
32127
|
/**
|
|
31966
|
-
* Persists current signal
|
|
31967
|
-
* Sorts by priority and
|
|
31968
|
-
*
|
|
31969
|
-
* @throws Error if storage not initialized
|
|
32128
|
+
* Persists the current signal map to disk storage.
|
|
32129
|
+
* Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
|
|
32130
|
+
* @throws Error if not initialized
|
|
31970
32131
|
*/
|
|
31971
32132
|
async _updateStorage() {
|
|
31972
32133
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_UPDATE_STORAGE);
|
|
31973
32134
|
if (!this._signals) {
|
|
31974
|
-
throw new Error("
|
|
32135
|
+
throw new Error("StoragePersistLiveUtils not initialized. Call waitForInit first.");
|
|
31975
32136
|
}
|
|
31976
32137
|
const signalList = Array.from(this._signals.values());
|
|
31977
32138
|
signalList.sort((a, b) => a.priority - b.priority);
|
|
@@ -31979,36 +32140,385 @@ class StorageLiveUtils {
|
|
|
31979
32140
|
}
|
|
31980
32141
|
}
|
|
31981
32142
|
/**
|
|
31982
|
-
*
|
|
32143
|
+
* In-memory storage adapter for live trading signals.
|
|
31983
32144
|
*
|
|
31984
|
-
*
|
|
31985
|
-
*
|
|
31986
|
-
*
|
|
32145
|
+
* Features:
|
|
32146
|
+
* - Stores signals in memory only (no persistence)
|
|
32147
|
+
* - Fast read/write operations
|
|
32148
|
+
* - Data is lost when application restarts
|
|
32149
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
32150
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31987
32151
|
*
|
|
31988
|
-
*
|
|
31989
|
-
|
|
31990
|
-
|
|
32152
|
+
* Use this adapter for testing or when persistence is not required.
|
|
32153
|
+
*/
|
|
32154
|
+
class StorageMemoryLiveUtils {
|
|
32155
|
+
constructor() {
|
|
32156
|
+
/** Map of signal IDs to signal rows */
|
|
32157
|
+
this._signals = new Map();
|
|
32158
|
+
/**
|
|
32159
|
+
* Handles signal opened event.
|
|
32160
|
+
* Updates in-memory storage with opened status if not stale.
|
|
32161
|
+
* @param tick - The opened signal tick data
|
|
32162
|
+
*/
|
|
32163
|
+
this.handleOpened = async (tick) => {
|
|
32164
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_OPENED, {
|
|
32165
|
+
signalId: tick.signal.id,
|
|
32166
|
+
});
|
|
32167
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32168
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32169
|
+
return;
|
|
32170
|
+
}
|
|
32171
|
+
this._signals.set(tick.signal.id, {
|
|
32172
|
+
...tick.signal,
|
|
32173
|
+
status: "opened",
|
|
32174
|
+
priority: Date.now(),
|
|
32175
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32176
|
+
updatedAt: tick.createdAt,
|
|
32177
|
+
});
|
|
32178
|
+
};
|
|
32179
|
+
/**
|
|
32180
|
+
* Handles signal closed event.
|
|
32181
|
+
* Updates in-memory storage with closed status and PnL if not stale.
|
|
32182
|
+
* @param tick - The closed signal tick data
|
|
32183
|
+
*/
|
|
32184
|
+
this.handleClosed = async (tick) => {
|
|
32185
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CLOSED, {
|
|
32186
|
+
signalId: tick.signal.id,
|
|
32187
|
+
});
|
|
32188
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32189
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32190
|
+
return;
|
|
32191
|
+
}
|
|
32192
|
+
this._signals.set(tick.signal.id, {
|
|
32193
|
+
...tick.signal,
|
|
32194
|
+
status: "closed",
|
|
32195
|
+
priority: Date.now(),
|
|
32196
|
+
pnl: tick.pnl,
|
|
32197
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32198
|
+
updatedAt: tick.createdAt,
|
|
32199
|
+
});
|
|
32200
|
+
};
|
|
32201
|
+
/**
|
|
32202
|
+
* Handles signal scheduled event.
|
|
32203
|
+
* Updates in-memory storage with scheduled status if not stale.
|
|
32204
|
+
* @param tick - The scheduled signal tick data
|
|
32205
|
+
*/
|
|
32206
|
+
this.handleScheduled = async (tick) => {
|
|
32207
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
32208
|
+
signalId: tick.signal.id,
|
|
32209
|
+
});
|
|
32210
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32211
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32212
|
+
return;
|
|
32213
|
+
}
|
|
32214
|
+
this._signals.set(tick.signal.id, {
|
|
32215
|
+
...tick.signal,
|
|
32216
|
+
status: "scheduled",
|
|
32217
|
+
priority: Date.now(),
|
|
32218
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32219
|
+
updatedAt: tick.createdAt,
|
|
32220
|
+
});
|
|
32221
|
+
};
|
|
32222
|
+
/**
|
|
32223
|
+
* Handles signal cancelled event.
|
|
32224
|
+
* Updates in-memory storage with cancelled status if not stale.
|
|
32225
|
+
* @param tick - The cancelled signal tick data
|
|
32226
|
+
*/
|
|
32227
|
+
this.handleCancelled = async (tick) => {
|
|
32228
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CANCELLED, {
|
|
32229
|
+
signalId: tick.signal.id,
|
|
32230
|
+
});
|
|
32231
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32232
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32233
|
+
return;
|
|
32234
|
+
}
|
|
32235
|
+
this._signals.set(tick.signal.id, {
|
|
32236
|
+
...tick.signal,
|
|
32237
|
+
status: "cancelled",
|
|
32238
|
+
priority: Date.now(),
|
|
32239
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32240
|
+
updatedAt: tick.createdAt,
|
|
32241
|
+
});
|
|
32242
|
+
};
|
|
32243
|
+
/**
|
|
32244
|
+
* Finds a signal by its ID.
|
|
32245
|
+
* @param id - The signal ID to search for
|
|
32246
|
+
* @returns The signal row or null if not found
|
|
32247
|
+
*/
|
|
32248
|
+
this.findById = async (id) => {
|
|
32249
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_FIND_BY_ID, { id });
|
|
32250
|
+
return this._signals.get(id) ?? null;
|
|
32251
|
+
};
|
|
32252
|
+
/**
|
|
32253
|
+
* Lists all stored signals.
|
|
32254
|
+
* @returns Array of all signal rows
|
|
32255
|
+
*/
|
|
32256
|
+
this.list = async () => {
|
|
32257
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_LIST);
|
|
32258
|
+
return Array.from(this._signals.values());
|
|
32259
|
+
};
|
|
32260
|
+
}
|
|
32261
|
+
}
|
|
32262
|
+
/**
|
|
32263
|
+
* Dummy storage adapter for live trading signals that discards all writes.
|
|
31991
32264
|
*
|
|
31992
|
-
*
|
|
31993
|
-
*
|
|
32265
|
+
* Features:
|
|
32266
|
+
* - No-op implementation for all methods
|
|
32267
|
+
* - findById always returns null
|
|
32268
|
+
* - list always returns empty array
|
|
31994
32269
|
*
|
|
31995
|
-
*
|
|
31996
|
-
|
|
31997
|
-
|
|
31998
|
-
|
|
32270
|
+
* Use this adapter to disable live signal storage completely.
|
|
32271
|
+
*/
|
|
32272
|
+
class StorageDummyLiveUtils {
|
|
32273
|
+
constructor() {
|
|
32274
|
+
/**
|
|
32275
|
+
* No-op handler for signal opened event.
|
|
32276
|
+
*/
|
|
32277
|
+
this.handleOpened = async () => {
|
|
32278
|
+
};
|
|
32279
|
+
/**
|
|
32280
|
+
* No-op handler for signal closed event.
|
|
32281
|
+
*/
|
|
32282
|
+
this.handleClosed = async () => {
|
|
32283
|
+
};
|
|
32284
|
+
/**
|
|
32285
|
+
* No-op handler for signal scheduled event.
|
|
32286
|
+
*/
|
|
32287
|
+
this.handleScheduled = async () => {
|
|
32288
|
+
};
|
|
32289
|
+
/**
|
|
32290
|
+
* No-op handler for signal cancelled event.
|
|
32291
|
+
*/
|
|
32292
|
+
this.handleCancelled = async () => {
|
|
32293
|
+
};
|
|
32294
|
+
/**
|
|
32295
|
+
* Always returns null (no storage).
|
|
32296
|
+
* @returns null
|
|
32297
|
+
*/
|
|
32298
|
+
this.findById = async () => {
|
|
32299
|
+
return null;
|
|
32300
|
+
};
|
|
32301
|
+
/**
|
|
32302
|
+
* Always returns empty array (no storage).
|
|
32303
|
+
* @returns Empty array
|
|
32304
|
+
*/
|
|
32305
|
+
this.list = async () => {
|
|
32306
|
+
return [];
|
|
32307
|
+
};
|
|
32308
|
+
}
|
|
32309
|
+
}
|
|
32310
|
+
/**
|
|
32311
|
+
* Backtest storage adapter with pluggable storage backend.
|
|
31999
32312
|
*
|
|
32000
|
-
*
|
|
32001
|
-
*
|
|
32002
|
-
*
|
|
32313
|
+
* Features:
|
|
32314
|
+
* - Adapter pattern for swappable storage implementations
|
|
32315
|
+
* - Default adapter: StoragePersistBacktestUtils (persistent storage)
|
|
32316
|
+
* - Alternative adapters: StorageMemoryBacktestUtils, StorageDummyBacktestUtils
|
|
32317
|
+
* - Convenience methods: usePersist(), useMemory(), useDummy()
|
|
32318
|
+
*/
|
|
32319
|
+
class StorageBacktestAdapter {
|
|
32320
|
+
constructor() {
|
|
32321
|
+
/** Internal storage utils instance */
|
|
32322
|
+
this._signalBacktestUtils = new StorageMemoryBacktestUtils();
|
|
32323
|
+
/**
|
|
32324
|
+
* Handles signal opened event.
|
|
32325
|
+
* Proxies call to the underlying storage adapter.
|
|
32326
|
+
* @param tick - The opened signal tick data
|
|
32327
|
+
*/
|
|
32328
|
+
this.handleOpened = async (tick) => {
|
|
32329
|
+
return await this._signalBacktestUtils.handleOpened(tick);
|
|
32330
|
+
};
|
|
32331
|
+
/**
|
|
32332
|
+
* Handles signal closed event.
|
|
32333
|
+
* Proxies call to the underlying storage adapter.
|
|
32334
|
+
* @param tick - The closed signal tick data
|
|
32335
|
+
*/
|
|
32336
|
+
this.handleClosed = async (tick) => {
|
|
32337
|
+
return await this._signalBacktestUtils.handleClosed(tick);
|
|
32338
|
+
};
|
|
32339
|
+
/**
|
|
32340
|
+
* Handles signal scheduled event.
|
|
32341
|
+
* Proxies call to the underlying storage adapter.
|
|
32342
|
+
* @param tick - The scheduled signal tick data
|
|
32343
|
+
*/
|
|
32344
|
+
this.handleScheduled = async (tick) => {
|
|
32345
|
+
return await this._signalBacktestUtils.handleScheduled(tick);
|
|
32346
|
+
};
|
|
32347
|
+
/**
|
|
32348
|
+
* Handles signal cancelled event.
|
|
32349
|
+
* Proxies call to the underlying storage adapter.
|
|
32350
|
+
* @param tick - The cancelled signal tick data
|
|
32351
|
+
*/
|
|
32352
|
+
this.handleCancelled = async (tick) => {
|
|
32353
|
+
return await this._signalBacktestUtils.handleCancelled(tick);
|
|
32354
|
+
};
|
|
32355
|
+
/**
|
|
32356
|
+
* Finds a signal by its ID.
|
|
32357
|
+
* Proxies call to the underlying storage adapter.
|
|
32358
|
+
* @param id - The signal ID to search for
|
|
32359
|
+
* @returns The signal row or null if not found
|
|
32360
|
+
*/
|
|
32361
|
+
this.findById = async (id) => {
|
|
32362
|
+
return await this._signalBacktestUtils.findById(id);
|
|
32363
|
+
};
|
|
32364
|
+
/**
|
|
32365
|
+
* Lists all stored signals.
|
|
32366
|
+
* Proxies call to the underlying storage adapter.
|
|
32367
|
+
* @returns Array of all signal rows
|
|
32368
|
+
*/
|
|
32369
|
+
this.list = async () => {
|
|
32370
|
+
return await this._signalBacktestUtils.list();
|
|
32371
|
+
};
|
|
32372
|
+
/**
|
|
32373
|
+
* Sets the storage adapter constructor.
|
|
32374
|
+
* All future storage operations will use this adapter.
|
|
32375
|
+
*
|
|
32376
|
+
* @param Ctor - Constructor for storage adapter
|
|
32377
|
+
*/
|
|
32378
|
+
this.useStorageAdapter = (Ctor) => {
|
|
32379
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
32380
|
+
this._signalBacktestUtils = Reflect.construct(Ctor, []);
|
|
32381
|
+
};
|
|
32382
|
+
/**
|
|
32383
|
+
* Switches to dummy storage adapter.
|
|
32384
|
+
* All future storage writes will be no-ops.
|
|
32385
|
+
*/
|
|
32386
|
+
this.useDummy = () => {
|
|
32387
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
32388
|
+
this._signalBacktestUtils = new StorageDummyBacktestUtils();
|
|
32389
|
+
};
|
|
32390
|
+
/**
|
|
32391
|
+
* Switches to persistent storage adapter (default).
|
|
32392
|
+
* Signals will be persisted to disk.
|
|
32393
|
+
*/
|
|
32394
|
+
this.usePersist = () => {
|
|
32395
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
32396
|
+
this._signalBacktestUtils = new StoragePersistBacktestUtils();
|
|
32397
|
+
};
|
|
32398
|
+
/**
|
|
32399
|
+
* Switches to in-memory storage adapter.
|
|
32400
|
+
* Signals will be stored in memory only.
|
|
32401
|
+
*/
|
|
32402
|
+
this.useMemory = () => {
|
|
32403
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
32404
|
+
this._signalBacktestUtils = new StorageMemoryBacktestUtils();
|
|
32405
|
+
};
|
|
32406
|
+
}
|
|
32407
|
+
}
|
|
32408
|
+
/**
|
|
32409
|
+
* Live trading storage adapter with pluggable storage backend.
|
|
32410
|
+
*
|
|
32411
|
+
* Features:
|
|
32412
|
+
* - Adapter pattern for swappable storage implementations
|
|
32413
|
+
* - Default adapter: StoragePersistLiveUtils (persistent storage)
|
|
32414
|
+
* - Alternative adapters: StorageMemoryLiveUtils, StorageDummyLiveUtils
|
|
32415
|
+
* - Convenience methods: usePersist(), useMemory(), useDummy()
|
|
32416
|
+
*/
|
|
32417
|
+
class StorageLiveAdapter {
|
|
32418
|
+
constructor() {
|
|
32419
|
+
/** Internal storage utils instance */
|
|
32420
|
+
this._signalLiveUtils = new StoragePersistLiveUtils();
|
|
32421
|
+
/**
|
|
32422
|
+
* Handles signal opened event.
|
|
32423
|
+
* Proxies call to the underlying storage adapter.
|
|
32424
|
+
* @param tick - The opened signal tick data
|
|
32425
|
+
*/
|
|
32426
|
+
this.handleOpened = async (tick) => {
|
|
32427
|
+
return await this._signalLiveUtils.handleOpened(tick);
|
|
32428
|
+
};
|
|
32429
|
+
/**
|
|
32430
|
+
* Handles signal closed event.
|
|
32431
|
+
* Proxies call to the underlying storage adapter.
|
|
32432
|
+
* @param tick - The closed signal tick data
|
|
32433
|
+
*/
|
|
32434
|
+
this.handleClosed = async (tick) => {
|
|
32435
|
+
return await this._signalLiveUtils.handleClosed(tick);
|
|
32436
|
+
};
|
|
32437
|
+
/**
|
|
32438
|
+
* Handles signal scheduled event.
|
|
32439
|
+
* Proxies call to the underlying storage adapter.
|
|
32440
|
+
* @param tick - The scheduled signal tick data
|
|
32441
|
+
*/
|
|
32442
|
+
this.handleScheduled = async (tick) => {
|
|
32443
|
+
return await this._signalLiveUtils.handleScheduled(tick);
|
|
32444
|
+
};
|
|
32445
|
+
/**
|
|
32446
|
+
* Handles signal cancelled event.
|
|
32447
|
+
* Proxies call to the underlying storage adapter.
|
|
32448
|
+
* @param tick - The cancelled signal tick data
|
|
32449
|
+
*/
|
|
32450
|
+
this.handleCancelled = async (tick) => {
|
|
32451
|
+
return await this._signalLiveUtils.handleCancelled(tick);
|
|
32452
|
+
};
|
|
32453
|
+
/**
|
|
32454
|
+
* Finds a signal by its ID.
|
|
32455
|
+
* Proxies call to the underlying storage adapter.
|
|
32456
|
+
* @param id - The signal ID to search for
|
|
32457
|
+
* @returns The signal row or null if not found
|
|
32458
|
+
*/
|
|
32459
|
+
this.findById = async (id) => {
|
|
32460
|
+
return await this._signalLiveUtils.findById(id);
|
|
32461
|
+
};
|
|
32462
|
+
/**
|
|
32463
|
+
* Lists all stored signals.
|
|
32464
|
+
* Proxies call to the underlying storage adapter.
|
|
32465
|
+
* @returns Array of all signal rows
|
|
32466
|
+
*/
|
|
32467
|
+
this.list = async () => {
|
|
32468
|
+
return await this._signalLiveUtils.list();
|
|
32469
|
+
};
|
|
32470
|
+
/**
|
|
32471
|
+
* Sets the storage adapter constructor.
|
|
32472
|
+
* All future storage operations will use this adapter.
|
|
32473
|
+
*
|
|
32474
|
+
* @param Ctor - Constructor for storage adapter
|
|
32475
|
+
*/
|
|
32476
|
+
this.useStorageAdapter = (Ctor) => {
|
|
32477
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
32478
|
+
this._signalLiveUtils = Reflect.construct(Ctor, []);
|
|
32479
|
+
};
|
|
32480
|
+
/**
|
|
32481
|
+
* Switches to dummy storage adapter.
|
|
32482
|
+
* All future storage writes will be no-ops.
|
|
32483
|
+
*/
|
|
32484
|
+
this.useDummy = () => {
|
|
32485
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
32486
|
+
this._signalLiveUtils = new StorageDummyLiveUtils();
|
|
32487
|
+
};
|
|
32488
|
+
/**
|
|
32489
|
+
* Switches to persistent storage adapter (default).
|
|
32490
|
+
* Signals will be persisted to disk.
|
|
32491
|
+
*/
|
|
32492
|
+
this.usePersist = () => {
|
|
32493
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
32494
|
+
this._signalLiveUtils = new StoragePersistLiveUtils();
|
|
32495
|
+
};
|
|
32496
|
+
/**
|
|
32497
|
+
* Switches to in-memory storage adapter.
|
|
32498
|
+
* Signals will be stored in memory only.
|
|
32499
|
+
*/
|
|
32500
|
+
this.useMemory = () => {
|
|
32501
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
32502
|
+
this._signalLiveUtils = new StorageMemoryLiveUtils();
|
|
32503
|
+
};
|
|
32504
|
+
}
|
|
32505
|
+
}
|
|
32506
|
+
/**
|
|
32507
|
+
* Main storage adapter that manages both backtest and live signal storage.
|
|
32508
|
+
*
|
|
32509
|
+
* Features:
|
|
32510
|
+
* - Subscribes to signal emitters for automatic storage updates
|
|
32511
|
+
* - Provides unified access to both backtest and live signals
|
|
32512
|
+
* - Singleshot enable pattern prevents duplicate subscriptions
|
|
32513
|
+
* - Cleanup function for proper unsubscription
|
|
32003
32514
|
*/
|
|
32004
32515
|
class StorageAdapter {
|
|
32005
32516
|
constructor() {
|
|
32006
|
-
this._signalLiveUtils = new StorageLiveUtils();
|
|
32007
|
-
this._signalBacktestUtils = new StorageBacktestUtils();
|
|
32008
32517
|
/**
|
|
32009
|
-
* Enables signal
|
|
32518
|
+
* Enables signal storage by subscribing to signal emitters.
|
|
32519
|
+
* Uses singleshot to ensure one-time subscription.
|
|
32010
32520
|
*
|
|
32011
|
-
* @returns Cleanup function
|
|
32521
|
+
* @returns Cleanup function that unsubscribes from all emitters
|
|
32012
32522
|
*/
|
|
32013
32523
|
this.enable = functoolsKit.singleshot(() => {
|
|
32014
32524
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_ENABLE);
|
|
@@ -32017,31 +32527,31 @@ class StorageAdapter {
|
|
|
32017
32527
|
{
|
|
32018
32528
|
const unBacktestOpen = signalBacktestEmitter
|
|
32019
32529
|
.filter(({ action }) => action === "opened")
|
|
32020
|
-
.connect((tick) =>
|
|
32530
|
+
.connect((tick) => StorageBacktest.handleOpened(tick));
|
|
32021
32531
|
const unBacktestClose = signalBacktestEmitter
|
|
32022
32532
|
.filter(({ action }) => action === "closed")
|
|
32023
|
-
.connect((tick) =>
|
|
32533
|
+
.connect((tick) => StorageBacktest.handleClosed(tick));
|
|
32024
32534
|
const unBacktestScheduled = signalBacktestEmitter
|
|
32025
32535
|
.filter(({ action }) => action === "scheduled")
|
|
32026
|
-
.connect((tick) =>
|
|
32536
|
+
.connect((tick) => StorageBacktest.handleScheduled(tick));
|
|
32027
32537
|
const unBacktestCancelled = signalBacktestEmitter
|
|
32028
32538
|
.filter(({ action }) => action === "cancelled")
|
|
32029
|
-
.connect((tick) =>
|
|
32539
|
+
.connect((tick) => StorageBacktest.handleCancelled(tick));
|
|
32030
32540
|
unBacktest = functoolsKit.compose(() => unBacktestOpen(), () => unBacktestClose(), () => unBacktestScheduled(), () => unBacktestCancelled());
|
|
32031
32541
|
}
|
|
32032
32542
|
{
|
|
32033
32543
|
const unLiveOpen = signalLiveEmitter
|
|
32034
32544
|
.filter(({ action }) => action === "opened")
|
|
32035
|
-
.connect((tick) =>
|
|
32545
|
+
.connect((tick) => StorageLive.handleOpened(tick));
|
|
32036
32546
|
const unLiveClose = signalLiveEmitter
|
|
32037
32547
|
.filter(({ action }) => action === "closed")
|
|
32038
|
-
.connect((tick) =>
|
|
32548
|
+
.connect((tick) => StorageLive.handleClosed(tick));
|
|
32039
32549
|
const unLiveScheduled = signalLiveEmitter
|
|
32040
32550
|
.filter(({ action }) => action === "scheduled")
|
|
32041
|
-
.connect((tick) =>
|
|
32551
|
+
.connect((tick) => StorageLive.handleScheduled(tick));
|
|
32042
32552
|
const unLiveCancelled = signalLiveEmitter
|
|
32043
32553
|
.filter(({ action }) => action === "cancelled")
|
|
32044
|
-
.connect((tick) =>
|
|
32554
|
+
.connect((tick) => StorageLive.handleCancelled(tick));
|
|
32045
32555
|
unLive = functoolsKit.compose(() => unLiveOpen(), () => unLiveClose(), () => unLiveScheduled(), () => unLiveCancelled());
|
|
32046
32556
|
}
|
|
32047
32557
|
return () => {
|
|
@@ -32051,7 +32561,8 @@ class StorageAdapter {
|
|
|
32051
32561
|
};
|
|
32052
32562
|
});
|
|
32053
32563
|
/**
|
|
32054
|
-
* Disables signal
|
|
32564
|
+
* Disables signal storage by unsubscribing from all emitters.
|
|
32565
|
+
* Safe to call multiple times.
|
|
32055
32566
|
*/
|
|
32056
32567
|
this.disable = () => {
|
|
32057
32568
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_DISABLE);
|
|
@@ -32061,11 +32572,12 @@ class StorageAdapter {
|
|
|
32061
32572
|
}
|
|
32062
32573
|
};
|
|
32063
32574
|
/**
|
|
32064
|
-
* Finds a signal by ID across both backtest and live
|
|
32575
|
+
* Finds a signal by ID across both backtest and live storage.
|
|
32065
32576
|
*
|
|
32066
|
-
* @param id -
|
|
32067
|
-
* @returns
|
|
32068
|
-
* @throws Error if
|
|
32577
|
+
* @param id - The signal ID to search for
|
|
32578
|
+
* @returns The signal row or throws if not found
|
|
32579
|
+
* @throws Error if StorageAdapter is not enabled
|
|
32580
|
+
* @throws Error if signal is not found in either storage
|
|
32069
32581
|
*/
|
|
32070
32582
|
this.findSignalById = async (id) => {
|
|
32071
32583
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_FIND_SIGNAL_BY_ID, { id });
|
|
@@ -32073,41 +32585,57 @@ class StorageAdapter {
|
|
|
32073
32585
|
throw new Error("StorageAdapter is not enabled. Call enable() first.");
|
|
32074
32586
|
}
|
|
32075
32587
|
let result = null;
|
|
32076
|
-
if ((result = await
|
|
32588
|
+
if ((result = await StorageBacktest.findById(id))) {
|
|
32077
32589
|
return result;
|
|
32078
32590
|
}
|
|
32079
|
-
if ((result = await
|
|
32591
|
+
if ((result = await StorageLive.findById(id))) {
|
|
32080
32592
|
return result;
|
|
32081
32593
|
}
|
|
32082
32594
|
throw new Error(`Storage signal with id ${id} not found`);
|
|
32083
32595
|
};
|
|
32084
32596
|
/**
|
|
32085
|
-
* Lists all backtest
|
|
32597
|
+
* Lists all backtest signals from storage.
|
|
32086
32598
|
*
|
|
32087
|
-
* @returns
|
|
32599
|
+
* @returns Array of all backtest signal rows
|
|
32600
|
+
* @throws Error if StorageAdapter is not enabled
|
|
32088
32601
|
*/
|
|
32089
32602
|
this.listSignalBacktest = async () => {
|
|
32090
32603
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_BACKTEST);
|
|
32091
32604
|
if (!this.enable.hasValue()) {
|
|
32092
32605
|
throw new Error("StorageAdapter is not enabled. Call enable() first.");
|
|
32093
32606
|
}
|
|
32094
|
-
return await
|
|
32607
|
+
return await StorageBacktest.list();
|
|
32095
32608
|
};
|
|
32096
32609
|
/**
|
|
32097
|
-
* Lists all live
|
|
32610
|
+
* Lists all live signals from storage.
|
|
32098
32611
|
*
|
|
32099
|
-
* @returns
|
|
32612
|
+
* @returns Array of all live signal rows
|
|
32613
|
+
* @throws Error if StorageAdapter is not enabled
|
|
32100
32614
|
*/
|
|
32101
32615
|
this.listSignalLive = async () => {
|
|
32102
32616
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_LIVE);
|
|
32103
32617
|
if (!this.enable.hasValue()) {
|
|
32104
32618
|
throw new Error("StorageAdapter is not enabled. Call enable() first.");
|
|
32105
32619
|
}
|
|
32106
|
-
return await
|
|
32620
|
+
return await StorageLive.list();
|
|
32107
32621
|
};
|
|
32108
32622
|
}
|
|
32109
32623
|
}
|
|
32624
|
+
/**
|
|
32625
|
+
* Global singleton instance of StorageAdapter.
|
|
32626
|
+
* Provides unified signal storage management for backtest and live trading.
|
|
32627
|
+
*/
|
|
32110
32628
|
const Storage = new StorageAdapter();
|
|
32629
|
+
/**
|
|
32630
|
+
* Global singleton instance of StorageLiveAdapter.
|
|
32631
|
+
* Provides live trading signal storage with pluggable backends.
|
|
32632
|
+
*/
|
|
32633
|
+
const StorageLive = new StorageLiveAdapter();
|
|
32634
|
+
/**
|
|
32635
|
+
* Global singleton instance of StorageBacktestAdapter.
|
|
32636
|
+
* Provides backtest signal storage with pluggable backends.
|
|
32637
|
+
*/
|
|
32638
|
+
const StorageBacktest = new StorageBacktestAdapter();
|
|
32111
32639
|
|
|
32112
32640
|
const EXCHANGE_METHOD_NAME_GET_CANDLES = "ExchangeUtils.getCandles";
|
|
32113
32641
|
const EXCHANGE_METHOD_NAME_GET_AVERAGE_PRICE = "ExchangeUtils.getAveragePrice";
|
|
@@ -34144,6 +34672,8 @@ exports.ReportBase = ReportBase;
|
|
|
34144
34672
|
exports.Risk = Risk;
|
|
34145
34673
|
exports.Schedule = Schedule;
|
|
34146
34674
|
exports.Storage = Storage;
|
|
34675
|
+
exports.StorageBacktest = StorageBacktest;
|
|
34676
|
+
exports.StorageLive = StorageLive;
|
|
34147
34677
|
exports.Strategy = Strategy;
|
|
34148
34678
|
exports.Walker = Walker;
|
|
34149
34679
|
exports.addActionSchema = addActionSchema;
|