backtest-kit 2.2.17 → 2.2.19
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 +1042 -242
- package/build/index.mjs +1041 -243
- package/package.json +1 -1
- package/types.d.ts +434 -143
package/build/index.mjs
CHANGED
|
@@ -2808,6 +2808,11 @@ const INTERVAL_MINUTES$3 = {
|
|
|
2808
2808
|
"30m": 30,
|
|
2809
2809
|
"1h": 60,
|
|
2810
2810
|
};
|
|
2811
|
+
/**
|
|
2812
|
+
* Mock value for scheduled signal pendingAt timestamp.
|
|
2813
|
+
* Used to indicate that the actual pendingAt will be set upon activation.
|
|
2814
|
+
*/
|
|
2815
|
+
const SCHEDULED_SIGNAL_PENDING_MOCK = 0;
|
|
2811
2816
|
const TIMEOUT_SYMBOL = Symbol('timeout');
|
|
2812
2817
|
/**
|
|
2813
2818
|
* Calls onCommit callback with strategy commit event.
|
|
@@ -2847,73 +2852,123 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, timestamp) => {
|
|
|
2847
2852
|
return;
|
|
2848
2853
|
}
|
|
2849
2854
|
const queue = self._commitQueue;
|
|
2850
|
-
|
|
2855
|
+
{
|
|
2856
|
+
self._commitQueue = [];
|
|
2857
|
+
}
|
|
2858
|
+
if (!self._pendingSignal) {
|
|
2859
|
+
return;
|
|
2860
|
+
}
|
|
2861
|
+
// Get public signal data for commit events (contains effective and original SL/TP)
|
|
2862
|
+
const publicSignal = TO_PUBLIC_SIGNAL(self._pendingSignal);
|
|
2851
2863
|
for (const commit of queue) {
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
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
|
-
|
|
2864
|
+
if (commit.action === "partial-profit") {
|
|
2865
|
+
await CALL_COMMIT_FN(self, {
|
|
2866
|
+
action: "partial-profit",
|
|
2867
|
+
symbol: commit.symbol,
|
|
2868
|
+
strategyName: self.params.strategyName,
|
|
2869
|
+
exchangeName: self.params.exchangeName,
|
|
2870
|
+
frameName: self.params.frameName,
|
|
2871
|
+
backtest: commit.backtest,
|
|
2872
|
+
percentToClose: commit.percentToClose,
|
|
2873
|
+
currentPrice: commit.currentPrice,
|
|
2874
|
+
timestamp,
|
|
2875
|
+
position: publicSignal.position,
|
|
2876
|
+
priceOpen: publicSignal.priceOpen,
|
|
2877
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2878
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2879
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2880
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2881
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2882
|
+
pendingAt: publicSignal.pendingAt,
|
|
2883
|
+
});
|
|
2884
|
+
continue;
|
|
2885
|
+
}
|
|
2886
|
+
if (commit.action === "partial-loss") {
|
|
2887
|
+
await CALL_COMMIT_FN(self, {
|
|
2888
|
+
action: "partial-loss",
|
|
2889
|
+
symbol: commit.symbol,
|
|
2890
|
+
strategyName: self.params.strategyName,
|
|
2891
|
+
exchangeName: self.params.exchangeName,
|
|
2892
|
+
frameName: self.params.frameName,
|
|
2893
|
+
backtest: commit.backtest,
|
|
2894
|
+
percentToClose: commit.percentToClose,
|
|
2895
|
+
currentPrice: commit.currentPrice,
|
|
2896
|
+
timestamp,
|
|
2897
|
+
position: publicSignal.position,
|
|
2898
|
+
priceOpen: publicSignal.priceOpen,
|
|
2899
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2900
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2901
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2902
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2903
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2904
|
+
pendingAt: publicSignal.pendingAt,
|
|
2905
|
+
});
|
|
2906
|
+
continue;
|
|
2907
|
+
}
|
|
2908
|
+
if (commit.action === "breakeven") {
|
|
2909
|
+
await CALL_COMMIT_FN(self, {
|
|
2910
|
+
action: "breakeven",
|
|
2911
|
+
symbol: commit.symbol,
|
|
2912
|
+
strategyName: self.params.strategyName,
|
|
2913
|
+
exchangeName: self.params.exchangeName,
|
|
2914
|
+
frameName: self.params.frameName,
|
|
2915
|
+
backtest: commit.backtest,
|
|
2916
|
+
currentPrice: commit.currentPrice,
|
|
2917
|
+
timestamp,
|
|
2918
|
+
position: publicSignal.position,
|
|
2919
|
+
priceOpen: publicSignal.priceOpen,
|
|
2920
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2921
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2922
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2923
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2924
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2925
|
+
pendingAt: publicSignal.pendingAt,
|
|
2926
|
+
});
|
|
2927
|
+
continue;
|
|
2928
|
+
}
|
|
2929
|
+
if (commit.action === "trailing-stop") {
|
|
2930
|
+
await CALL_COMMIT_FN(self, {
|
|
2931
|
+
action: "trailing-stop",
|
|
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
|
+
position: publicSignal.position,
|
|
2941
|
+
priceOpen: publicSignal.priceOpen,
|
|
2942
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2943
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2944
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2945
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2946
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2947
|
+
pendingAt: publicSignal.pendingAt,
|
|
2948
|
+
});
|
|
2949
|
+
continue;
|
|
2950
|
+
}
|
|
2951
|
+
if (commit.action === "trailing-take") {
|
|
2952
|
+
await CALL_COMMIT_FN(self, {
|
|
2953
|
+
action: "trailing-take",
|
|
2954
|
+
symbol: commit.symbol,
|
|
2955
|
+
strategyName: self.params.strategyName,
|
|
2956
|
+
exchangeName: self.params.exchangeName,
|
|
2957
|
+
frameName: self.params.frameName,
|
|
2958
|
+
backtest: commit.backtest,
|
|
2959
|
+
percentShift: commit.percentShift,
|
|
2960
|
+
currentPrice: commit.currentPrice,
|
|
2961
|
+
timestamp,
|
|
2962
|
+
position: publicSignal.position,
|
|
2963
|
+
priceOpen: publicSignal.priceOpen,
|
|
2964
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2965
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2966
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2967
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2968
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2969
|
+
pendingAt: publicSignal.pendingAt,
|
|
2970
|
+
});
|
|
2971
|
+
continue;
|
|
2917
2972
|
}
|
|
2918
2973
|
}
|
|
2919
2974
|
};
|
|
@@ -3238,7 +3293,7 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
|
|
|
3238
3293
|
if (typeof signal.pendingAt !== "number") {
|
|
3239
3294
|
errors.push(`pendingAt must be a number type, got ${signal.pendingAt} (${typeof signal.pendingAt})`);
|
|
3240
3295
|
}
|
|
3241
|
-
if (signal.pendingAt <= 0) {
|
|
3296
|
+
if (signal.pendingAt <= 0 && !isScheduled) {
|
|
3242
3297
|
errors.push(`pendingAt must be positive, got ${signal.pendingAt}`);
|
|
3243
3298
|
}
|
|
3244
3299
|
}
|
|
@@ -3324,7 +3379,7 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
|
|
|
3324
3379
|
strategyName: self.params.method.context.strategyName,
|
|
3325
3380
|
frameName: self.params.method.context.frameName,
|
|
3326
3381
|
scheduledAt: currentTime,
|
|
3327
|
-
pendingAt:
|
|
3382
|
+
pendingAt: SCHEDULED_SIGNAL_PENDING_MOCK, // Временно, обновится при активации
|
|
3328
3383
|
_isScheduled: true,
|
|
3329
3384
|
};
|
|
3330
3385
|
// Валидируем сигнал перед возвратом
|
|
@@ -13468,6 +13523,8 @@ const backtest_columns = [
|
|
|
13468
13523
|
key: "duration",
|
|
13469
13524
|
label: "Duration (min)",
|
|
13470
13525
|
format: (data) => {
|
|
13526
|
+
if (!data.closeTimestamp || !data.signal.pendingAt)
|
|
13527
|
+
return "N/A";
|
|
13471
13528
|
const durationMs = data.closeTimestamp - data.signal.pendingAt;
|
|
13472
13529
|
const durationMin = Math.round(durationMs / 60000);
|
|
13473
13530
|
return `${durationMin}`;
|
|
@@ -13477,7 +13534,7 @@ const backtest_columns = [
|
|
|
13477
13534
|
{
|
|
13478
13535
|
key: "openTimestamp",
|
|
13479
13536
|
label: "Open Time",
|
|
13480
|
-
format: (data) => new Date(data.signal.pendingAt).toISOString(),
|
|
13537
|
+
format: (data) => data.signal.pendingAt ? new Date(data.signal.pendingAt).toISOString() : "N/A",
|
|
13481
13538
|
isVisible: () => true,
|
|
13482
13539
|
},
|
|
13483
13540
|
{
|
|
@@ -23606,7 +23663,7 @@ class RiskReportService {
|
|
|
23606
23663
|
strategyName: data.strategyName,
|
|
23607
23664
|
exchangeName: data.exchangeName,
|
|
23608
23665
|
frameName: data.frameName,
|
|
23609
|
-
signalId: "",
|
|
23666
|
+
signalId: data.pendingSignal?.id || "",
|
|
23610
23667
|
walkerName: "",
|
|
23611
23668
|
});
|
|
23612
23669
|
};
|
|
@@ -23771,8 +23828,16 @@ class StrategyReportService {
|
|
|
23771
23828
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23772
23829
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23773
23830
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23774
|
-
|
|
23775
|
-
|
|
23831
|
+
* @param position - Trade direction: "long" or "short"
|
|
23832
|
+
* @param priceOpen - Entry price for the position
|
|
23833
|
+
* @param priceTakeProfit - Effective take profit price
|
|
23834
|
+
* @param priceStopLoss - Effective stop loss price
|
|
23835
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
23836
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
23837
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
23838
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
23839
|
+
*/
|
|
23840
|
+
this.partialProfit = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23776
23841
|
this.loggerService.log("strategyReportService partialProfit", {
|
|
23777
23842
|
symbol,
|
|
23778
23843
|
percentToClose,
|
|
@@ -23798,6 +23863,14 @@ class StrategyReportService {
|
|
|
23798
23863
|
symbol,
|
|
23799
23864
|
timestamp,
|
|
23800
23865
|
createdAt,
|
|
23866
|
+
position,
|
|
23867
|
+
priceOpen,
|
|
23868
|
+
priceTakeProfit,
|
|
23869
|
+
priceStopLoss,
|
|
23870
|
+
originalPriceTakeProfit,
|
|
23871
|
+
originalPriceStopLoss,
|
|
23872
|
+
scheduledAt,
|
|
23873
|
+
pendingAt,
|
|
23801
23874
|
}, {
|
|
23802
23875
|
signalId: pendingRow.id,
|
|
23803
23876
|
exchangeName: context.exchangeName,
|
|
@@ -23816,8 +23889,16 @@ class StrategyReportService {
|
|
|
23816
23889
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23817
23890
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23818
23891
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23819
|
-
|
|
23820
|
-
|
|
23892
|
+
* @param position - Trade direction: "long" or "short"
|
|
23893
|
+
* @param priceOpen - Entry price for the position
|
|
23894
|
+
* @param priceTakeProfit - Effective take profit price
|
|
23895
|
+
* @param priceStopLoss - Effective stop loss price
|
|
23896
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
23897
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
23898
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
23899
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
23900
|
+
*/
|
|
23901
|
+
this.partialLoss = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23821
23902
|
this.loggerService.log("strategyReportService partialLoss", {
|
|
23822
23903
|
symbol,
|
|
23823
23904
|
percentToClose,
|
|
@@ -23843,6 +23924,14 @@ class StrategyReportService {
|
|
|
23843
23924
|
symbol,
|
|
23844
23925
|
timestamp,
|
|
23845
23926
|
createdAt,
|
|
23927
|
+
position,
|
|
23928
|
+
priceOpen,
|
|
23929
|
+
priceTakeProfit,
|
|
23930
|
+
priceStopLoss,
|
|
23931
|
+
originalPriceTakeProfit,
|
|
23932
|
+
originalPriceStopLoss,
|
|
23933
|
+
scheduledAt,
|
|
23934
|
+
pendingAt,
|
|
23846
23935
|
}, {
|
|
23847
23936
|
signalId: pendingRow.id,
|
|
23848
23937
|
exchangeName: context.exchangeName,
|
|
@@ -23861,8 +23950,16 @@ class StrategyReportService {
|
|
|
23861
23950
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23862
23951
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23863
23952
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23864
|
-
|
|
23865
|
-
|
|
23953
|
+
* @param position - Trade direction: "long" or "short"
|
|
23954
|
+
* @param priceOpen - Entry price for the position
|
|
23955
|
+
* @param priceTakeProfit - Effective take profit price
|
|
23956
|
+
* @param priceStopLoss - Effective stop loss price
|
|
23957
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
23958
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
23959
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
23960
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
23961
|
+
*/
|
|
23962
|
+
this.trailingStop = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23866
23963
|
this.loggerService.log("strategyReportService trailingStop", {
|
|
23867
23964
|
symbol,
|
|
23868
23965
|
percentShift,
|
|
@@ -23888,6 +23985,14 @@ class StrategyReportService {
|
|
|
23888
23985
|
symbol,
|
|
23889
23986
|
timestamp,
|
|
23890
23987
|
createdAt,
|
|
23988
|
+
position,
|
|
23989
|
+
priceOpen,
|
|
23990
|
+
priceTakeProfit,
|
|
23991
|
+
priceStopLoss,
|
|
23992
|
+
originalPriceTakeProfit,
|
|
23993
|
+
originalPriceStopLoss,
|
|
23994
|
+
scheduledAt,
|
|
23995
|
+
pendingAt,
|
|
23891
23996
|
}, {
|
|
23892
23997
|
signalId: pendingRow.id,
|
|
23893
23998
|
exchangeName: context.exchangeName,
|
|
@@ -23906,8 +24011,16 @@ class StrategyReportService {
|
|
|
23906
24011
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23907
24012
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23908
24013
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23909
|
-
|
|
23910
|
-
|
|
24014
|
+
* @param position - Trade direction: "long" or "short"
|
|
24015
|
+
* @param priceOpen - Entry price for the position
|
|
24016
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24017
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24018
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24019
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24020
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24021
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24022
|
+
*/
|
|
24023
|
+
this.trailingTake = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23911
24024
|
this.loggerService.log("strategyReportService trailingTake", {
|
|
23912
24025
|
symbol,
|
|
23913
24026
|
percentShift,
|
|
@@ -23933,6 +24046,14 @@ class StrategyReportService {
|
|
|
23933
24046
|
symbol,
|
|
23934
24047
|
timestamp,
|
|
23935
24048
|
createdAt,
|
|
24049
|
+
position,
|
|
24050
|
+
priceOpen,
|
|
24051
|
+
priceTakeProfit,
|
|
24052
|
+
priceStopLoss,
|
|
24053
|
+
originalPriceTakeProfit,
|
|
24054
|
+
originalPriceStopLoss,
|
|
24055
|
+
scheduledAt,
|
|
24056
|
+
pendingAt,
|
|
23936
24057
|
}, {
|
|
23937
24058
|
signalId: pendingRow.id,
|
|
23938
24059
|
exchangeName: context.exchangeName,
|
|
@@ -23950,8 +24071,16 @@ class StrategyReportService {
|
|
|
23950
24071
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23951
24072
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23952
24073
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23953
|
-
|
|
23954
|
-
|
|
24074
|
+
* @param position - Trade direction: "long" or "short"
|
|
24075
|
+
* @param priceOpen - Entry price for the position
|
|
24076
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24077
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24078
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24079
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24080
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24081
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24082
|
+
*/
|
|
24083
|
+
this.breakeven = async (symbol, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23955
24084
|
this.loggerService.log("strategyReportService breakeven", {
|
|
23956
24085
|
symbol,
|
|
23957
24086
|
currentPrice,
|
|
@@ -23975,6 +24104,14 @@ class StrategyReportService {
|
|
|
23975
24104
|
symbol,
|
|
23976
24105
|
timestamp,
|
|
23977
24106
|
createdAt,
|
|
24107
|
+
position,
|
|
24108
|
+
priceOpen,
|
|
24109
|
+
priceTakeProfit,
|
|
24110
|
+
priceStopLoss,
|
|
24111
|
+
originalPriceTakeProfit,
|
|
24112
|
+
originalPriceStopLoss,
|
|
24113
|
+
scheduledAt,
|
|
24114
|
+
pendingAt,
|
|
23978
24115
|
}, {
|
|
23979
24116
|
signalId: pendingRow.id,
|
|
23980
24117
|
exchangeName: context.exchangeName,
|
|
@@ -24014,35 +24151,35 @@ class StrategyReportService {
|
|
|
24014
24151
|
exchangeName: event.exchangeName,
|
|
24015
24152
|
frameName: event.frameName,
|
|
24016
24153
|
strategyName: event.strategyName,
|
|
24017
|
-
}, event.timestamp));
|
|
24154
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24018
24155
|
const unPartialLoss = strategyCommitSubject
|
|
24019
24156
|
.filter(({ action }) => action === "partial-loss")
|
|
24020
24157
|
.connect(async (event) => await this.partialLoss(event.symbol, event.percentToClose, event.currentPrice, event.backtest, {
|
|
24021
24158
|
exchangeName: event.exchangeName,
|
|
24022
24159
|
frameName: event.frameName,
|
|
24023
24160
|
strategyName: event.strategyName,
|
|
24024
|
-
}, event.timestamp));
|
|
24161
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24025
24162
|
const unTrailingStop = strategyCommitSubject
|
|
24026
24163
|
.filter(({ action }) => action === "trailing-stop")
|
|
24027
24164
|
.connect(async (event) => await this.trailingStop(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
|
|
24028
24165
|
exchangeName: event.exchangeName,
|
|
24029
24166
|
frameName: event.frameName,
|
|
24030
24167
|
strategyName: event.strategyName,
|
|
24031
|
-
}, event.timestamp));
|
|
24168
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24032
24169
|
const unTrailingTake = strategyCommitSubject
|
|
24033
24170
|
.filter(({ action }) => action === "trailing-take")
|
|
24034
24171
|
.connect(async (event) => await this.trailingTake(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
|
|
24035
24172
|
exchangeName: event.exchangeName,
|
|
24036
24173
|
frameName: event.frameName,
|
|
24037
24174
|
strategyName: event.strategyName,
|
|
24038
|
-
}, event.timestamp));
|
|
24175
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24039
24176
|
const unBreakeven = strategyCommitSubject
|
|
24040
24177
|
.filter(({ action }) => action === "breakeven")
|
|
24041
24178
|
.connect(async (event) => await this.breakeven(event.symbol, event.currentPrice, event.backtest, {
|
|
24042
24179
|
exchangeName: event.exchangeName,
|
|
24043
24180
|
frameName: event.frameName,
|
|
24044
24181
|
strategyName: event.strategyName,
|
|
24045
|
-
}, event.timestamp));
|
|
24182
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24046
24183
|
const disposeFn = compose(() => unCancelSchedule(), () => unClosePending(), () => unPartialProfit(), () => unPartialLoss(), () => unTrailingStop(), () => unTrailingTake(), () => unBreakeven());
|
|
24047
24184
|
return () => {
|
|
24048
24185
|
disposeFn();
|
|
@@ -24412,8 +24549,16 @@ class StrategyMarkdownService {
|
|
|
24412
24549
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24413
24550
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24414
24551
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24415
|
-
|
|
24416
|
-
|
|
24552
|
+
* @param position - Trade direction: "long" or "short"
|
|
24553
|
+
* @param priceOpen - Entry price for the position
|
|
24554
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24555
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24556
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24557
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24558
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24559
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24560
|
+
*/
|
|
24561
|
+
this.partialProfit = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24417
24562
|
this.loggerService.log("strategyMarkdownService partialProfit", {
|
|
24418
24563
|
symbol,
|
|
24419
24564
|
percentToClose,
|
|
@@ -24445,6 +24590,14 @@ class StrategyMarkdownService {
|
|
|
24445
24590
|
currentPrice,
|
|
24446
24591
|
createdAt,
|
|
24447
24592
|
backtest: isBacktest,
|
|
24593
|
+
position,
|
|
24594
|
+
priceOpen,
|
|
24595
|
+
priceTakeProfit,
|
|
24596
|
+
priceStopLoss,
|
|
24597
|
+
originalPriceTakeProfit,
|
|
24598
|
+
originalPriceStopLoss,
|
|
24599
|
+
scheduledAt,
|
|
24600
|
+
pendingAt,
|
|
24448
24601
|
});
|
|
24449
24602
|
};
|
|
24450
24603
|
/**
|
|
@@ -24456,8 +24609,16 @@ class StrategyMarkdownService {
|
|
|
24456
24609
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24457
24610
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24458
24611
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24459
|
-
|
|
24460
|
-
|
|
24612
|
+
* @param position - Trade direction: "long" or "short"
|
|
24613
|
+
* @param priceOpen - Entry price for the position
|
|
24614
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24615
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24616
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24617
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24618
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24619
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24620
|
+
*/
|
|
24621
|
+
this.partialLoss = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24461
24622
|
this.loggerService.log("strategyMarkdownService partialLoss", {
|
|
24462
24623
|
symbol,
|
|
24463
24624
|
percentToClose,
|
|
@@ -24489,6 +24650,14 @@ class StrategyMarkdownService {
|
|
|
24489
24650
|
currentPrice,
|
|
24490
24651
|
createdAt,
|
|
24491
24652
|
backtest: isBacktest,
|
|
24653
|
+
position,
|
|
24654
|
+
priceOpen,
|
|
24655
|
+
priceTakeProfit,
|
|
24656
|
+
priceStopLoss,
|
|
24657
|
+
originalPriceTakeProfit,
|
|
24658
|
+
originalPriceStopLoss,
|
|
24659
|
+
scheduledAt,
|
|
24660
|
+
pendingAt,
|
|
24492
24661
|
});
|
|
24493
24662
|
};
|
|
24494
24663
|
/**
|
|
@@ -24500,8 +24669,16 @@ class StrategyMarkdownService {
|
|
|
24500
24669
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24501
24670
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24502
24671
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24503
|
-
|
|
24504
|
-
|
|
24672
|
+
* @param position - Trade direction: "long" or "short"
|
|
24673
|
+
* @param priceOpen - Entry price for the position
|
|
24674
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24675
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24676
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24677
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24678
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24679
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24680
|
+
*/
|
|
24681
|
+
this.trailingStop = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24505
24682
|
this.loggerService.log("strategyMarkdownService trailingStop", {
|
|
24506
24683
|
symbol,
|
|
24507
24684
|
percentShift,
|
|
@@ -24533,6 +24710,14 @@ class StrategyMarkdownService {
|
|
|
24533
24710
|
currentPrice,
|
|
24534
24711
|
createdAt,
|
|
24535
24712
|
backtest: isBacktest,
|
|
24713
|
+
position,
|
|
24714
|
+
priceOpen,
|
|
24715
|
+
priceTakeProfit,
|
|
24716
|
+
priceStopLoss,
|
|
24717
|
+
originalPriceTakeProfit,
|
|
24718
|
+
originalPriceStopLoss,
|
|
24719
|
+
scheduledAt,
|
|
24720
|
+
pendingAt,
|
|
24536
24721
|
});
|
|
24537
24722
|
};
|
|
24538
24723
|
/**
|
|
@@ -24544,8 +24729,16 @@ class StrategyMarkdownService {
|
|
|
24544
24729
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24545
24730
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24546
24731
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24547
|
-
|
|
24548
|
-
|
|
24732
|
+
* @param position - Trade direction: "long" or "short"
|
|
24733
|
+
* @param priceOpen - Entry price for the position
|
|
24734
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24735
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24736
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24737
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24738
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24739
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24740
|
+
*/
|
|
24741
|
+
this.trailingTake = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24549
24742
|
this.loggerService.log("strategyMarkdownService trailingTake", {
|
|
24550
24743
|
symbol,
|
|
24551
24744
|
percentShift,
|
|
@@ -24577,6 +24770,14 @@ class StrategyMarkdownService {
|
|
|
24577
24770
|
currentPrice,
|
|
24578
24771
|
createdAt,
|
|
24579
24772
|
backtest: isBacktest,
|
|
24773
|
+
position,
|
|
24774
|
+
priceOpen,
|
|
24775
|
+
priceTakeProfit,
|
|
24776
|
+
priceStopLoss,
|
|
24777
|
+
originalPriceTakeProfit,
|
|
24778
|
+
originalPriceStopLoss,
|
|
24779
|
+
scheduledAt,
|
|
24780
|
+
pendingAt,
|
|
24580
24781
|
});
|
|
24581
24782
|
};
|
|
24582
24783
|
/**
|
|
@@ -24587,8 +24788,16 @@ class StrategyMarkdownService {
|
|
|
24587
24788
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24588
24789
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24589
24790
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24590
|
-
|
|
24591
|
-
|
|
24791
|
+
* @param position - Trade direction: "long" or "short"
|
|
24792
|
+
* @param priceOpen - Entry price for the position
|
|
24793
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24794
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24795
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24796
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24797
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24798
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24799
|
+
*/
|
|
24800
|
+
this.breakeven = async (symbol, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24592
24801
|
this.loggerService.log("strategyMarkdownService breakeven", {
|
|
24593
24802
|
symbol,
|
|
24594
24803
|
currentPrice,
|
|
@@ -24618,6 +24827,14 @@ class StrategyMarkdownService {
|
|
|
24618
24827
|
currentPrice,
|
|
24619
24828
|
createdAt,
|
|
24620
24829
|
backtest: isBacktest,
|
|
24830
|
+
position,
|
|
24831
|
+
priceOpen,
|
|
24832
|
+
priceTakeProfit,
|
|
24833
|
+
priceStopLoss,
|
|
24834
|
+
originalPriceTakeProfit,
|
|
24835
|
+
originalPriceStopLoss,
|
|
24836
|
+
scheduledAt,
|
|
24837
|
+
pendingAt,
|
|
24621
24838
|
});
|
|
24622
24839
|
};
|
|
24623
24840
|
/**
|
|
@@ -24764,35 +24981,35 @@ class StrategyMarkdownService {
|
|
|
24764
24981
|
exchangeName: event.exchangeName,
|
|
24765
24982
|
frameName: event.frameName,
|
|
24766
24983
|
strategyName: event.strategyName,
|
|
24767
|
-
}, event.timestamp));
|
|
24984
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24768
24985
|
const unPartialLoss = strategyCommitSubject
|
|
24769
24986
|
.filter(({ action }) => action === "partial-loss")
|
|
24770
24987
|
.connect(async (event) => await this.partialLoss(event.symbol, event.percentToClose, event.currentPrice, event.backtest, {
|
|
24771
24988
|
exchangeName: event.exchangeName,
|
|
24772
24989
|
frameName: event.frameName,
|
|
24773
24990
|
strategyName: event.strategyName,
|
|
24774
|
-
}, event.timestamp));
|
|
24991
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24775
24992
|
const unTrailingStop = strategyCommitSubject
|
|
24776
24993
|
.filter(({ action }) => action === "trailing-stop")
|
|
24777
24994
|
.connect(async (event) => await this.trailingStop(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
|
|
24778
24995
|
exchangeName: event.exchangeName,
|
|
24779
24996
|
frameName: event.frameName,
|
|
24780
24997
|
strategyName: event.strategyName,
|
|
24781
|
-
}, event.timestamp));
|
|
24998
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24782
24999
|
const unTrailingTake = strategyCommitSubject
|
|
24783
25000
|
.filter(({ action }) => action === "trailing-take")
|
|
24784
25001
|
.connect(async (event) => await this.trailingTake(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
|
|
24785
25002
|
exchangeName: event.exchangeName,
|
|
24786
25003
|
frameName: event.frameName,
|
|
24787
25004
|
strategyName: event.strategyName,
|
|
24788
|
-
}, event.timestamp));
|
|
25005
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24789
25006
|
const unBreakeven = strategyCommitSubject
|
|
24790
25007
|
.filter(({ action }) => action === "breakeven")
|
|
24791
25008
|
.connect(async (event) => await this.breakeven(event.symbol, event.currentPrice, event.backtest, {
|
|
24792
25009
|
exchangeName: event.exchangeName,
|
|
24793
25010
|
frameName: event.frameName,
|
|
24794
25011
|
strategyName: event.strategyName,
|
|
24795
|
-
}, event.timestamp));
|
|
25012
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24796
25013
|
const disposeFn = compose(() => unCancelSchedule(), () => unClosePending(), () => unPartialProfit(), () => unPartialLoss(), () => unTrailingStop(), () => unTrailingTake(), () => unBreakeven());
|
|
24797
25014
|
return () => {
|
|
24798
25015
|
disposeFn();
|
|
@@ -31597,53 +31814,64 @@ class ConstantUtils {
|
|
|
31597
31814
|
const Constant = new ConstantUtils();
|
|
31598
31815
|
|
|
31599
31816
|
const MAX_SIGNALS = 25;
|
|
31600
|
-
const STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "
|
|
31601
|
-
const STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE = "
|
|
31602
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED = "
|
|
31603
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CLOSED = "
|
|
31604
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED = "
|
|
31605
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CANCELLED = "
|
|
31606
|
-
const STORAGE_BACKTEST_METHOD_NAME_FIND_BY_ID = "
|
|
31607
|
-
const STORAGE_BACKTEST_METHOD_NAME_LIST = "
|
|
31608
|
-
const STORAGE_LIVE_METHOD_NAME_WAIT_FOR_INIT = "
|
|
31609
|
-
const STORAGE_LIVE_METHOD_NAME_UPDATE_STORAGE = "
|
|
31610
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_OPENED = "
|
|
31611
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_CLOSED = "
|
|
31612
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_SCHEDULED = "
|
|
31613
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_CANCELLED = "
|
|
31614
|
-
const STORAGE_LIVE_METHOD_NAME_FIND_BY_ID = "
|
|
31615
|
-
const STORAGE_LIVE_METHOD_NAME_LIST = "
|
|
31817
|
+
const STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "StoragePersistBacktestUtils.waitForInit";
|
|
31818
|
+
const STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE = "StoragePersistBacktestUtils._updateStorage";
|
|
31819
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED = "StoragePersistBacktestUtils.handleOpened";
|
|
31820
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CLOSED = "StoragePersistBacktestUtils.handleClosed";
|
|
31821
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED = "StoragePersistBacktestUtils.handleScheduled";
|
|
31822
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CANCELLED = "StoragePersistBacktestUtils.handleCancelled";
|
|
31823
|
+
const STORAGE_BACKTEST_METHOD_NAME_FIND_BY_ID = "StoragePersistBacktestUtils.findById";
|
|
31824
|
+
const STORAGE_BACKTEST_METHOD_NAME_LIST = "StoragePersistBacktestUtils.list";
|
|
31825
|
+
const STORAGE_LIVE_METHOD_NAME_WAIT_FOR_INIT = "StoragePersistLiveUtils.waitForInit";
|
|
31826
|
+
const STORAGE_LIVE_METHOD_NAME_UPDATE_STORAGE = "StoragePersistLiveUtils._updateStorage";
|
|
31827
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_OPENED = "StoragePersistLiveUtils.handleOpened";
|
|
31828
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_CLOSED = "StoragePersistLiveUtils.handleClosed";
|
|
31829
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_SCHEDULED = "StoragePersistLiveUtils.handleScheduled";
|
|
31830
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_CANCELLED = "StoragePersistLiveUtils.handleCancelled";
|
|
31831
|
+
const STORAGE_LIVE_METHOD_NAME_FIND_BY_ID = "StoragePersistLiveUtils.findById";
|
|
31832
|
+
const STORAGE_LIVE_METHOD_NAME_LIST = "StoragePersistLiveUtils.list";
|
|
31833
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_OPENED = "StorageMemoryBacktestUtils.handleOpened";
|
|
31834
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CLOSED = "StorageMemoryBacktestUtils.handleClosed";
|
|
31835
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED = "StorageMemoryBacktestUtils.handleScheduled";
|
|
31836
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CANCELLED = "StorageMemoryBacktestUtils.handleCancelled";
|
|
31837
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_FIND_BY_ID = "StorageMemoryBacktestUtils.findById";
|
|
31838
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_LIST = "StorageMemoryBacktestUtils.list";
|
|
31839
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_OPENED = "StorageMemoryLiveUtils.handleOpened";
|
|
31840
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CLOSED = "StorageMemoryLiveUtils.handleClosed";
|
|
31841
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_SCHEDULED = "StorageMemoryLiveUtils.handleScheduled";
|
|
31842
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CANCELLED = "StorageMemoryLiveUtils.handleCancelled";
|
|
31843
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_FIND_BY_ID = "StorageMemoryLiveUtils.findById";
|
|
31844
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_LIST = "StorageMemoryLiveUtils.list";
|
|
31616
31845
|
const STORAGE_ADAPTER_METHOD_NAME_ENABLE = "StorageAdapter.enable";
|
|
31617
31846
|
const STORAGE_ADAPTER_METHOD_NAME_DISABLE = "StorageAdapter.disable";
|
|
31618
31847
|
const STORAGE_ADAPTER_METHOD_NAME_FIND_SIGNAL_BY_ID = "StorageAdapter.findSignalById";
|
|
31619
31848
|
const STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_BACKTEST = "StorageAdapter.listSignalBacktest";
|
|
31620
31849
|
const STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_LIVE = "StorageAdapter.listSignalLive";
|
|
31850
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER = "StorageBacktestAdapter.useStorageAdapter";
|
|
31851
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY = "StorageBacktestAdapter.useDummy";
|
|
31852
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST = "StorageBacktestAdapter.usePersist";
|
|
31853
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY = "StorageBacktestAdapter.useMemory";
|
|
31854
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER = "StorageLiveAdapter.useStorageAdapter";
|
|
31855
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY = "StorageLiveAdapter.useDummy";
|
|
31856
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST = "StorageLiveAdapter.usePersist";
|
|
31857
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY = "StorageLiveAdapter.useMemory";
|
|
31621
31858
|
/**
|
|
31622
|
-
*
|
|
31623
|
-
*
|
|
31624
|
-
* Stores trading signal history for admin dashboard display during backtesting
|
|
31625
|
-
* with automatic initialization, deduplication, and storage limits.
|
|
31626
|
-
*
|
|
31627
|
-
* @example
|
|
31628
|
-
* ```typescript
|
|
31629
|
-
* import { StorageBacktestUtils } from "./classes/Storage";
|
|
31859
|
+
* Persistent storage adapter for backtest signals.
|
|
31630
31860
|
*
|
|
31631
|
-
*
|
|
31632
|
-
*
|
|
31633
|
-
*
|
|
31634
|
-
*
|
|
31635
|
-
*
|
|
31861
|
+
* Features:
|
|
31862
|
+
* - Persists signals to disk using PersistStorageAdapter
|
|
31863
|
+
* - Lazy initialization with singleshot pattern
|
|
31864
|
+
* - Maintains up to MAX_SIGNALS (25) most recent signals
|
|
31865
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
31866
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31636
31867
|
*
|
|
31637
|
-
*
|
|
31638
|
-
* const signal = await storage.findById("signal-123");
|
|
31639
|
-
* const allSignals = await storage.list();
|
|
31640
|
-
* ```
|
|
31868
|
+
* Use this adapter (default) for backtest signal persistence across sessions.
|
|
31641
31869
|
*/
|
|
31642
|
-
class
|
|
31870
|
+
class StoragePersistBacktestUtils {
|
|
31643
31871
|
constructor() {
|
|
31644
31872
|
/**
|
|
31645
|
-
*
|
|
31646
|
-
*
|
|
31873
|
+
* Singleshot initialization function that loads signals from disk.
|
|
31874
|
+
* Protected by singleshot to ensure one-time execution.
|
|
31647
31875
|
*/
|
|
31648
31876
|
this.waitForInit = singleshot(async () => {
|
|
31649
31877
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT);
|
|
@@ -31655,9 +31883,8 @@ class StorageBacktestUtils {
|
|
|
31655
31883
|
});
|
|
31656
31884
|
/**
|
|
31657
31885
|
* Handles signal opened event.
|
|
31658
|
-
*
|
|
31659
|
-
* @param tick -
|
|
31660
|
-
* @returns Promise resolving when storage is updated
|
|
31886
|
+
* Updates storage with opened status if not stale.
|
|
31887
|
+
* @param tick - The opened signal tick data
|
|
31661
31888
|
*/
|
|
31662
31889
|
this.handleOpened = async (tick) => {
|
|
31663
31890
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED, {
|
|
@@ -31679,9 +31906,8 @@ class StorageBacktestUtils {
|
|
|
31679
31906
|
};
|
|
31680
31907
|
/**
|
|
31681
31908
|
* Handles signal closed event.
|
|
31682
|
-
*
|
|
31683
|
-
* @param tick -
|
|
31684
|
-
* @returns Promise resolving when storage is updated
|
|
31909
|
+
* Updates storage with closed status and PnL if not stale.
|
|
31910
|
+
* @param tick - The closed signal tick data
|
|
31685
31911
|
*/
|
|
31686
31912
|
this.handleClosed = async (tick) => {
|
|
31687
31913
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_CLOSED, {
|
|
@@ -31704,9 +31930,8 @@ class StorageBacktestUtils {
|
|
|
31704
31930
|
};
|
|
31705
31931
|
/**
|
|
31706
31932
|
* Handles signal scheduled event.
|
|
31707
|
-
*
|
|
31708
|
-
* @param tick -
|
|
31709
|
-
* @returns Promise resolving when storage is updated
|
|
31933
|
+
* Updates storage with scheduled status if not stale.
|
|
31934
|
+
* @param tick - The scheduled signal tick data
|
|
31710
31935
|
*/
|
|
31711
31936
|
this.handleScheduled = async (tick) => {
|
|
31712
31937
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
@@ -31728,9 +31953,8 @@ class StorageBacktestUtils {
|
|
|
31728
31953
|
};
|
|
31729
31954
|
/**
|
|
31730
31955
|
* Handles signal cancelled event.
|
|
31731
|
-
*
|
|
31732
|
-
* @param tick -
|
|
31733
|
-
* @returns Promise resolving when storage is updated
|
|
31956
|
+
* Updates storage with cancelled status if not stale.
|
|
31957
|
+
* @param tick - The cancelled signal tick data
|
|
31734
31958
|
*/
|
|
31735
31959
|
this.handleCancelled = async (tick) => {
|
|
31736
31960
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_CANCELLED, {
|
|
@@ -31751,10 +31975,9 @@ class StorageBacktestUtils {
|
|
|
31751
31975
|
await this._updateStorage();
|
|
31752
31976
|
};
|
|
31753
31977
|
/**
|
|
31754
|
-
* Finds a signal by its
|
|
31755
|
-
*
|
|
31756
|
-
* @
|
|
31757
|
-
* @returns Promise resolving to signal row or null if not found
|
|
31978
|
+
* Finds a signal by its ID.
|
|
31979
|
+
* @param id - The signal ID to search for
|
|
31980
|
+
* @returns The signal row or null if not found
|
|
31758
31981
|
*/
|
|
31759
31982
|
this.findById = async (id) => {
|
|
31760
31983
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_FIND_BY_ID, { id });
|
|
@@ -31762,9 +31985,8 @@ class StorageBacktestUtils {
|
|
|
31762
31985
|
return this._signals.get(id) ?? null;
|
|
31763
31986
|
};
|
|
31764
31987
|
/**
|
|
31765
|
-
* Lists all stored
|
|
31766
|
-
*
|
|
31767
|
-
* @returns Promise resolving to array of signal rows
|
|
31988
|
+
* Lists all stored signals.
|
|
31989
|
+
* @returns Array of all signal rows
|
|
31768
31990
|
*/
|
|
31769
31991
|
this.list = async () => {
|
|
31770
31992
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_LIST);
|
|
@@ -31773,15 +31995,14 @@ class StorageBacktestUtils {
|
|
|
31773
31995
|
};
|
|
31774
31996
|
}
|
|
31775
31997
|
/**
|
|
31776
|
-
* Persists current signal
|
|
31777
|
-
* Sorts by priority and
|
|
31778
|
-
*
|
|
31779
|
-
* @throws Error if storage not initialized
|
|
31998
|
+
* Persists the current signal map to disk storage.
|
|
31999
|
+
* Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
|
|
32000
|
+
* @throws Error if not initialized
|
|
31780
32001
|
*/
|
|
31781
32002
|
async _updateStorage() {
|
|
31782
32003
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE);
|
|
31783
32004
|
if (!this._signals) {
|
|
31784
|
-
throw new Error("
|
|
32005
|
+
throw new Error("StoragePersistBacktestUtils not initialized. Call waitForInit first.");
|
|
31785
32006
|
}
|
|
31786
32007
|
const signalList = Array.from(this._signals.values());
|
|
31787
32008
|
signalList.sort((a, b) => a.priority - b.priority);
|
|
@@ -31789,31 +32010,190 @@ class StorageBacktestUtils {
|
|
|
31789
32010
|
}
|
|
31790
32011
|
}
|
|
31791
32012
|
/**
|
|
31792
|
-
*
|
|
32013
|
+
* In-memory storage adapter for backtest signals.
|
|
31793
32014
|
*
|
|
31794
|
-
*
|
|
31795
|
-
*
|
|
32015
|
+
* Features:
|
|
32016
|
+
* - Stores signals in memory only (no persistence)
|
|
32017
|
+
* - Fast read/write operations
|
|
32018
|
+
* - Data is lost when application restarts
|
|
32019
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
32020
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31796
32021
|
*
|
|
31797
|
-
*
|
|
31798
|
-
|
|
31799
|
-
|
|
32022
|
+
* Use this adapter for testing or when persistence is not required.
|
|
32023
|
+
*/
|
|
32024
|
+
class StorageMemoryBacktestUtils {
|
|
32025
|
+
constructor() {
|
|
32026
|
+
/** Map of signal IDs to signal rows */
|
|
32027
|
+
this._signals = new Map();
|
|
32028
|
+
/**
|
|
32029
|
+
* Handles signal opened event.
|
|
32030
|
+
* Updates in-memory storage with opened status if not stale.
|
|
32031
|
+
* @param tick - The opened signal tick data
|
|
32032
|
+
*/
|
|
32033
|
+
this.handleOpened = async (tick) => {
|
|
32034
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_OPENED, {
|
|
32035
|
+
signalId: tick.signal.id,
|
|
32036
|
+
});
|
|
32037
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32038
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32039
|
+
return;
|
|
32040
|
+
}
|
|
32041
|
+
this._signals.set(tick.signal.id, {
|
|
32042
|
+
...tick.signal,
|
|
32043
|
+
status: "opened",
|
|
32044
|
+
priority: Date.now(),
|
|
32045
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32046
|
+
updatedAt: tick.createdAt,
|
|
32047
|
+
});
|
|
32048
|
+
};
|
|
32049
|
+
/**
|
|
32050
|
+
* Handles signal closed event.
|
|
32051
|
+
* Updates in-memory storage with closed status and PnL if not stale.
|
|
32052
|
+
* @param tick - The closed signal tick data
|
|
32053
|
+
*/
|
|
32054
|
+
this.handleClosed = async (tick) => {
|
|
32055
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CLOSED, {
|
|
32056
|
+
signalId: tick.signal.id,
|
|
32057
|
+
});
|
|
32058
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32059
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32060
|
+
return;
|
|
32061
|
+
}
|
|
32062
|
+
this._signals.set(tick.signal.id, {
|
|
32063
|
+
...tick.signal,
|
|
32064
|
+
status: "closed",
|
|
32065
|
+
priority: Date.now(),
|
|
32066
|
+
pnl: tick.pnl,
|
|
32067
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32068
|
+
updatedAt: tick.createdAt,
|
|
32069
|
+
});
|
|
32070
|
+
};
|
|
32071
|
+
/**
|
|
32072
|
+
* Handles signal scheduled event.
|
|
32073
|
+
* Updates in-memory storage with scheduled status if not stale.
|
|
32074
|
+
* @param tick - The scheduled signal tick data
|
|
32075
|
+
*/
|
|
32076
|
+
this.handleScheduled = async (tick) => {
|
|
32077
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
32078
|
+
signalId: tick.signal.id,
|
|
32079
|
+
});
|
|
32080
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32081
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32082
|
+
return;
|
|
32083
|
+
}
|
|
32084
|
+
this._signals.set(tick.signal.id, {
|
|
32085
|
+
...tick.signal,
|
|
32086
|
+
status: "scheduled",
|
|
32087
|
+
priority: Date.now(),
|
|
32088
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32089
|
+
updatedAt: tick.createdAt,
|
|
32090
|
+
});
|
|
32091
|
+
};
|
|
32092
|
+
/**
|
|
32093
|
+
* Handles signal cancelled event.
|
|
32094
|
+
* Updates in-memory storage with cancelled status if not stale.
|
|
32095
|
+
* @param tick - The cancelled signal tick data
|
|
32096
|
+
*/
|
|
32097
|
+
this.handleCancelled = async (tick) => {
|
|
32098
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CANCELLED, {
|
|
32099
|
+
signalId: tick.signal.id,
|
|
32100
|
+
});
|
|
32101
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32102
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32103
|
+
return;
|
|
32104
|
+
}
|
|
32105
|
+
this._signals.set(tick.signal.id, {
|
|
32106
|
+
...tick.signal,
|
|
32107
|
+
status: "cancelled",
|
|
32108
|
+
priority: Date.now(),
|
|
32109
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32110
|
+
updatedAt: tick.createdAt,
|
|
32111
|
+
});
|
|
32112
|
+
};
|
|
32113
|
+
/**
|
|
32114
|
+
* Finds a signal by its ID.
|
|
32115
|
+
* @param id - The signal ID to search for
|
|
32116
|
+
* @returns The signal row or null if not found
|
|
32117
|
+
*/
|
|
32118
|
+
this.findById = async (id) => {
|
|
32119
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_FIND_BY_ID, { id });
|
|
32120
|
+
return this._signals.get(id) ?? null;
|
|
32121
|
+
};
|
|
32122
|
+
/**
|
|
32123
|
+
* Lists all stored signals.
|
|
32124
|
+
* @returns Array of all signal rows
|
|
32125
|
+
*/
|
|
32126
|
+
this.list = async () => {
|
|
32127
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_LIST);
|
|
32128
|
+
return Array.from(this._signals.values());
|
|
32129
|
+
};
|
|
32130
|
+
}
|
|
32131
|
+
}
|
|
32132
|
+
/**
|
|
32133
|
+
* Dummy storage adapter for backtest signals that discards all writes.
|
|
32134
|
+
*
|
|
32135
|
+
* Features:
|
|
32136
|
+
* - No-op implementation for all methods
|
|
32137
|
+
* - findById always returns null
|
|
32138
|
+
* - list always returns empty array
|
|
31800
32139
|
*
|
|
31801
|
-
*
|
|
32140
|
+
* Use this adapter to disable backtest signal storage completely.
|
|
32141
|
+
*/
|
|
32142
|
+
class StorageDummyBacktestUtils {
|
|
32143
|
+
constructor() {
|
|
32144
|
+
/**
|
|
32145
|
+
* No-op handler for signal opened event.
|
|
32146
|
+
*/
|
|
32147
|
+
this.handleOpened = async () => {
|
|
32148
|
+
};
|
|
32149
|
+
/**
|
|
32150
|
+
* No-op handler for signal closed event.
|
|
32151
|
+
*/
|
|
32152
|
+
this.handleClosed = async () => {
|
|
32153
|
+
};
|
|
32154
|
+
/**
|
|
32155
|
+
* No-op handler for signal scheduled event.
|
|
32156
|
+
*/
|
|
32157
|
+
this.handleScheduled = async () => {
|
|
32158
|
+
};
|
|
32159
|
+
/**
|
|
32160
|
+
* No-op handler for signal cancelled event.
|
|
32161
|
+
*/
|
|
32162
|
+
this.handleCancelled = async () => {
|
|
32163
|
+
};
|
|
32164
|
+
/**
|
|
32165
|
+
* Always returns null (no storage).
|
|
32166
|
+
* @returns null
|
|
32167
|
+
*/
|
|
32168
|
+
this.findById = async () => {
|
|
32169
|
+
return null;
|
|
32170
|
+
};
|
|
32171
|
+
/**
|
|
32172
|
+
* Always returns empty array (no storage).
|
|
32173
|
+
* @returns Empty array
|
|
32174
|
+
*/
|
|
32175
|
+
this.list = async () => {
|
|
32176
|
+
return [];
|
|
32177
|
+
};
|
|
32178
|
+
}
|
|
32179
|
+
}
|
|
32180
|
+
/**
|
|
32181
|
+
* Persistent storage adapter for live trading signals.
|
|
31802
32182
|
*
|
|
31803
|
-
*
|
|
31804
|
-
*
|
|
31805
|
-
*
|
|
32183
|
+
* Features:
|
|
32184
|
+
* - Persists signals to disk using PersistStorageAdapter
|
|
32185
|
+
* - Lazy initialization with singleshot pattern
|
|
32186
|
+
* - Maintains up to MAX_SIGNALS (25) most recent signals
|
|
32187
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
32188
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31806
32189
|
*
|
|
31807
|
-
*
|
|
31808
|
-
* const signal = await storage.findById("signal-123");
|
|
31809
|
-
* const allSignals = await storage.list();
|
|
31810
|
-
* ```
|
|
32190
|
+
* Use this adapter (default) for live signal persistence across sessions.
|
|
31811
32191
|
*/
|
|
31812
|
-
class
|
|
32192
|
+
class StoragePersistLiveUtils {
|
|
31813
32193
|
constructor() {
|
|
31814
32194
|
/**
|
|
31815
|
-
*
|
|
31816
|
-
*
|
|
32195
|
+
* Singleshot initialization function that loads signals from disk.
|
|
32196
|
+
* Protected by singleshot to ensure one-time execution.
|
|
31817
32197
|
*/
|
|
31818
32198
|
this.waitForInit = singleshot(async () => {
|
|
31819
32199
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_WAIT_FOR_INIT);
|
|
@@ -31825,9 +32205,8 @@ class StorageLiveUtils {
|
|
|
31825
32205
|
});
|
|
31826
32206
|
/**
|
|
31827
32207
|
* Handles signal opened event.
|
|
31828
|
-
*
|
|
31829
|
-
* @param tick -
|
|
31830
|
-
* @returns Promise resolving when history is updated
|
|
32208
|
+
* Updates storage with opened status if not stale.
|
|
32209
|
+
* @param tick - The opened signal tick data
|
|
31831
32210
|
*/
|
|
31832
32211
|
this.handleOpened = async (tick) => {
|
|
31833
32212
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_OPENED, {
|
|
@@ -31849,9 +32228,8 @@ class StorageLiveUtils {
|
|
|
31849
32228
|
};
|
|
31850
32229
|
/**
|
|
31851
32230
|
* Handles signal closed event.
|
|
31852
|
-
*
|
|
31853
|
-
* @param tick -
|
|
31854
|
-
* @returns Promise resolving when history is updated
|
|
32231
|
+
* Updates storage with closed status and PnL if not stale.
|
|
32232
|
+
* @param tick - The closed signal tick data
|
|
31855
32233
|
*/
|
|
31856
32234
|
this.handleClosed = async (tick) => {
|
|
31857
32235
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_CLOSED, {
|
|
@@ -31874,9 +32252,8 @@ class StorageLiveUtils {
|
|
|
31874
32252
|
};
|
|
31875
32253
|
/**
|
|
31876
32254
|
* Handles signal scheduled event.
|
|
31877
|
-
*
|
|
31878
|
-
* @param tick -
|
|
31879
|
-
* @returns Promise resolving when history is updated
|
|
32255
|
+
* Updates storage with scheduled status if not stale.
|
|
32256
|
+
* @param tick - The scheduled signal tick data
|
|
31880
32257
|
*/
|
|
31881
32258
|
this.handleScheduled = async (tick) => {
|
|
31882
32259
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
@@ -31898,9 +32275,8 @@ class StorageLiveUtils {
|
|
|
31898
32275
|
};
|
|
31899
32276
|
/**
|
|
31900
32277
|
* Handles signal cancelled event.
|
|
31901
|
-
*
|
|
31902
|
-
* @param tick -
|
|
31903
|
-
* @returns Promise resolving when history is updated
|
|
32278
|
+
* Updates storage with cancelled status if not stale.
|
|
32279
|
+
* @param tick - The cancelled signal tick data
|
|
31904
32280
|
*/
|
|
31905
32281
|
this.handleCancelled = async (tick) => {
|
|
31906
32282
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_CANCELLED, {
|
|
@@ -31921,10 +32297,9 @@ class StorageLiveUtils {
|
|
|
31921
32297
|
await this._updateStorage();
|
|
31922
32298
|
};
|
|
31923
32299
|
/**
|
|
31924
|
-
* Finds a signal by its
|
|
31925
|
-
*
|
|
31926
|
-
* @
|
|
31927
|
-
* @returns Promise resolving to signal row or null if not found
|
|
32300
|
+
* Finds a signal by its ID.
|
|
32301
|
+
* @param id - The signal ID to search for
|
|
32302
|
+
* @returns The signal row or null if not found
|
|
31928
32303
|
*/
|
|
31929
32304
|
this.findById = async (id) => {
|
|
31930
32305
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_FIND_BY_ID, { id });
|
|
@@ -31932,9 +32307,8 @@ class StorageLiveUtils {
|
|
|
31932
32307
|
return this._signals.get(id) ?? null;
|
|
31933
32308
|
};
|
|
31934
32309
|
/**
|
|
31935
|
-
* Lists all stored
|
|
31936
|
-
*
|
|
31937
|
-
* @returns Promise resolving to array of signal rows
|
|
32310
|
+
* Lists all stored signals.
|
|
32311
|
+
* @returns Array of all signal rows
|
|
31938
32312
|
*/
|
|
31939
32313
|
this.list = async () => {
|
|
31940
32314
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_LIST);
|
|
@@ -31943,15 +32317,14 @@ class StorageLiveUtils {
|
|
|
31943
32317
|
};
|
|
31944
32318
|
}
|
|
31945
32319
|
/**
|
|
31946
|
-
* Persists current signal
|
|
31947
|
-
* Sorts by priority and
|
|
31948
|
-
*
|
|
31949
|
-
* @throws Error if storage not initialized
|
|
32320
|
+
* Persists the current signal map to disk storage.
|
|
32321
|
+
* Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
|
|
32322
|
+
* @throws Error if not initialized
|
|
31950
32323
|
*/
|
|
31951
32324
|
async _updateStorage() {
|
|
31952
32325
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_UPDATE_STORAGE);
|
|
31953
32326
|
if (!this._signals) {
|
|
31954
|
-
throw new Error("
|
|
32327
|
+
throw new Error("StoragePersistLiveUtils not initialized. Call waitForInit first.");
|
|
31955
32328
|
}
|
|
31956
32329
|
const signalList = Array.from(this._signals.values());
|
|
31957
32330
|
signalList.sort((a, b) => a.priority - b.priority);
|
|
@@ -31959,36 +32332,385 @@ class StorageLiveUtils {
|
|
|
31959
32332
|
}
|
|
31960
32333
|
}
|
|
31961
32334
|
/**
|
|
31962
|
-
*
|
|
32335
|
+
* In-memory storage adapter for live trading signals.
|
|
31963
32336
|
*
|
|
31964
|
-
*
|
|
31965
|
-
*
|
|
31966
|
-
*
|
|
32337
|
+
* Features:
|
|
32338
|
+
* - Stores signals in memory only (no persistence)
|
|
32339
|
+
* - Fast read/write operations
|
|
32340
|
+
* - Data is lost when application restarts
|
|
32341
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
32342
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31967
32343
|
*
|
|
31968
|
-
*
|
|
31969
|
-
|
|
31970
|
-
|
|
32344
|
+
* Use this adapter for testing or when persistence is not required.
|
|
32345
|
+
*/
|
|
32346
|
+
class StorageMemoryLiveUtils {
|
|
32347
|
+
constructor() {
|
|
32348
|
+
/** Map of signal IDs to signal rows */
|
|
32349
|
+
this._signals = new Map();
|
|
32350
|
+
/**
|
|
32351
|
+
* Handles signal opened event.
|
|
32352
|
+
* Updates in-memory storage with opened status if not stale.
|
|
32353
|
+
* @param tick - The opened signal tick data
|
|
32354
|
+
*/
|
|
32355
|
+
this.handleOpened = async (tick) => {
|
|
32356
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_OPENED, {
|
|
32357
|
+
signalId: tick.signal.id,
|
|
32358
|
+
});
|
|
32359
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32360
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32361
|
+
return;
|
|
32362
|
+
}
|
|
32363
|
+
this._signals.set(tick.signal.id, {
|
|
32364
|
+
...tick.signal,
|
|
32365
|
+
status: "opened",
|
|
32366
|
+
priority: Date.now(),
|
|
32367
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32368
|
+
updatedAt: tick.createdAt,
|
|
32369
|
+
});
|
|
32370
|
+
};
|
|
32371
|
+
/**
|
|
32372
|
+
* Handles signal closed event.
|
|
32373
|
+
* Updates in-memory storage with closed status and PnL if not stale.
|
|
32374
|
+
* @param tick - The closed signal tick data
|
|
32375
|
+
*/
|
|
32376
|
+
this.handleClosed = async (tick) => {
|
|
32377
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CLOSED, {
|
|
32378
|
+
signalId: tick.signal.id,
|
|
32379
|
+
});
|
|
32380
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32381
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32382
|
+
return;
|
|
32383
|
+
}
|
|
32384
|
+
this._signals.set(tick.signal.id, {
|
|
32385
|
+
...tick.signal,
|
|
32386
|
+
status: "closed",
|
|
32387
|
+
priority: Date.now(),
|
|
32388
|
+
pnl: tick.pnl,
|
|
32389
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32390
|
+
updatedAt: tick.createdAt,
|
|
32391
|
+
});
|
|
32392
|
+
};
|
|
32393
|
+
/**
|
|
32394
|
+
* Handles signal scheduled event.
|
|
32395
|
+
* Updates in-memory storage with scheduled status if not stale.
|
|
32396
|
+
* @param tick - The scheduled signal tick data
|
|
32397
|
+
*/
|
|
32398
|
+
this.handleScheduled = async (tick) => {
|
|
32399
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
32400
|
+
signalId: tick.signal.id,
|
|
32401
|
+
});
|
|
32402
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32403
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32404
|
+
return;
|
|
32405
|
+
}
|
|
32406
|
+
this._signals.set(tick.signal.id, {
|
|
32407
|
+
...tick.signal,
|
|
32408
|
+
status: "scheduled",
|
|
32409
|
+
priority: Date.now(),
|
|
32410
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32411
|
+
updatedAt: tick.createdAt,
|
|
32412
|
+
});
|
|
32413
|
+
};
|
|
32414
|
+
/**
|
|
32415
|
+
* Handles signal cancelled event.
|
|
32416
|
+
* Updates in-memory storage with cancelled status if not stale.
|
|
32417
|
+
* @param tick - The cancelled signal tick data
|
|
32418
|
+
*/
|
|
32419
|
+
this.handleCancelled = async (tick) => {
|
|
32420
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CANCELLED, {
|
|
32421
|
+
signalId: tick.signal.id,
|
|
32422
|
+
});
|
|
32423
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32424
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32425
|
+
return;
|
|
32426
|
+
}
|
|
32427
|
+
this._signals.set(tick.signal.id, {
|
|
32428
|
+
...tick.signal,
|
|
32429
|
+
status: "cancelled",
|
|
32430
|
+
priority: Date.now(),
|
|
32431
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32432
|
+
updatedAt: tick.createdAt,
|
|
32433
|
+
});
|
|
32434
|
+
};
|
|
32435
|
+
/**
|
|
32436
|
+
* Finds a signal by its ID.
|
|
32437
|
+
* @param id - The signal ID to search for
|
|
32438
|
+
* @returns The signal row or null if not found
|
|
32439
|
+
*/
|
|
32440
|
+
this.findById = async (id) => {
|
|
32441
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_FIND_BY_ID, { id });
|
|
32442
|
+
return this._signals.get(id) ?? null;
|
|
32443
|
+
};
|
|
32444
|
+
/**
|
|
32445
|
+
* Lists all stored signals.
|
|
32446
|
+
* @returns Array of all signal rows
|
|
32447
|
+
*/
|
|
32448
|
+
this.list = async () => {
|
|
32449
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_LIST);
|
|
32450
|
+
return Array.from(this._signals.values());
|
|
32451
|
+
};
|
|
32452
|
+
}
|
|
32453
|
+
}
|
|
32454
|
+
/**
|
|
32455
|
+
* Dummy storage adapter for live trading signals that discards all writes.
|
|
31971
32456
|
*
|
|
31972
|
-
*
|
|
31973
|
-
*
|
|
32457
|
+
* Features:
|
|
32458
|
+
* - No-op implementation for all methods
|
|
32459
|
+
* - findById always returns null
|
|
32460
|
+
* - list always returns empty array
|
|
31974
32461
|
*
|
|
31975
|
-
*
|
|
31976
|
-
|
|
31977
|
-
|
|
31978
|
-
|
|
32462
|
+
* Use this adapter to disable live signal storage completely.
|
|
32463
|
+
*/
|
|
32464
|
+
class StorageDummyLiveUtils {
|
|
32465
|
+
constructor() {
|
|
32466
|
+
/**
|
|
32467
|
+
* No-op handler for signal opened event.
|
|
32468
|
+
*/
|
|
32469
|
+
this.handleOpened = async () => {
|
|
32470
|
+
};
|
|
32471
|
+
/**
|
|
32472
|
+
* No-op handler for signal closed event.
|
|
32473
|
+
*/
|
|
32474
|
+
this.handleClosed = async () => {
|
|
32475
|
+
};
|
|
32476
|
+
/**
|
|
32477
|
+
* No-op handler for signal scheduled event.
|
|
32478
|
+
*/
|
|
32479
|
+
this.handleScheduled = async () => {
|
|
32480
|
+
};
|
|
32481
|
+
/**
|
|
32482
|
+
* No-op handler for signal cancelled event.
|
|
32483
|
+
*/
|
|
32484
|
+
this.handleCancelled = async () => {
|
|
32485
|
+
};
|
|
32486
|
+
/**
|
|
32487
|
+
* Always returns null (no storage).
|
|
32488
|
+
* @returns null
|
|
32489
|
+
*/
|
|
32490
|
+
this.findById = async () => {
|
|
32491
|
+
return null;
|
|
32492
|
+
};
|
|
32493
|
+
/**
|
|
32494
|
+
* Always returns empty array (no storage).
|
|
32495
|
+
* @returns Empty array
|
|
32496
|
+
*/
|
|
32497
|
+
this.list = async () => {
|
|
32498
|
+
return [];
|
|
32499
|
+
};
|
|
32500
|
+
}
|
|
32501
|
+
}
|
|
32502
|
+
/**
|
|
32503
|
+
* Backtest storage adapter with pluggable storage backend.
|
|
31979
32504
|
*
|
|
31980
|
-
*
|
|
31981
|
-
*
|
|
31982
|
-
*
|
|
32505
|
+
* Features:
|
|
32506
|
+
* - Adapter pattern for swappable storage implementations
|
|
32507
|
+
* - Default adapter: StoragePersistBacktestUtils (persistent storage)
|
|
32508
|
+
* - Alternative adapters: StorageMemoryBacktestUtils, StorageDummyBacktestUtils
|
|
32509
|
+
* - Convenience methods: usePersist(), useMemory(), useDummy()
|
|
32510
|
+
*/
|
|
32511
|
+
class StorageBacktestAdapter {
|
|
32512
|
+
constructor() {
|
|
32513
|
+
/** Internal storage utils instance */
|
|
32514
|
+
this._signalBacktestUtils = new StorageMemoryBacktestUtils();
|
|
32515
|
+
/**
|
|
32516
|
+
* Handles signal opened event.
|
|
32517
|
+
* Proxies call to the underlying storage adapter.
|
|
32518
|
+
* @param tick - The opened signal tick data
|
|
32519
|
+
*/
|
|
32520
|
+
this.handleOpened = async (tick) => {
|
|
32521
|
+
return await this._signalBacktestUtils.handleOpened(tick);
|
|
32522
|
+
};
|
|
32523
|
+
/**
|
|
32524
|
+
* Handles signal closed event.
|
|
32525
|
+
* Proxies call to the underlying storage adapter.
|
|
32526
|
+
* @param tick - The closed signal tick data
|
|
32527
|
+
*/
|
|
32528
|
+
this.handleClosed = async (tick) => {
|
|
32529
|
+
return await this._signalBacktestUtils.handleClosed(tick);
|
|
32530
|
+
};
|
|
32531
|
+
/**
|
|
32532
|
+
* Handles signal scheduled event.
|
|
32533
|
+
* Proxies call to the underlying storage adapter.
|
|
32534
|
+
* @param tick - The scheduled signal tick data
|
|
32535
|
+
*/
|
|
32536
|
+
this.handleScheduled = async (tick) => {
|
|
32537
|
+
return await this._signalBacktestUtils.handleScheduled(tick);
|
|
32538
|
+
};
|
|
32539
|
+
/**
|
|
32540
|
+
* Handles signal cancelled event.
|
|
32541
|
+
* Proxies call to the underlying storage adapter.
|
|
32542
|
+
* @param tick - The cancelled signal tick data
|
|
32543
|
+
*/
|
|
32544
|
+
this.handleCancelled = async (tick) => {
|
|
32545
|
+
return await this._signalBacktestUtils.handleCancelled(tick);
|
|
32546
|
+
};
|
|
32547
|
+
/**
|
|
32548
|
+
* Finds a signal by its ID.
|
|
32549
|
+
* Proxies call to the underlying storage adapter.
|
|
32550
|
+
* @param id - The signal ID to search for
|
|
32551
|
+
* @returns The signal row or null if not found
|
|
32552
|
+
*/
|
|
32553
|
+
this.findById = async (id) => {
|
|
32554
|
+
return await this._signalBacktestUtils.findById(id);
|
|
32555
|
+
};
|
|
32556
|
+
/**
|
|
32557
|
+
* Lists all stored signals.
|
|
32558
|
+
* Proxies call to the underlying storage adapter.
|
|
32559
|
+
* @returns Array of all signal rows
|
|
32560
|
+
*/
|
|
32561
|
+
this.list = async () => {
|
|
32562
|
+
return await this._signalBacktestUtils.list();
|
|
32563
|
+
};
|
|
32564
|
+
/**
|
|
32565
|
+
* Sets the storage adapter constructor.
|
|
32566
|
+
* All future storage operations will use this adapter.
|
|
32567
|
+
*
|
|
32568
|
+
* @param Ctor - Constructor for storage adapter
|
|
32569
|
+
*/
|
|
32570
|
+
this.useStorageAdapter = (Ctor) => {
|
|
32571
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
32572
|
+
this._signalBacktestUtils = Reflect.construct(Ctor, []);
|
|
32573
|
+
};
|
|
32574
|
+
/**
|
|
32575
|
+
* Switches to dummy storage adapter.
|
|
32576
|
+
* All future storage writes will be no-ops.
|
|
32577
|
+
*/
|
|
32578
|
+
this.useDummy = () => {
|
|
32579
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
32580
|
+
this._signalBacktestUtils = new StorageDummyBacktestUtils();
|
|
32581
|
+
};
|
|
32582
|
+
/**
|
|
32583
|
+
* Switches to persistent storage adapter (default).
|
|
32584
|
+
* Signals will be persisted to disk.
|
|
32585
|
+
*/
|
|
32586
|
+
this.usePersist = () => {
|
|
32587
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
32588
|
+
this._signalBacktestUtils = new StoragePersistBacktestUtils();
|
|
32589
|
+
};
|
|
32590
|
+
/**
|
|
32591
|
+
* Switches to in-memory storage adapter.
|
|
32592
|
+
* Signals will be stored in memory only.
|
|
32593
|
+
*/
|
|
32594
|
+
this.useMemory = () => {
|
|
32595
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
32596
|
+
this._signalBacktestUtils = new StorageMemoryBacktestUtils();
|
|
32597
|
+
};
|
|
32598
|
+
}
|
|
32599
|
+
}
|
|
32600
|
+
/**
|
|
32601
|
+
* Live trading storage adapter with pluggable storage backend.
|
|
32602
|
+
*
|
|
32603
|
+
* Features:
|
|
32604
|
+
* - Adapter pattern for swappable storage implementations
|
|
32605
|
+
* - Default adapter: StoragePersistLiveUtils (persistent storage)
|
|
32606
|
+
* - Alternative adapters: StorageMemoryLiveUtils, StorageDummyLiveUtils
|
|
32607
|
+
* - Convenience methods: usePersist(), useMemory(), useDummy()
|
|
32608
|
+
*/
|
|
32609
|
+
class StorageLiveAdapter {
|
|
32610
|
+
constructor() {
|
|
32611
|
+
/** Internal storage utils instance */
|
|
32612
|
+
this._signalLiveUtils = new StoragePersistLiveUtils();
|
|
32613
|
+
/**
|
|
32614
|
+
* Handles signal opened event.
|
|
32615
|
+
* Proxies call to the underlying storage adapter.
|
|
32616
|
+
* @param tick - The opened signal tick data
|
|
32617
|
+
*/
|
|
32618
|
+
this.handleOpened = async (tick) => {
|
|
32619
|
+
return await this._signalLiveUtils.handleOpened(tick);
|
|
32620
|
+
};
|
|
32621
|
+
/**
|
|
32622
|
+
* Handles signal closed event.
|
|
32623
|
+
* Proxies call to the underlying storage adapter.
|
|
32624
|
+
* @param tick - The closed signal tick data
|
|
32625
|
+
*/
|
|
32626
|
+
this.handleClosed = async (tick) => {
|
|
32627
|
+
return await this._signalLiveUtils.handleClosed(tick);
|
|
32628
|
+
};
|
|
32629
|
+
/**
|
|
32630
|
+
* Handles signal scheduled event.
|
|
32631
|
+
* Proxies call to the underlying storage adapter.
|
|
32632
|
+
* @param tick - The scheduled signal tick data
|
|
32633
|
+
*/
|
|
32634
|
+
this.handleScheduled = async (tick) => {
|
|
32635
|
+
return await this._signalLiveUtils.handleScheduled(tick);
|
|
32636
|
+
};
|
|
32637
|
+
/**
|
|
32638
|
+
* Handles signal cancelled event.
|
|
32639
|
+
* Proxies call to the underlying storage adapter.
|
|
32640
|
+
* @param tick - The cancelled signal tick data
|
|
32641
|
+
*/
|
|
32642
|
+
this.handleCancelled = async (tick) => {
|
|
32643
|
+
return await this._signalLiveUtils.handleCancelled(tick);
|
|
32644
|
+
};
|
|
32645
|
+
/**
|
|
32646
|
+
* Finds a signal by its ID.
|
|
32647
|
+
* Proxies call to the underlying storage adapter.
|
|
32648
|
+
* @param id - The signal ID to search for
|
|
32649
|
+
* @returns The signal row or null if not found
|
|
32650
|
+
*/
|
|
32651
|
+
this.findById = async (id) => {
|
|
32652
|
+
return await this._signalLiveUtils.findById(id);
|
|
32653
|
+
};
|
|
32654
|
+
/**
|
|
32655
|
+
* Lists all stored signals.
|
|
32656
|
+
* Proxies call to the underlying storage adapter.
|
|
32657
|
+
* @returns Array of all signal rows
|
|
32658
|
+
*/
|
|
32659
|
+
this.list = async () => {
|
|
32660
|
+
return await this._signalLiveUtils.list();
|
|
32661
|
+
};
|
|
32662
|
+
/**
|
|
32663
|
+
* Sets the storage adapter constructor.
|
|
32664
|
+
* All future storage operations will use this adapter.
|
|
32665
|
+
*
|
|
32666
|
+
* @param Ctor - Constructor for storage adapter
|
|
32667
|
+
*/
|
|
32668
|
+
this.useStorageAdapter = (Ctor) => {
|
|
32669
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
32670
|
+
this._signalLiveUtils = Reflect.construct(Ctor, []);
|
|
32671
|
+
};
|
|
32672
|
+
/**
|
|
32673
|
+
* Switches to dummy storage adapter.
|
|
32674
|
+
* All future storage writes will be no-ops.
|
|
32675
|
+
*/
|
|
32676
|
+
this.useDummy = () => {
|
|
32677
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
32678
|
+
this._signalLiveUtils = new StorageDummyLiveUtils();
|
|
32679
|
+
};
|
|
32680
|
+
/**
|
|
32681
|
+
* Switches to persistent storage adapter (default).
|
|
32682
|
+
* Signals will be persisted to disk.
|
|
32683
|
+
*/
|
|
32684
|
+
this.usePersist = () => {
|
|
32685
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
32686
|
+
this._signalLiveUtils = new StoragePersistLiveUtils();
|
|
32687
|
+
};
|
|
32688
|
+
/**
|
|
32689
|
+
* Switches to in-memory storage adapter.
|
|
32690
|
+
* Signals will be stored in memory only.
|
|
32691
|
+
*/
|
|
32692
|
+
this.useMemory = () => {
|
|
32693
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
32694
|
+
this._signalLiveUtils = new StorageMemoryLiveUtils();
|
|
32695
|
+
};
|
|
32696
|
+
}
|
|
32697
|
+
}
|
|
32698
|
+
/**
|
|
32699
|
+
* Main storage adapter that manages both backtest and live signal storage.
|
|
32700
|
+
*
|
|
32701
|
+
* Features:
|
|
32702
|
+
* - Subscribes to signal emitters for automatic storage updates
|
|
32703
|
+
* - Provides unified access to both backtest and live signals
|
|
32704
|
+
* - Singleshot enable pattern prevents duplicate subscriptions
|
|
32705
|
+
* - Cleanup function for proper unsubscription
|
|
31983
32706
|
*/
|
|
31984
32707
|
class StorageAdapter {
|
|
31985
32708
|
constructor() {
|
|
31986
|
-
this._signalLiveUtils = new StorageLiveUtils();
|
|
31987
|
-
this._signalBacktestUtils = new StorageBacktestUtils();
|
|
31988
32709
|
/**
|
|
31989
|
-
* Enables signal
|
|
32710
|
+
* Enables signal storage by subscribing to signal emitters.
|
|
32711
|
+
* Uses singleshot to ensure one-time subscription.
|
|
31990
32712
|
*
|
|
31991
|
-
* @returns Cleanup function
|
|
32713
|
+
* @returns Cleanup function that unsubscribes from all emitters
|
|
31992
32714
|
*/
|
|
31993
32715
|
this.enable = singleshot(() => {
|
|
31994
32716
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_ENABLE);
|
|
@@ -31997,31 +32719,31 @@ class StorageAdapter {
|
|
|
31997
32719
|
{
|
|
31998
32720
|
const unBacktestOpen = signalBacktestEmitter
|
|
31999
32721
|
.filter(({ action }) => action === "opened")
|
|
32000
|
-
.connect((tick) =>
|
|
32722
|
+
.connect((tick) => StorageBacktest.handleOpened(tick));
|
|
32001
32723
|
const unBacktestClose = signalBacktestEmitter
|
|
32002
32724
|
.filter(({ action }) => action === "closed")
|
|
32003
|
-
.connect((tick) =>
|
|
32725
|
+
.connect((tick) => StorageBacktest.handleClosed(tick));
|
|
32004
32726
|
const unBacktestScheduled = signalBacktestEmitter
|
|
32005
32727
|
.filter(({ action }) => action === "scheduled")
|
|
32006
|
-
.connect((tick) =>
|
|
32728
|
+
.connect((tick) => StorageBacktest.handleScheduled(tick));
|
|
32007
32729
|
const unBacktestCancelled = signalBacktestEmitter
|
|
32008
32730
|
.filter(({ action }) => action === "cancelled")
|
|
32009
|
-
.connect((tick) =>
|
|
32731
|
+
.connect((tick) => StorageBacktest.handleCancelled(tick));
|
|
32010
32732
|
unBacktest = compose(() => unBacktestOpen(), () => unBacktestClose(), () => unBacktestScheduled(), () => unBacktestCancelled());
|
|
32011
32733
|
}
|
|
32012
32734
|
{
|
|
32013
32735
|
const unLiveOpen = signalLiveEmitter
|
|
32014
32736
|
.filter(({ action }) => action === "opened")
|
|
32015
|
-
.connect((tick) =>
|
|
32737
|
+
.connect((tick) => StorageLive.handleOpened(tick));
|
|
32016
32738
|
const unLiveClose = signalLiveEmitter
|
|
32017
32739
|
.filter(({ action }) => action === "closed")
|
|
32018
|
-
.connect((tick) =>
|
|
32740
|
+
.connect((tick) => StorageLive.handleClosed(tick));
|
|
32019
32741
|
const unLiveScheduled = signalLiveEmitter
|
|
32020
32742
|
.filter(({ action }) => action === "scheduled")
|
|
32021
|
-
.connect((tick) =>
|
|
32743
|
+
.connect((tick) => StorageLive.handleScheduled(tick));
|
|
32022
32744
|
const unLiveCancelled = signalLiveEmitter
|
|
32023
32745
|
.filter(({ action }) => action === "cancelled")
|
|
32024
|
-
.connect((tick) =>
|
|
32746
|
+
.connect((tick) => StorageLive.handleCancelled(tick));
|
|
32025
32747
|
unLive = compose(() => unLiveOpen(), () => unLiveClose(), () => unLiveScheduled(), () => unLiveCancelled());
|
|
32026
32748
|
}
|
|
32027
32749
|
return () => {
|
|
@@ -32031,7 +32753,8 @@ class StorageAdapter {
|
|
|
32031
32753
|
};
|
|
32032
32754
|
});
|
|
32033
32755
|
/**
|
|
32034
|
-
* Disables signal
|
|
32756
|
+
* Disables signal storage by unsubscribing from all emitters.
|
|
32757
|
+
* Safe to call multiple times.
|
|
32035
32758
|
*/
|
|
32036
32759
|
this.disable = () => {
|
|
32037
32760
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_DISABLE);
|
|
@@ -32041,11 +32764,12 @@ class StorageAdapter {
|
|
|
32041
32764
|
}
|
|
32042
32765
|
};
|
|
32043
32766
|
/**
|
|
32044
|
-
* Finds a signal by ID across both backtest and live
|
|
32767
|
+
* Finds a signal by ID across both backtest and live storage.
|
|
32045
32768
|
*
|
|
32046
|
-
* @param id -
|
|
32047
|
-
* @returns
|
|
32048
|
-
* @throws Error if
|
|
32769
|
+
* @param id - The signal ID to search for
|
|
32770
|
+
* @returns The signal row or throws if not found
|
|
32771
|
+
* @throws Error if StorageAdapter is not enabled
|
|
32772
|
+
* @throws Error if signal is not found in either storage
|
|
32049
32773
|
*/
|
|
32050
32774
|
this.findSignalById = async (id) => {
|
|
32051
32775
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_FIND_SIGNAL_BY_ID, { id });
|
|
@@ -32053,41 +32777,57 @@ class StorageAdapter {
|
|
|
32053
32777
|
throw new Error("StorageAdapter is not enabled. Call enable() first.");
|
|
32054
32778
|
}
|
|
32055
32779
|
let result = null;
|
|
32056
|
-
if ((result = await
|
|
32780
|
+
if ((result = await StorageBacktest.findById(id))) {
|
|
32057
32781
|
return result;
|
|
32058
32782
|
}
|
|
32059
|
-
if ((result = await
|
|
32783
|
+
if ((result = await StorageLive.findById(id))) {
|
|
32060
32784
|
return result;
|
|
32061
32785
|
}
|
|
32062
32786
|
throw new Error(`Storage signal with id ${id} not found`);
|
|
32063
32787
|
};
|
|
32064
32788
|
/**
|
|
32065
|
-
* Lists all backtest
|
|
32789
|
+
* Lists all backtest signals from storage.
|
|
32066
32790
|
*
|
|
32067
|
-
* @returns
|
|
32791
|
+
* @returns Array of all backtest signal rows
|
|
32792
|
+
* @throws Error if StorageAdapter is not enabled
|
|
32068
32793
|
*/
|
|
32069
32794
|
this.listSignalBacktest = async () => {
|
|
32070
32795
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_BACKTEST);
|
|
32071
32796
|
if (!this.enable.hasValue()) {
|
|
32072
32797
|
throw new Error("StorageAdapter is not enabled. Call enable() first.");
|
|
32073
32798
|
}
|
|
32074
|
-
return await
|
|
32799
|
+
return await StorageBacktest.list();
|
|
32075
32800
|
};
|
|
32076
32801
|
/**
|
|
32077
|
-
* Lists all live
|
|
32802
|
+
* Lists all live signals from storage.
|
|
32078
32803
|
*
|
|
32079
|
-
* @returns
|
|
32804
|
+
* @returns Array of all live signal rows
|
|
32805
|
+
* @throws Error if StorageAdapter is not enabled
|
|
32080
32806
|
*/
|
|
32081
32807
|
this.listSignalLive = async () => {
|
|
32082
32808
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_LIVE);
|
|
32083
32809
|
if (!this.enable.hasValue()) {
|
|
32084
32810
|
throw new Error("StorageAdapter is not enabled. Call enable() first.");
|
|
32085
32811
|
}
|
|
32086
|
-
return await
|
|
32812
|
+
return await StorageLive.list();
|
|
32087
32813
|
};
|
|
32088
32814
|
}
|
|
32089
32815
|
}
|
|
32816
|
+
/**
|
|
32817
|
+
* Global singleton instance of StorageAdapter.
|
|
32818
|
+
* Provides unified signal storage management for backtest and live trading.
|
|
32819
|
+
*/
|
|
32090
32820
|
const Storage = new StorageAdapter();
|
|
32821
|
+
/**
|
|
32822
|
+
* Global singleton instance of StorageLiveAdapter.
|
|
32823
|
+
* Provides live trading signal storage with pluggable backends.
|
|
32824
|
+
*/
|
|
32825
|
+
const StorageLive = new StorageLiveAdapter();
|
|
32826
|
+
/**
|
|
32827
|
+
* Global singleton instance of StorageBacktestAdapter.
|
|
32828
|
+
* Provides backtest signal storage with pluggable backends.
|
|
32829
|
+
*/
|
|
32830
|
+
const StorageBacktest = new StorageBacktestAdapter();
|
|
32091
32831
|
|
|
32092
32832
|
const EXCHANGE_METHOD_NAME_GET_CANDLES = "ExchangeUtils.getCandles";
|
|
32093
32833
|
const EXCHANGE_METHOD_NAME_GET_AVERAGE_PRICE = "ExchangeUtils.getAveragePrice";
|
|
@@ -33181,6 +33921,12 @@ class NotificationInstance {
|
|
|
33181
33921
|
currentPrice: data.currentPrice,
|
|
33182
33922
|
priceOpen: data.data.priceOpen,
|
|
33183
33923
|
position: data.data.position,
|
|
33924
|
+
priceTakeProfit: data.data.priceTakeProfit,
|
|
33925
|
+
priceStopLoss: data.data.priceStopLoss,
|
|
33926
|
+
originalPriceTakeProfit: data.data.originalPriceTakeProfit,
|
|
33927
|
+
originalPriceStopLoss: data.data.originalPriceStopLoss,
|
|
33928
|
+
scheduledAt: data.data.scheduledAt,
|
|
33929
|
+
pendingAt: data.data.pendingAt,
|
|
33184
33930
|
createdAt: data.timestamp,
|
|
33185
33931
|
});
|
|
33186
33932
|
};
|
|
@@ -33201,6 +33947,12 @@ class NotificationInstance {
|
|
|
33201
33947
|
currentPrice: data.currentPrice,
|
|
33202
33948
|
priceOpen: data.data.priceOpen,
|
|
33203
33949
|
position: data.data.position,
|
|
33950
|
+
priceTakeProfit: data.data.priceTakeProfit,
|
|
33951
|
+
priceStopLoss: data.data.priceStopLoss,
|
|
33952
|
+
originalPriceTakeProfit: data.data.originalPriceTakeProfit,
|
|
33953
|
+
originalPriceStopLoss: data.data.originalPriceStopLoss,
|
|
33954
|
+
scheduledAt: data.data.scheduledAt,
|
|
33955
|
+
pendingAt: data.data.pendingAt,
|
|
33204
33956
|
createdAt: data.timestamp,
|
|
33205
33957
|
});
|
|
33206
33958
|
};
|
|
@@ -33220,6 +33972,12 @@ class NotificationInstance {
|
|
|
33220
33972
|
currentPrice: data.currentPrice,
|
|
33221
33973
|
priceOpen: data.data.priceOpen,
|
|
33222
33974
|
position: data.data.position,
|
|
33975
|
+
priceTakeProfit: data.data.priceTakeProfit,
|
|
33976
|
+
priceStopLoss: data.data.priceStopLoss,
|
|
33977
|
+
originalPriceTakeProfit: data.data.originalPriceTakeProfit,
|
|
33978
|
+
originalPriceStopLoss: data.data.originalPriceStopLoss,
|
|
33979
|
+
scheduledAt: data.data.scheduledAt,
|
|
33980
|
+
pendingAt: data.data.pendingAt,
|
|
33223
33981
|
createdAt: data.timestamp,
|
|
33224
33982
|
});
|
|
33225
33983
|
};
|
|
@@ -33238,6 +33996,14 @@ class NotificationInstance {
|
|
|
33238
33996
|
exchangeName: data.exchangeName,
|
|
33239
33997
|
percentToClose: data.percentToClose,
|
|
33240
33998
|
currentPrice: data.currentPrice,
|
|
33999
|
+
position: data.position,
|
|
34000
|
+
priceOpen: data.priceOpen,
|
|
34001
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34002
|
+
priceStopLoss: data.priceStopLoss,
|
|
34003
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34004
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34005
|
+
scheduledAt: data.scheduledAt,
|
|
34006
|
+
pendingAt: data.pendingAt,
|
|
33241
34007
|
createdAt: data.timestamp,
|
|
33242
34008
|
});
|
|
33243
34009
|
}
|
|
@@ -33252,6 +34018,14 @@ class NotificationInstance {
|
|
|
33252
34018
|
exchangeName: data.exchangeName,
|
|
33253
34019
|
percentToClose: data.percentToClose,
|
|
33254
34020
|
currentPrice: data.currentPrice,
|
|
34021
|
+
position: data.position,
|
|
34022
|
+
priceOpen: data.priceOpen,
|
|
34023
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34024
|
+
priceStopLoss: data.priceStopLoss,
|
|
34025
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34026
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34027
|
+
scheduledAt: data.scheduledAt,
|
|
34028
|
+
pendingAt: data.pendingAt,
|
|
33255
34029
|
createdAt: data.timestamp,
|
|
33256
34030
|
});
|
|
33257
34031
|
}
|
|
@@ -33265,6 +34039,14 @@ class NotificationInstance {
|
|
|
33265
34039
|
strategyName: data.strategyName,
|
|
33266
34040
|
exchangeName: data.exchangeName,
|
|
33267
34041
|
currentPrice: data.currentPrice,
|
|
34042
|
+
position: data.position,
|
|
34043
|
+
priceOpen: data.priceOpen,
|
|
34044
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34045
|
+
priceStopLoss: data.priceStopLoss,
|
|
34046
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34047
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34048
|
+
scheduledAt: data.scheduledAt,
|
|
34049
|
+
pendingAt: data.pendingAt,
|
|
33268
34050
|
createdAt: data.timestamp,
|
|
33269
34051
|
});
|
|
33270
34052
|
}
|
|
@@ -33279,6 +34061,14 @@ class NotificationInstance {
|
|
|
33279
34061
|
exchangeName: data.exchangeName,
|
|
33280
34062
|
percentShift: data.percentShift,
|
|
33281
34063
|
currentPrice: data.currentPrice,
|
|
34064
|
+
position: data.position,
|
|
34065
|
+
priceOpen: data.priceOpen,
|
|
34066
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34067
|
+
priceStopLoss: data.priceStopLoss,
|
|
34068
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34069
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34070
|
+
scheduledAt: data.scheduledAt,
|
|
34071
|
+
pendingAt: data.pendingAt,
|
|
33282
34072
|
createdAt: data.timestamp,
|
|
33283
34073
|
});
|
|
33284
34074
|
}
|
|
@@ -33293,6 +34083,14 @@ class NotificationInstance {
|
|
|
33293
34083
|
exchangeName: data.exchangeName,
|
|
33294
34084
|
percentShift: data.percentShift,
|
|
33295
34085
|
currentPrice: data.currentPrice,
|
|
34086
|
+
position: data.position,
|
|
34087
|
+
priceOpen: data.priceOpen,
|
|
34088
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34089
|
+
priceStopLoss: data.priceStopLoss,
|
|
34090
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34091
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34092
|
+
scheduledAt: data.scheduledAt,
|
|
34093
|
+
pendingAt: data.pendingAt,
|
|
33296
34094
|
createdAt: data.timestamp,
|
|
33297
34095
|
});
|
|
33298
34096
|
}
|
|
@@ -34094,4 +34892,4 @@ const set = (object, path, value) => {
|
|
|
34094
34892
|
}
|
|
34095
34893
|
};
|
|
34096
34894
|
|
|
34097
|
-
export { ActionBase, Backtest, Breakeven, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, Markdown, MarkdownFileBase, MarkdownFolderBase, MethodContextService, Notification, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, PositionSize, Report, ReportBase, Risk, Schedule, Storage, Strategy, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialProfit, commitTrailingStop, commitTrailingTake, emitters, formatPrice, formatQuantity, get, getActionSchema, getAveragePrice, getBacktestTimeframe, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getExchangeSchema, getFrameSchema, getMode, getOrderBook, getRawCandles, getRiskSchema, getSizingSchema, getStrategySchema, getSymbol, getWalkerSchema, hasTradeContext, backtest as lib, listExchangeSchema, listFrameSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, roundTicks, set, setColumns, setConfig, setLogger, stopStrategy, validate };
|
|
34895
|
+
export { ActionBase, Backtest, Breakeven, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, Markdown, MarkdownFileBase, MarkdownFolderBase, MethodContextService, Notification, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, PositionSize, Report, ReportBase, Risk, Schedule, Storage, StorageBacktest, StorageLive, Strategy, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialProfit, commitTrailingStop, commitTrailingTake, emitters, formatPrice, formatQuantity, get, getActionSchema, getAveragePrice, getBacktestTimeframe, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getExchangeSchema, getFrameSchema, getMode, getOrderBook, getRawCandles, getRiskSchema, getSizingSchema, getStrategySchema, getSymbol, getWalkerSchema, hasTradeContext, backtest as lib, listExchangeSchema, listFrameSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, roundTicks, set, setColumns, setConfig, setLogger, stopStrategy, validate };
|