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.cjs
CHANGED
|
@@ -2828,6 +2828,11 @@ const INTERVAL_MINUTES$3 = {
|
|
|
2828
2828
|
"30m": 30,
|
|
2829
2829
|
"1h": 60,
|
|
2830
2830
|
};
|
|
2831
|
+
/**
|
|
2832
|
+
* Mock value for scheduled signal pendingAt timestamp.
|
|
2833
|
+
* Used to indicate that the actual pendingAt will be set upon activation.
|
|
2834
|
+
*/
|
|
2835
|
+
const SCHEDULED_SIGNAL_PENDING_MOCK = 0;
|
|
2831
2836
|
const TIMEOUT_SYMBOL = Symbol('timeout');
|
|
2832
2837
|
/**
|
|
2833
2838
|
* Calls onCommit callback with strategy commit event.
|
|
@@ -2867,73 +2872,123 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, timestamp) => {
|
|
|
2867
2872
|
return;
|
|
2868
2873
|
}
|
|
2869
2874
|
const queue = self._commitQueue;
|
|
2870
|
-
|
|
2875
|
+
{
|
|
2876
|
+
self._commitQueue = [];
|
|
2877
|
+
}
|
|
2878
|
+
if (!self._pendingSignal) {
|
|
2879
|
+
return;
|
|
2880
|
+
}
|
|
2881
|
+
// Get public signal data for commit events (contains effective and original SL/TP)
|
|
2882
|
+
const publicSignal = TO_PUBLIC_SIGNAL(self._pendingSignal);
|
|
2871
2883
|
for (const commit of queue) {
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2884
|
+
if (commit.action === "partial-profit") {
|
|
2885
|
+
await CALL_COMMIT_FN(self, {
|
|
2886
|
+
action: "partial-profit",
|
|
2887
|
+
symbol: commit.symbol,
|
|
2888
|
+
strategyName: self.params.strategyName,
|
|
2889
|
+
exchangeName: self.params.exchangeName,
|
|
2890
|
+
frameName: self.params.frameName,
|
|
2891
|
+
backtest: commit.backtest,
|
|
2892
|
+
percentToClose: commit.percentToClose,
|
|
2893
|
+
currentPrice: commit.currentPrice,
|
|
2894
|
+
timestamp,
|
|
2895
|
+
position: publicSignal.position,
|
|
2896
|
+
priceOpen: publicSignal.priceOpen,
|
|
2897
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2898
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2899
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2900
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2901
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2902
|
+
pendingAt: publicSignal.pendingAt,
|
|
2903
|
+
});
|
|
2904
|
+
continue;
|
|
2905
|
+
}
|
|
2906
|
+
if (commit.action === "partial-loss") {
|
|
2907
|
+
await CALL_COMMIT_FN(self, {
|
|
2908
|
+
action: "partial-loss",
|
|
2909
|
+
symbol: commit.symbol,
|
|
2910
|
+
strategyName: self.params.strategyName,
|
|
2911
|
+
exchangeName: self.params.exchangeName,
|
|
2912
|
+
frameName: self.params.frameName,
|
|
2913
|
+
backtest: commit.backtest,
|
|
2914
|
+
percentToClose: commit.percentToClose,
|
|
2915
|
+
currentPrice: commit.currentPrice,
|
|
2916
|
+
timestamp,
|
|
2917
|
+
position: publicSignal.position,
|
|
2918
|
+
priceOpen: publicSignal.priceOpen,
|
|
2919
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2920
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2921
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2922
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2923
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2924
|
+
pendingAt: publicSignal.pendingAt,
|
|
2925
|
+
});
|
|
2926
|
+
continue;
|
|
2927
|
+
}
|
|
2928
|
+
if (commit.action === "breakeven") {
|
|
2929
|
+
await CALL_COMMIT_FN(self, {
|
|
2930
|
+
action: "breakeven",
|
|
2931
|
+
symbol: commit.symbol,
|
|
2932
|
+
strategyName: self.params.strategyName,
|
|
2933
|
+
exchangeName: self.params.exchangeName,
|
|
2934
|
+
frameName: self.params.frameName,
|
|
2935
|
+
backtest: commit.backtest,
|
|
2936
|
+
currentPrice: commit.currentPrice,
|
|
2937
|
+
timestamp,
|
|
2938
|
+
position: publicSignal.position,
|
|
2939
|
+
priceOpen: publicSignal.priceOpen,
|
|
2940
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2941
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2942
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2943
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2944
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2945
|
+
pendingAt: publicSignal.pendingAt,
|
|
2946
|
+
});
|
|
2947
|
+
continue;
|
|
2948
|
+
}
|
|
2949
|
+
if (commit.action === "trailing-stop") {
|
|
2950
|
+
await CALL_COMMIT_FN(self, {
|
|
2951
|
+
action: "trailing-stop",
|
|
2952
|
+
symbol: commit.symbol,
|
|
2953
|
+
strategyName: self.params.strategyName,
|
|
2954
|
+
exchangeName: self.params.exchangeName,
|
|
2955
|
+
frameName: self.params.frameName,
|
|
2956
|
+
backtest: commit.backtest,
|
|
2957
|
+
percentShift: commit.percentShift,
|
|
2958
|
+
currentPrice: commit.currentPrice,
|
|
2959
|
+
timestamp,
|
|
2960
|
+
position: publicSignal.position,
|
|
2961
|
+
priceOpen: publicSignal.priceOpen,
|
|
2962
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2963
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2964
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2965
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2966
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2967
|
+
pendingAt: publicSignal.pendingAt,
|
|
2968
|
+
});
|
|
2969
|
+
continue;
|
|
2970
|
+
}
|
|
2971
|
+
if (commit.action === "trailing-take") {
|
|
2972
|
+
await CALL_COMMIT_FN(self, {
|
|
2973
|
+
action: "trailing-take",
|
|
2974
|
+
symbol: commit.symbol,
|
|
2975
|
+
strategyName: self.params.strategyName,
|
|
2976
|
+
exchangeName: self.params.exchangeName,
|
|
2977
|
+
frameName: self.params.frameName,
|
|
2978
|
+
backtest: commit.backtest,
|
|
2979
|
+
percentShift: commit.percentShift,
|
|
2980
|
+
currentPrice: commit.currentPrice,
|
|
2981
|
+
timestamp,
|
|
2982
|
+
position: publicSignal.position,
|
|
2983
|
+
priceOpen: publicSignal.priceOpen,
|
|
2984
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
2985
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
2986
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
2987
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
2988
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
2989
|
+
pendingAt: publicSignal.pendingAt,
|
|
2990
|
+
});
|
|
2991
|
+
continue;
|
|
2937
2992
|
}
|
|
2938
2993
|
}
|
|
2939
2994
|
};
|
|
@@ -3258,7 +3313,7 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
|
|
|
3258
3313
|
if (typeof signal.pendingAt !== "number") {
|
|
3259
3314
|
errors.push(`pendingAt must be a number type, got ${signal.pendingAt} (${typeof signal.pendingAt})`);
|
|
3260
3315
|
}
|
|
3261
|
-
if (signal.pendingAt <= 0) {
|
|
3316
|
+
if (signal.pendingAt <= 0 && !isScheduled) {
|
|
3262
3317
|
errors.push(`pendingAt must be positive, got ${signal.pendingAt}`);
|
|
3263
3318
|
}
|
|
3264
3319
|
}
|
|
@@ -3344,7 +3399,7 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
3344
3399
|
strategyName: self.params.method.context.strategyName,
|
|
3345
3400
|
frameName: self.params.method.context.frameName,
|
|
3346
3401
|
scheduledAt: currentTime,
|
|
3347
|
-
pendingAt:
|
|
3402
|
+
pendingAt: SCHEDULED_SIGNAL_PENDING_MOCK, // Временно, обновится при активации
|
|
3348
3403
|
_isScheduled: true,
|
|
3349
3404
|
};
|
|
3350
3405
|
// Валидируем сигнал перед возвратом
|
|
@@ -13488,6 +13543,8 @@ const backtest_columns = [
|
|
|
13488
13543
|
key: "duration",
|
|
13489
13544
|
label: "Duration (min)",
|
|
13490
13545
|
format: (data) => {
|
|
13546
|
+
if (!data.closeTimestamp || !data.signal.pendingAt)
|
|
13547
|
+
return "N/A";
|
|
13491
13548
|
const durationMs = data.closeTimestamp - data.signal.pendingAt;
|
|
13492
13549
|
const durationMin = Math.round(durationMs / 60000);
|
|
13493
13550
|
return `${durationMin}`;
|
|
@@ -13497,7 +13554,7 @@ const backtest_columns = [
|
|
|
13497
13554
|
{
|
|
13498
13555
|
key: "openTimestamp",
|
|
13499
13556
|
label: "Open Time",
|
|
13500
|
-
format: (data) => new Date(data.signal.pendingAt).toISOString(),
|
|
13557
|
+
format: (data) => data.signal.pendingAt ? new Date(data.signal.pendingAt).toISOString() : "N/A",
|
|
13501
13558
|
isVisible: () => true,
|
|
13502
13559
|
},
|
|
13503
13560
|
{
|
|
@@ -23626,7 +23683,7 @@ class RiskReportService {
|
|
|
23626
23683
|
strategyName: data.strategyName,
|
|
23627
23684
|
exchangeName: data.exchangeName,
|
|
23628
23685
|
frameName: data.frameName,
|
|
23629
|
-
signalId: "",
|
|
23686
|
+
signalId: data.pendingSignal?.id || "",
|
|
23630
23687
|
walkerName: "",
|
|
23631
23688
|
});
|
|
23632
23689
|
};
|
|
@@ -23791,8 +23848,16 @@ class StrategyReportService {
|
|
|
23791
23848
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23792
23849
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23793
23850
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23794
|
-
|
|
23795
|
-
|
|
23851
|
+
* @param position - Trade direction: "long" or "short"
|
|
23852
|
+
* @param priceOpen - Entry price for the position
|
|
23853
|
+
* @param priceTakeProfit - Effective take profit price
|
|
23854
|
+
* @param priceStopLoss - Effective stop loss price
|
|
23855
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
23856
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
23857
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
23858
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
23859
|
+
*/
|
|
23860
|
+
this.partialProfit = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23796
23861
|
this.loggerService.log("strategyReportService partialProfit", {
|
|
23797
23862
|
symbol,
|
|
23798
23863
|
percentToClose,
|
|
@@ -23818,6 +23883,14 @@ class StrategyReportService {
|
|
|
23818
23883
|
symbol,
|
|
23819
23884
|
timestamp,
|
|
23820
23885
|
createdAt,
|
|
23886
|
+
position,
|
|
23887
|
+
priceOpen,
|
|
23888
|
+
priceTakeProfit,
|
|
23889
|
+
priceStopLoss,
|
|
23890
|
+
originalPriceTakeProfit,
|
|
23891
|
+
originalPriceStopLoss,
|
|
23892
|
+
scheduledAt,
|
|
23893
|
+
pendingAt,
|
|
23821
23894
|
}, {
|
|
23822
23895
|
signalId: pendingRow.id,
|
|
23823
23896
|
exchangeName: context.exchangeName,
|
|
@@ -23836,8 +23909,16 @@ class StrategyReportService {
|
|
|
23836
23909
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23837
23910
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23838
23911
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23839
|
-
|
|
23840
|
-
|
|
23912
|
+
* @param position - Trade direction: "long" or "short"
|
|
23913
|
+
* @param priceOpen - Entry price for the position
|
|
23914
|
+
* @param priceTakeProfit - Effective take profit price
|
|
23915
|
+
* @param priceStopLoss - Effective stop loss price
|
|
23916
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
23917
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
23918
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
23919
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
23920
|
+
*/
|
|
23921
|
+
this.partialLoss = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23841
23922
|
this.loggerService.log("strategyReportService partialLoss", {
|
|
23842
23923
|
symbol,
|
|
23843
23924
|
percentToClose,
|
|
@@ -23863,6 +23944,14 @@ class StrategyReportService {
|
|
|
23863
23944
|
symbol,
|
|
23864
23945
|
timestamp,
|
|
23865
23946
|
createdAt,
|
|
23947
|
+
position,
|
|
23948
|
+
priceOpen,
|
|
23949
|
+
priceTakeProfit,
|
|
23950
|
+
priceStopLoss,
|
|
23951
|
+
originalPriceTakeProfit,
|
|
23952
|
+
originalPriceStopLoss,
|
|
23953
|
+
scheduledAt,
|
|
23954
|
+
pendingAt,
|
|
23866
23955
|
}, {
|
|
23867
23956
|
signalId: pendingRow.id,
|
|
23868
23957
|
exchangeName: context.exchangeName,
|
|
@@ -23881,8 +23970,16 @@ class StrategyReportService {
|
|
|
23881
23970
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23882
23971
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23883
23972
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23884
|
-
|
|
23885
|
-
|
|
23973
|
+
* @param position - Trade direction: "long" or "short"
|
|
23974
|
+
* @param priceOpen - Entry price for the position
|
|
23975
|
+
* @param priceTakeProfit - Effective take profit price
|
|
23976
|
+
* @param priceStopLoss - Effective stop loss price
|
|
23977
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
23978
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
23979
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
23980
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
23981
|
+
*/
|
|
23982
|
+
this.trailingStop = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23886
23983
|
this.loggerService.log("strategyReportService trailingStop", {
|
|
23887
23984
|
symbol,
|
|
23888
23985
|
percentShift,
|
|
@@ -23908,6 +24005,14 @@ class StrategyReportService {
|
|
|
23908
24005
|
symbol,
|
|
23909
24006
|
timestamp,
|
|
23910
24007
|
createdAt,
|
|
24008
|
+
position,
|
|
24009
|
+
priceOpen,
|
|
24010
|
+
priceTakeProfit,
|
|
24011
|
+
priceStopLoss,
|
|
24012
|
+
originalPriceTakeProfit,
|
|
24013
|
+
originalPriceStopLoss,
|
|
24014
|
+
scheduledAt,
|
|
24015
|
+
pendingAt,
|
|
23911
24016
|
}, {
|
|
23912
24017
|
signalId: pendingRow.id,
|
|
23913
24018
|
exchangeName: context.exchangeName,
|
|
@@ -23926,8 +24031,16 @@ class StrategyReportService {
|
|
|
23926
24031
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23927
24032
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23928
24033
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23929
|
-
|
|
23930
|
-
|
|
24034
|
+
* @param position - Trade direction: "long" or "short"
|
|
24035
|
+
* @param priceOpen - Entry price for the position
|
|
24036
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24037
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24038
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24039
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24040
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24041
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24042
|
+
*/
|
|
24043
|
+
this.trailingTake = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23931
24044
|
this.loggerService.log("strategyReportService trailingTake", {
|
|
23932
24045
|
symbol,
|
|
23933
24046
|
percentShift,
|
|
@@ -23953,6 +24066,14 @@ class StrategyReportService {
|
|
|
23953
24066
|
symbol,
|
|
23954
24067
|
timestamp,
|
|
23955
24068
|
createdAt,
|
|
24069
|
+
position,
|
|
24070
|
+
priceOpen,
|
|
24071
|
+
priceTakeProfit,
|
|
24072
|
+
priceStopLoss,
|
|
24073
|
+
originalPriceTakeProfit,
|
|
24074
|
+
originalPriceStopLoss,
|
|
24075
|
+
scheduledAt,
|
|
24076
|
+
pendingAt,
|
|
23956
24077
|
}, {
|
|
23957
24078
|
signalId: pendingRow.id,
|
|
23958
24079
|
exchangeName: context.exchangeName,
|
|
@@ -23970,8 +24091,16 @@ class StrategyReportService {
|
|
|
23970
24091
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
23971
24092
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
23972
24093
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
23973
|
-
|
|
23974
|
-
|
|
24094
|
+
* @param position - Trade direction: "long" or "short"
|
|
24095
|
+
* @param priceOpen - Entry price for the position
|
|
24096
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24097
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24098
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24099
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24100
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24101
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24102
|
+
*/
|
|
24103
|
+
this.breakeven = async (symbol, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
23975
24104
|
this.loggerService.log("strategyReportService breakeven", {
|
|
23976
24105
|
symbol,
|
|
23977
24106
|
currentPrice,
|
|
@@ -23995,6 +24124,14 @@ class StrategyReportService {
|
|
|
23995
24124
|
symbol,
|
|
23996
24125
|
timestamp,
|
|
23997
24126
|
createdAt,
|
|
24127
|
+
position,
|
|
24128
|
+
priceOpen,
|
|
24129
|
+
priceTakeProfit,
|
|
24130
|
+
priceStopLoss,
|
|
24131
|
+
originalPriceTakeProfit,
|
|
24132
|
+
originalPriceStopLoss,
|
|
24133
|
+
scheduledAt,
|
|
24134
|
+
pendingAt,
|
|
23998
24135
|
}, {
|
|
23999
24136
|
signalId: pendingRow.id,
|
|
24000
24137
|
exchangeName: context.exchangeName,
|
|
@@ -24034,35 +24171,35 @@ class StrategyReportService {
|
|
|
24034
24171
|
exchangeName: event.exchangeName,
|
|
24035
24172
|
frameName: event.frameName,
|
|
24036
24173
|
strategyName: event.strategyName,
|
|
24037
|
-
}, event.timestamp));
|
|
24174
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24038
24175
|
const unPartialLoss = strategyCommitSubject
|
|
24039
24176
|
.filter(({ action }) => action === "partial-loss")
|
|
24040
24177
|
.connect(async (event) => await this.partialLoss(event.symbol, event.percentToClose, event.currentPrice, event.backtest, {
|
|
24041
24178
|
exchangeName: event.exchangeName,
|
|
24042
24179
|
frameName: event.frameName,
|
|
24043
24180
|
strategyName: event.strategyName,
|
|
24044
|
-
}, event.timestamp));
|
|
24181
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24045
24182
|
const unTrailingStop = strategyCommitSubject
|
|
24046
24183
|
.filter(({ action }) => action === "trailing-stop")
|
|
24047
24184
|
.connect(async (event) => await this.trailingStop(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
|
|
24048
24185
|
exchangeName: event.exchangeName,
|
|
24049
24186
|
frameName: event.frameName,
|
|
24050
24187
|
strategyName: event.strategyName,
|
|
24051
|
-
}, event.timestamp));
|
|
24188
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24052
24189
|
const unTrailingTake = strategyCommitSubject
|
|
24053
24190
|
.filter(({ action }) => action === "trailing-take")
|
|
24054
24191
|
.connect(async (event) => await this.trailingTake(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
|
|
24055
24192
|
exchangeName: event.exchangeName,
|
|
24056
24193
|
frameName: event.frameName,
|
|
24057
24194
|
strategyName: event.strategyName,
|
|
24058
|
-
}, event.timestamp));
|
|
24195
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24059
24196
|
const unBreakeven = strategyCommitSubject
|
|
24060
24197
|
.filter(({ action }) => action === "breakeven")
|
|
24061
24198
|
.connect(async (event) => await this.breakeven(event.symbol, event.currentPrice, event.backtest, {
|
|
24062
24199
|
exchangeName: event.exchangeName,
|
|
24063
24200
|
frameName: event.frameName,
|
|
24064
24201
|
strategyName: event.strategyName,
|
|
24065
|
-
}, event.timestamp));
|
|
24202
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24066
24203
|
const disposeFn = functoolsKit.compose(() => unCancelSchedule(), () => unClosePending(), () => unPartialProfit(), () => unPartialLoss(), () => unTrailingStop(), () => unTrailingTake(), () => unBreakeven());
|
|
24067
24204
|
return () => {
|
|
24068
24205
|
disposeFn();
|
|
@@ -24432,8 +24569,16 @@ class StrategyMarkdownService {
|
|
|
24432
24569
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24433
24570
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24434
24571
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24435
|
-
|
|
24436
|
-
|
|
24572
|
+
* @param position - Trade direction: "long" or "short"
|
|
24573
|
+
* @param priceOpen - Entry price for the position
|
|
24574
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24575
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24576
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24577
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24578
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24579
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24580
|
+
*/
|
|
24581
|
+
this.partialProfit = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24437
24582
|
this.loggerService.log("strategyMarkdownService partialProfit", {
|
|
24438
24583
|
symbol,
|
|
24439
24584
|
percentToClose,
|
|
@@ -24465,6 +24610,14 @@ class StrategyMarkdownService {
|
|
|
24465
24610
|
currentPrice,
|
|
24466
24611
|
createdAt,
|
|
24467
24612
|
backtest: isBacktest,
|
|
24613
|
+
position,
|
|
24614
|
+
priceOpen,
|
|
24615
|
+
priceTakeProfit,
|
|
24616
|
+
priceStopLoss,
|
|
24617
|
+
originalPriceTakeProfit,
|
|
24618
|
+
originalPriceStopLoss,
|
|
24619
|
+
scheduledAt,
|
|
24620
|
+
pendingAt,
|
|
24468
24621
|
});
|
|
24469
24622
|
};
|
|
24470
24623
|
/**
|
|
@@ -24476,8 +24629,16 @@ class StrategyMarkdownService {
|
|
|
24476
24629
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24477
24630
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24478
24631
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24479
|
-
|
|
24480
|
-
|
|
24632
|
+
* @param position - Trade direction: "long" or "short"
|
|
24633
|
+
* @param priceOpen - Entry price for the position
|
|
24634
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24635
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24636
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24637
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24638
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24639
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24640
|
+
*/
|
|
24641
|
+
this.partialLoss = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24481
24642
|
this.loggerService.log("strategyMarkdownService partialLoss", {
|
|
24482
24643
|
symbol,
|
|
24483
24644
|
percentToClose,
|
|
@@ -24509,6 +24670,14 @@ class StrategyMarkdownService {
|
|
|
24509
24670
|
currentPrice,
|
|
24510
24671
|
createdAt,
|
|
24511
24672
|
backtest: isBacktest,
|
|
24673
|
+
position,
|
|
24674
|
+
priceOpen,
|
|
24675
|
+
priceTakeProfit,
|
|
24676
|
+
priceStopLoss,
|
|
24677
|
+
originalPriceTakeProfit,
|
|
24678
|
+
originalPriceStopLoss,
|
|
24679
|
+
scheduledAt,
|
|
24680
|
+
pendingAt,
|
|
24512
24681
|
});
|
|
24513
24682
|
};
|
|
24514
24683
|
/**
|
|
@@ -24520,8 +24689,16 @@ class StrategyMarkdownService {
|
|
|
24520
24689
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24521
24690
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24522
24691
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24523
|
-
|
|
24524
|
-
|
|
24692
|
+
* @param position - Trade direction: "long" or "short"
|
|
24693
|
+
* @param priceOpen - Entry price for the position
|
|
24694
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24695
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24696
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24697
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24698
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24699
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24700
|
+
*/
|
|
24701
|
+
this.trailingStop = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24525
24702
|
this.loggerService.log("strategyMarkdownService trailingStop", {
|
|
24526
24703
|
symbol,
|
|
24527
24704
|
percentShift,
|
|
@@ -24553,6 +24730,14 @@ class StrategyMarkdownService {
|
|
|
24553
24730
|
currentPrice,
|
|
24554
24731
|
createdAt,
|
|
24555
24732
|
backtest: isBacktest,
|
|
24733
|
+
position,
|
|
24734
|
+
priceOpen,
|
|
24735
|
+
priceTakeProfit,
|
|
24736
|
+
priceStopLoss,
|
|
24737
|
+
originalPriceTakeProfit,
|
|
24738
|
+
originalPriceStopLoss,
|
|
24739
|
+
scheduledAt,
|
|
24740
|
+
pendingAt,
|
|
24556
24741
|
});
|
|
24557
24742
|
};
|
|
24558
24743
|
/**
|
|
@@ -24564,8 +24749,16 @@ class StrategyMarkdownService {
|
|
|
24564
24749
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24565
24750
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24566
24751
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24567
|
-
|
|
24568
|
-
|
|
24752
|
+
* @param position - Trade direction: "long" or "short"
|
|
24753
|
+
* @param priceOpen - Entry price for the position
|
|
24754
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24755
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24756
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24757
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24758
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24759
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24760
|
+
*/
|
|
24761
|
+
this.trailingTake = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24569
24762
|
this.loggerService.log("strategyMarkdownService trailingTake", {
|
|
24570
24763
|
symbol,
|
|
24571
24764
|
percentShift,
|
|
@@ -24597,6 +24790,14 @@ class StrategyMarkdownService {
|
|
|
24597
24790
|
currentPrice,
|
|
24598
24791
|
createdAt,
|
|
24599
24792
|
backtest: isBacktest,
|
|
24793
|
+
position,
|
|
24794
|
+
priceOpen,
|
|
24795
|
+
priceTakeProfit,
|
|
24796
|
+
priceStopLoss,
|
|
24797
|
+
originalPriceTakeProfit,
|
|
24798
|
+
originalPriceStopLoss,
|
|
24799
|
+
scheduledAt,
|
|
24800
|
+
pendingAt,
|
|
24600
24801
|
});
|
|
24601
24802
|
};
|
|
24602
24803
|
/**
|
|
@@ -24607,8 +24808,16 @@ class StrategyMarkdownService {
|
|
|
24607
24808
|
* @param isBacktest - Whether this is a backtest or live trading event
|
|
24608
24809
|
* @param context - Strategy context with strategyName, exchangeName, frameName
|
|
24609
24810
|
* @param timestamp - Timestamp from StrategyCommitContract (execution context time)
|
|
24610
|
-
|
|
24611
|
-
|
|
24811
|
+
* @param position - Trade direction: "long" or "short"
|
|
24812
|
+
* @param priceOpen - Entry price for the position
|
|
24813
|
+
* @param priceTakeProfit - Effective take profit price
|
|
24814
|
+
* @param priceStopLoss - Effective stop loss price
|
|
24815
|
+
* @param originalPriceTakeProfit - Original take profit before trailing
|
|
24816
|
+
* @param originalPriceStopLoss - Original stop loss before trailing
|
|
24817
|
+
* @param scheduledAt - Signal creation timestamp in milliseconds
|
|
24818
|
+
* @param pendingAt - Pending timestamp in milliseconds
|
|
24819
|
+
*/
|
|
24820
|
+
this.breakeven = async (symbol, currentPrice, isBacktest, context, timestamp, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt) => {
|
|
24612
24821
|
this.loggerService.log("strategyMarkdownService breakeven", {
|
|
24613
24822
|
symbol,
|
|
24614
24823
|
currentPrice,
|
|
@@ -24638,6 +24847,14 @@ class StrategyMarkdownService {
|
|
|
24638
24847
|
currentPrice,
|
|
24639
24848
|
createdAt,
|
|
24640
24849
|
backtest: isBacktest,
|
|
24850
|
+
position,
|
|
24851
|
+
priceOpen,
|
|
24852
|
+
priceTakeProfit,
|
|
24853
|
+
priceStopLoss,
|
|
24854
|
+
originalPriceTakeProfit,
|
|
24855
|
+
originalPriceStopLoss,
|
|
24856
|
+
scheduledAt,
|
|
24857
|
+
pendingAt,
|
|
24641
24858
|
});
|
|
24642
24859
|
};
|
|
24643
24860
|
/**
|
|
@@ -24784,35 +25001,35 @@ class StrategyMarkdownService {
|
|
|
24784
25001
|
exchangeName: event.exchangeName,
|
|
24785
25002
|
frameName: event.frameName,
|
|
24786
25003
|
strategyName: event.strategyName,
|
|
24787
|
-
}, event.timestamp));
|
|
25004
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24788
25005
|
const unPartialLoss = strategyCommitSubject
|
|
24789
25006
|
.filter(({ action }) => action === "partial-loss")
|
|
24790
25007
|
.connect(async (event) => await this.partialLoss(event.symbol, event.percentToClose, event.currentPrice, event.backtest, {
|
|
24791
25008
|
exchangeName: event.exchangeName,
|
|
24792
25009
|
frameName: event.frameName,
|
|
24793
25010
|
strategyName: event.strategyName,
|
|
24794
|
-
}, event.timestamp));
|
|
25011
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24795
25012
|
const unTrailingStop = strategyCommitSubject
|
|
24796
25013
|
.filter(({ action }) => action === "trailing-stop")
|
|
24797
25014
|
.connect(async (event) => await this.trailingStop(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
|
|
24798
25015
|
exchangeName: event.exchangeName,
|
|
24799
25016
|
frameName: event.frameName,
|
|
24800
25017
|
strategyName: event.strategyName,
|
|
24801
|
-
}, event.timestamp));
|
|
25018
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24802
25019
|
const unTrailingTake = strategyCommitSubject
|
|
24803
25020
|
.filter(({ action }) => action === "trailing-take")
|
|
24804
25021
|
.connect(async (event) => await this.trailingTake(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
|
|
24805
25022
|
exchangeName: event.exchangeName,
|
|
24806
25023
|
frameName: event.frameName,
|
|
24807
25024
|
strategyName: event.strategyName,
|
|
24808
|
-
}, event.timestamp));
|
|
25025
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24809
25026
|
const unBreakeven = strategyCommitSubject
|
|
24810
25027
|
.filter(({ action }) => action === "breakeven")
|
|
24811
25028
|
.connect(async (event) => await this.breakeven(event.symbol, event.currentPrice, event.backtest, {
|
|
24812
25029
|
exchangeName: event.exchangeName,
|
|
24813
25030
|
frameName: event.frameName,
|
|
24814
25031
|
strategyName: event.strategyName,
|
|
24815
|
-
}, event.timestamp));
|
|
25032
|
+
}, event.timestamp, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt));
|
|
24816
25033
|
const disposeFn = functoolsKit.compose(() => unCancelSchedule(), () => unClosePending(), () => unPartialProfit(), () => unPartialLoss(), () => unTrailingStop(), () => unTrailingTake(), () => unBreakeven());
|
|
24817
25034
|
return () => {
|
|
24818
25035
|
disposeFn();
|
|
@@ -31617,53 +31834,64 @@ class ConstantUtils {
|
|
|
31617
31834
|
const Constant = new ConstantUtils();
|
|
31618
31835
|
|
|
31619
31836
|
const MAX_SIGNALS = 25;
|
|
31620
|
-
const STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "
|
|
31621
|
-
const STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE = "
|
|
31622
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED = "
|
|
31623
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CLOSED = "
|
|
31624
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED = "
|
|
31625
|
-
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CANCELLED = "
|
|
31626
|
-
const STORAGE_BACKTEST_METHOD_NAME_FIND_BY_ID = "
|
|
31627
|
-
const STORAGE_BACKTEST_METHOD_NAME_LIST = "
|
|
31628
|
-
const STORAGE_LIVE_METHOD_NAME_WAIT_FOR_INIT = "
|
|
31629
|
-
const STORAGE_LIVE_METHOD_NAME_UPDATE_STORAGE = "
|
|
31630
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_OPENED = "
|
|
31631
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_CLOSED = "
|
|
31632
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_SCHEDULED = "
|
|
31633
|
-
const STORAGE_LIVE_METHOD_NAME_HANDLE_CANCELLED = "
|
|
31634
|
-
const STORAGE_LIVE_METHOD_NAME_FIND_BY_ID = "
|
|
31635
|
-
const STORAGE_LIVE_METHOD_NAME_LIST = "
|
|
31837
|
+
const STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT = "StoragePersistBacktestUtils.waitForInit";
|
|
31838
|
+
const STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE = "StoragePersistBacktestUtils._updateStorage";
|
|
31839
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED = "StoragePersistBacktestUtils.handleOpened";
|
|
31840
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CLOSED = "StoragePersistBacktestUtils.handleClosed";
|
|
31841
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED = "StoragePersistBacktestUtils.handleScheduled";
|
|
31842
|
+
const STORAGE_BACKTEST_METHOD_NAME_HANDLE_CANCELLED = "StoragePersistBacktestUtils.handleCancelled";
|
|
31843
|
+
const STORAGE_BACKTEST_METHOD_NAME_FIND_BY_ID = "StoragePersistBacktestUtils.findById";
|
|
31844
|
+
const STORAGE_BACKTEST_METHOD_NAME_LIST = "StoragePersistBacktestUtils.list";
|
|
31845
|
+
const STORAGE_LIVE_METHOD_NAME_WAIT_FOR_INIT = "StoragePersistLiveUtils.waitForInit";
|
|
31846
|
+
const STORAGE_LIVE_METHOD_NAME_UPDATE_STORAGE = "StoragePersistLiveUtils._updateStorage";
|
|
31847
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_OPENED = "StoragePersistLiveUtils.handleOpened";
|
|
31848
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_CLOSED = "StoragePersistLiveUtils.handleClosed";
|
|
31849
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_SCHEDULED = "StoragePersistLiveUtils.handleScheduled";
|
|
31850
|
+
const STORAGE_LIVE_METHOD_NAME_HANDLE_CANCELLED = "StoragePersistLiveUtils.handleCancelled";
|
|
31851
|
+
const STORAGE_LIVE_METHOD_NAME_FIND_BY_ID = "StoragePersistLiveUtils.findById";
|
|
31852
|
+
const STORAGE_LIVE_METHOD_NAME_LIST = "StoragePersistLiveUtils.list";
|
|
31853
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_OPENED = "StorageMemoryBacktestUtils.handleOpened";
|
|
31854
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CLOSED = "StorageMemoryBacktestUtils.handleClosed";
|
|
31855
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED = "StorageMemoryBacktestUtils.handleScheduled";
|
|
31856
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CANCELLED = "StorageMemoryBacktestUtils.handleCancelled";
|
|
31857
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_FIND_BY_ID = "StorageMemoryBacktestUtils.findById";
|
|
31858
|
+
const STORAGE_MEMORY_BACKTEST_METHOD_NAME_LIST = "StorageMemoryBacktestUtils.list";
|
|
31859
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_OPENED = "StorageMemoryLiveUtils.handleOpened";
|
|
31860
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CLOSED = "StorageMemoryLiveUtils.handleClosed";
|
|
31861
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_SCHEDULED = "StorageMemoryLiveUtils.handleScheduled";
|
|
31862
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CANCELLED = "StorageMemoryLiveUtils.handleCancelled";
|
|
31863
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_FIND_BY_ID = "StorageMemoryLiveUtils.findById";
|
|
31864
|
+
const STORAGE_MEMORY_LIVE_METHOD_NAME_LIST = "StorageMemoryLiveUtils.list";
|
|
31636
31865
|
const STORAGE_ADAPTER_METHOD_NAME_ENABLE = "StorageAdapter.enable";
|
|
31637
31866
|
const STORAGE_ADAPTER_METHOD_NAME_DISABLE = "StorageAdapter.disable";
|
|
31638
31867
|
const STORAGE_ADAPTER_METHOD_NAME_FIND_SIGNAL_BY_ID = "StorageAdapter.findSignalById";
|
|
31639
31868
|
const STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_BACKTEST = "StorageAdapter.listSignalBacktest";
|
|
31640
31869
|
const STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_LIVE = "StorageAdapter.listSignalLive";
|
|
31870
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER = "StorageBacktestAdapter.useStorageAdapter";
|
|
31871
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY = "StorageBacktestAdapter.useDummy";
|
|
31872
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST = "StorageBacktestAdapter.usePersist";
|
|
31873
|
+
const STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY = "StorageBacktestAdapter.useMemory";
|
|
31874
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER = "StorageLiveAdapter.useStorageAdapter";
|
|
31875
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY = "StorageLiveAdapter.useDummy";
|
|
31876
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST = "StorageLiveAdapter.usePersist";
|
|
31877
|
+
const STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY = "StorageLiveAdapter.useMemory";
|
|
31641
31878
|
/**
|
|
31642
|
-
*
|
|
31643
|
-
*
|
|
31644
|
-
* Stores trading signal history for admin dashboard display during backtesting
|
|
31645
|
-
* with automatic initialization, deduplication, and storage limits.
|
|
31646
|
-
*
|
|
31647
|
-
* @example
|
|
31648
|
-
* ```typescript
|
|
31649
|
-
* import { StorageBacktestUtils } from "./classes/Storage";
|
|
31879
|
+
* Persistent storage adapter for backtest signals.
|
|
31650
31880
|
*
|
|
31651
|
-
*
|
|
31652
|
-
*
|
|
31653
|
-
*
|
|
31654
|
-
*
|
|
31655
|
-
*
|
|
31881
|
+
* Features:
|
|
31882
|
+
* - Persists signals to disk using PersistStorageAdapter
|
|
31883
|
+
* - Lazy initialization with singleshot pattern
|
|
31884
|
+
* - Maintains up to MAX_SIGNALS (25) most recent signals
|
|
31885
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
31886
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31656
31887
|
*
|
|
31657
|
-
*
|
|
31658
|
-
* const signal = await storage.findById("signal-123");
|
|
31659
|
-
* const allSignals = await storage.list();
|
|
31660
|
-
* ```
|
|
31888
|
+
* Use this adapter (default) for backtest signal persistence across sessions.
|
|
31661
31889
|
*/
|
|
31662
|
-
class
|
|
31890
|
+
class StoragePersistBacktestUtils {
|
|
31663
31891
|
constructor() {
|
|
31664
31892
|
/**
|
|
31665
|
-
*
|
|
31666
|
-
*
|
|
31893
|
+
* Singleshot initialization function that loads signals from disk.
|
|
31894
|
+
* Protected by singleshot to ensure one-time execution.
|
|
31667
31895
|
*/
|
|
31668
31896
|
this.waitForInit = functoolsKit.singleshot(async () => {
|
|
31669
31897
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_WAIT_FOR_INIT);
|
|
@@ -31675,9 +31903,8 @@ class StorageBacktestUtils {
|
|
|
31675
31903
|
});
|
|
31676
31904
|
/**
|
|
31677
31905
|
* Handles signal opened event.
|
|
31678
|
-
*
|
|
31679
|
-
* @param tick -
|
|
31680
|
-
* @returns Promise resolving when storage is updated
|
|
31906
|
+
* Updates storage with opened status if not stale.
|
|
31907
|
+
* @param tick - The opened signal tick data
|
|
31681
31908
|
*/
|
|
31682
31909
|
this.handleOpened = async (tick) => {
|
|
31683
31910
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_OPENED, {
|
|
@@ -31699,9 +31926,8 @@ class StorageBacktestUtils {
|
|
|
31699
31926
|
};
|
|
31700
31927
|
/**
|
|
31701
31928
|
* Handles signal closed event.
|
|
31702
|
-
*
|
|
31703
|
-
* @param tick -
|
|
31704
|
-
* @returns Promise resolving when storage is updated
|
|
31929
|
+
* Updates storage with closed status and PnL if not stale.
|
|
31930
|
+
* @param tick - The closed signal tick data
|
|
31705
31931
|
*/
|
|
31706
31932
|
this.handleClosed = async (tick) => {
|
|
31707
31933
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_CLOSED, {
|
|
@@ -31724,9 +31950,8 @@ class StorageBacktestUtils {
|
|
|
31724
31950
|
};
|
|
31725
31951
|
/**
|
|
31726
31952
|
* Handles signal scheduled event.
|
|
31727
|
-
*
|
|
31728
|
-
* @param tick -
|
|
31729
|
-
* @returns Promise resolving when storage is updated
|
|
31953
|
+
* Updates storage with scheduled status if not stale.
|
|
31954
|
+
* @param tick - The scheduled signal tick data
|
|
31730
31955
|
*/
|
|
31731
31956
|
this.handleScheduled = async (tick) => {
|
|
31732
31957
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
@@ -31748,9 +31973,8 @@ class StorageBacktestUtils {
|
|
|
31748
31973
|
};
|
|
31749
31974
|
/**
|
|
31750
31975
|
* Handles signal cancelled event.
|
|
31751
|
-
*
|
|
31752
|
-
* @param tick -
|
|
31753
|
-
* @returns Promise resolving when storage is updated
|
|
31976
|
+
* Updates storage with cancelled status if not stale.
|
|
31977
|
+
* @param tick - The cancelled signal tick data
|
|
31754
31978
|
*/
|
|
31755
31979
|
this.handleCancelled = async (tick) => {
|
|
31756
31980
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_HANDLE_CANCELLED, {
|
|
@@ -31771,10 +31995,9 @@ class StorageBacktestUtils {
|
|
|
31771
31995
|
await this._updateStorage();
|
|
31772
31996
|
};
|
|
31773
31997
|
/**
|
|
31774
|
-
* Finds a signal by its
|
|
31775
|
-
*
|
|
31776
|
-
* @
|
|
31777
|
-
* @returns Promise resolving to signal row or null if not found
|
|
31998
|
+
* Finds a signal by its ID.
|
|
31999
|
+
* @param id - The signal ID to search for
|
|
32000
|
+
* @returns The signal row or null if not found
|
|
31778
32001
|
*/
|
|
31779
32002
|
this.findById = async (id) => {
|
|
31780
32003
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_FIND_BY_ID, { id });
|
|
@@ -31782,9 +32005,8 @@ class StorageBacktestUtils {
|
|
|
31782
32005
|
return this._signals.get(id) ?? null;
|
|
31783
32006
|
};
|
|
31784
32007
|
/**
|
|
31785
|
-
* Lists all stored
|
|
31786
|
-
*
|
|
31787
|
-
* @returns Promise resolving to array of signal rows
|
|
32008
|
+
* Lists all stored signals.
|
|
32009
|
+
* @returns Array of all signal rows
|
|
31788
32010
|
*/
|
|
31789
32011
|
this.list = async () => {
|
|
31790
32012
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_LIST);
|
|
@@ -31793,15 +32015,14 @@ class StorageBacktestUtils {
|
|
|
31793
32015
|
};
|
|
31794
32016
|
}
|
|
31795
32017
|
/**
|
|
31796
|
-
* Persists current signal
|
|
31797
|
-
* Sorts by priority and
|
|
31798
|
-
*
|
|
31799
|
-
* @throws Error if storage not initialized
|
|
32018
|
+
* Persists the current signal map to disk storage.
|
|
32019
|
+
* Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
|
|
32020
|
+
* @throws Error if not initialized
|
|
31800
32021
|
*/
|
|
31801
32022
|
async _updateStorage() {
|
|
31802
32023
|
bt.loggerService.info(STORAGE_BACKTEST_METHOD_NAME_UPDATE_STORAGE);
|
|
31803
32024
|
if (!this._signals) {
|
|
31804
|
-
throw new Error("
|
|
32025
|
+
throw new Error("StoragePersistBacktestUtils not initialized. Call waitForInit first.");
|
|
31805
32026
|
}
|
|
31806
32027
|
const signalList = Array.from(this._signals.values());
|
|
31807
32028
|
signalList.sort((a, b) => a.priority - b.priority);
|
|
@@ -31809,31 +32030,190 @@ class StorageBacktestUtils {
|
|
|
31809
32030
|
}
|
|
31810
32031
|
}
|
|
31811
32032
|
/**
|
|
31812
|
-
*
|
|
32033
|
+
* In-memory storage adapter for backtest signals.
|
|
31813
32034
|
*
|
|
31814
|
-
*
|
|
31815
|
-
*
|
|
32035
|
+
* Features:
|
|
32036
|
+
* - Stores signals in memory only (no persistence)
|
|
32037
|
+
* - Fast read/write operations
|
|
32038
|
+
* - Data is lost when application restarts
|
|
32039
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
32040
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31816
32041
|
*
|
|
31817
|
-
*
|
|
31818
|
-
|
|
31819
|
-
|
|
32042
|
+
* Use this adapter for testing or when persistence is not required.
|
|
32043
|
+
*/
|
|
32044
|
+
class StorageMemoryBacktestUtils {
|
|
32045
|
+
constructor() {
|
|
32046
|
+
/** Map of signal IDs to signal rows */
|
|
32047
|
+
this._signals = new Map();
|
|
32048
|
+
/**
|
|
32049
|
+
* Handles signal opened event.
|
|
32050
|
+
* Updates in-memory storage with opened status if not stale.
|
|
32051
|
+
* @param tick - The opened signal tick data
|
|
32052
|
+
*/
|
|
32053
|
+
this.handleOpened = async (tick) => {
|
|
32054
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_OPENED, {
|
|
32055
|
+
signalId: tick.signal.id,
|
|
32056
|
+
});
|
|
32057
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32058
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32059
|
+
return;
|
|
32060
|
+
}
|
|
32061
|
+
this._signals.set(tick.signal.id, {
|
|
32062
|
+
...tick.signal,
|
|
32063
|
+
status: "opened",
|
|
32064
|
+
priority: Date.now(),
|
|
32065
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32066
|
+
updatedAt: tick.createdAt,
|
|
32067
|
+
});
|
|
32068
|
+
};
|
|
32069
|
+
/**
|
|
32070
|
+
* Handles signal closed event.
|
|
32071
|
+
* Updates in-memory storage with closed status and PnL if not stale.
|
|
32072
|
+
* @param tick - The closed signal tick data
|
|
32073
|
+
*/
|
|
32074
|
+
this.handleClosed = async (tick) => {
|
|
32075
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CLOSED, {
|
|
32076
|
+
signalId: tick.signal.id,
|
|
32077
|
+
});
|
|
32078
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32079
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32080
|
+
return;
|
|
32081
|
+
}
|
|
32082
|
+
this._signals.set(tick.signal.id, {
|
|
32083
|
+
...tick.signal,
|
|
32084
|
+
status: "closed",
|
|
32085
|
+
priority: Date.now(),
|
|
32086
|
+
pnl: tick.pnl,
|
|
32087
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32088
|
+
updatedAt: tick.createdAt,
|
|
32089
|
+
});
|
|
32090
|
+
};
|
|
32091
|
+
/**
|
|
32092
|
+
* Handles signal scheduled event.
|
|
32093
|
+
* Updates in-memory storage with scheduled status if not stale.
|
|
32094
|
+
* @param tick - The scheduled signal tick data
|
|
32095
|
+
*/
|
|
32096
|
+
this.handleScheduled = async (tick) => {
|
|
32097
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
32098
|
+
signalId: tick.signal.id,
|
|
32099
|
+
});
|
|
32100
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32101
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32102
|
+
return;
|
|
32103
|
+
}
|
|
32104
|
+
this._signals.set(tick.signal.id, {
|
|
32105
|
+
...tick.signal,
|
|
32106
|
+
status: "scheduled",
|
|
32107
|
+
priority: Date.now(),
|
|
32108
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32109
|
+
updatedAt: tick.createdAt,
|
|
32110
|
+
});
|
|
32111
|
+
};
|
|
32112
|
+
/**
|
|
32113
|
+
* Handles signal cancelled event.
|
|
32114
|
+
* Updates in-memory storage with cancelled status if not stale.
|
|
32115
|
+
* @param tick - The cancelled signal tick data
|
|
32116
|
+
*/
|
|
32117
|
+
this.handleCancelled = async (tick) => {
|
|
32118
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_HANDLE_CANCELLED, {
|
|
32119
|
+
signalId: tick.signal.id,
|
|
32120
|
+
});
|
|
32121
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32122
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32123
|
+
return;
|
|
32124
|
+
}
|
|
32125
|
+
this._signals.set(tick.signal.id, {
|
|
32126
|
+
...tick.signal,
|
|
32127
|
+
status: "cancelled",
|
|
32128
|
+
priority: Date.now(),
|
|
32129
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32130
|
+
updatedAt: tick.createdAt,
|
|
32131
|
+
});
|
|
32132
|
+
};
|
|
32133
|
+
/**
|
|
32134
|
+
* Finds a signal by its ID.
|
|
32135
|
+
* @param id - The signal ID to search for
|
|
32136
|
+
* @returns The signal row or null if not found
|
|
32137
|
+
*/
|
|
32138
|
+
this.findById = async (id) => {
|
|
32139
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_FIND_BY_ID, { id });
|
|
32140
|
+
return this._signals.get(id) ?? null;
|
|
32141
|
+
};
|
|
32142
|
+
/**
|
|
32143
|
+
* Lists all stored signals.
|
|
32144
|
+
* @returns Array of all signal rows
|
|
32145
|
+
*/
|
|
32146
|
+
this.list = async () => {
|
|
32147
|
+
bt.loggerService.info(STORAGE_MEMORY_BACKTEST_METHOD_NAME_LIST);
|
|
32148
|
+
return Array.from(this._signals.values());
|
|
32149
|
+
};
|
|
32150
|
+
}
|
|
32151
|
+
}
|
|
32152
|
+
/**
|
|
32153
|
+
* Dummy storage adapter for backtest signals that discards all writes.
|
|
32154
|
+
*
|
|
32155
|
+
* Features:
|
|
32156
|
+
* - No-op implementation for all methods
|
|
32157
|
+
* - findById always returns null
|
|
32158
|
+
* - list always returns empty array
|
|
31820
32159
|
*
|
|
31821
|
-
*
|
|
32160
|
+
* Use this adapter to disable backtest signal storage completely.
|
|
32161
|
+
*/
|
|
32162
|
+
class StorageDummyBacktestUtils {
|
|
32163
|
+
constructor() {
|
|
32164
|
+
/**
|
|
32165
|
+
* No-op handler for signal opened event.
|
|
32166
|
+
*/
|
|
32167
|
+
this.handleOpened = async () => {
|
|
32168
|
+
};
|
|
32169
|
+
/**
|
|
32170
|
+
* No-op handler for signal closed event.
|
|
32171
|
+
*/
|
|
32172
|
+
this.handleClosed = async () => {
|
|
32173
|
+
};
|
|
32174
|
+
/**
|
|
32175
|
+
* No-op handler for signal scheduled event.
|
|
32176
|
+
*/
|
|
32177
|
+
this.handleScheduled = async () => {
|
|
32178
|
+
};
|
|
32179
|
+
/**
|
|
32180
|
+
* No-op handler for signal cancelled event.
|
|
32181
|
+
*/
|
|
32182
|
+
this.handleCancelled = async () => {
|
|
32183
|
+
};
|
|
32184
|
+
/**
|
|
32185
|
+
* Always returns null (no storage).
|
|
32186
|
+
* @returns null
|
|
32187
|
+
*/
|
|
32188
|
+
this.findById = async () => {
|
|
32189
|
+
return null;
|
|
32190
|
+
};
|
|
32191
|
+
/**
|
|
32192
|
+
* Always returns empty array (no storage).
|
|
32193
|
+
* @returns Empty array
|
|
32194
|
+
*/
|
|
32195
|
+
this.list = async () => {
|
|
32196
|
+
return [];
|
|
32197
|
+
};
|
|
32198
|
+
}
|
|
32199
|
+
}
|
|
32200
|
+
/**
|
|
32201
|
+
* Persistent storage adapter for live trading signals.
|
|
31822
32202
|
*
|
|
31823
|
-
*
|
|
31824
|
-
*
|
|
31825
|
-
*
|
|
32203
|
+
* Features:
|
|
32204
|
+
* - Persists signals to disk using PersistStorageAdapter
|
|
32205
|
+
* - Lazy initialization with singleshot pattern
|
|
32206
|
+
* - Maintains up to MAX_SIGNALS (25) most recent signals
|
|
32207
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
32208
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31826
32209
|
*
|
|
31827
|
-
*
|
|
31828
|
-
* const signal = await storage.findById("signal-123");
|
|
31829
|
-
* const allSignals = await storage.list();
|
|
31830
|
-
* ```
|
|
32210
|
+
* Use this adapter (default) for live signal persistence across sessions.
|
|
31831
32211
|
*/
|
|
31832
|
-
class
|
|
32212
|
+
class StoragePersistLiveUtils {
|
|
31833
32213
|
constructor() {
|
|
31834
32214
|
/**
|
|
31835
|
-
*
|
|
31836
|
-
*
|
|
32215
|
+
* Singleshot initialization function that loads signals from disk.
|
|
32216
|
+
* Protected by singleshot to ensure one-time execution.
|
|
31837
32217
|
*/
|
|
31838
32218
|
this.waitForInit = functoolsKit.singleshot(async () => {
|
|
31839
32219
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_WAIT_FOR_INIT);
|
|
@@ -31845,9 +32225,8 @@ class StorageLiveUtils {
|
|
|
31845
32225
|
});
|
|
31846
32226
|
/**
|
|
31847
32227
|
* Handles signal opened event.
|
|
31848
|
-
*
|
|
31849
|
-
* @param tick -
|
|
31850
|
-
* @returns Promise resolving when history is updated
|
|
32228
|
+
* Updates storage with opened status if not stale.
|
|
32229
|
+
* @param tick - The opened signal tick data
|
|
31851
32230
|
*/
|
|
31852
32231
|
this.handleOpened = async (tick) => {
|
|
31853
32232
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_OPENED, {
|
|
@@ -31869,9 +32248,8 @@ class StorageLiveUtils {
|
|
|
31869
32248
|
};
|
|
31870
32249
|
/**
|
|
31871
32250
|
* Handles signal closed event.
|
|
31872
|
-
*
|
|
31873
|
-
* @param tick -
|
|
31874
|
-
* @returns Promise resolving when history is updated
|
|
32251
|
+
* Updates storage with closed status and PnL if not stale.
|
|
32252
|
+
* @param tick - The closed signal tick data
|
|
31875
32253
|
*/
|
|
31876
32254
|
this.handleClosed = async (tick) => {
|
|
31877
32255
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_CLOSED, {
|
|
@@ -31894,9 +32272,8 @@ class StorageLiveUtils {
|
|
|
31894
32272
|
};
|
|
31895
32273
|
/**
|
|
31896
32274
|
* Handles signal scheduled event.
|
|
31897
|
-
*
|
|
31898
|
-
* @param tick -
|
|
31899
|
-
* @returns Promise resolving when history is updated
|
|
32275
|
+
* Updates storage with scheduled status if not stale.
|
|
32276
|
+
* @param tick - The scheduled signal tick data
|
|
31900
32277
|
*/
|
|
31901
32278
|
this.handleScheduled = async (tick) => {
|
|
31902
32279
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
@@ -31918,9 +32295,8 @@ class StorageLiveUtils {
|
|
|
31918
32295
|
};
|
|
31919
32296
|
/**
|
|
31920
32297
|
* Handles signal cancelled event.
|
|
31921
|
-
*
|
|
31922
|
-
* @param tick -
|
|
31923
|
-
* @returns Promise resolving when history is updated
|
|
32298
|
+
* Updates storage with cancelled status if not stale.
|
|
32299
|
+
* @param tick - The cancelled signal tick data
|
|
31924
32300
|
*/
|
|
31925
32301
|
this.handleCancelled = async (tick) => {
|
|
31926
32302
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_HANDLE_CANCELLED, {
|
|
@@ -31941,10 +32317,9 @@ class StorageLiveUtils {
|
|
|
31941
32317
|
await this._updateStorage();
|
|
31942
32318
|
};
|
|
31943
32319
|
/**
|
|
31944
|
-
* Finds a signal by its
|
|
31945
|
-
*
|
|
31946
|
-
* @
|
|
31947
|
-
* @returns Promise resolving to signal row or null if not found
|
|
32320
|
+
* Finds a signal by its ID.
|
|
32321
|
+
* @param id - The signal ID to search for
|
|
32322
|
+
* @returns The signal row or null if not found
|
|
31948
32323
|
*/
|
|
31949
32324
|
this.findById = async (id) => {
|
|
31950
32325
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_FIND_BY_ID, { id });
|
|
@@ -31952,9 +32327,8 @@ class StorageLiveUtils {
|
|
|
31952
32327
|
return this._signals.get(id) ?? null;
|
|
31953
32328
|
};
|
|
31954
32329
|
/**
|
|
31955
|
-
* Lists all stored
|
|
31956
|
-
*
|
|
31957
|
-
* @returns Promise resolving to array of signal rows
|
|
32330
|
+
* Lists all stored signals.
|
|
32331
|
+
* @returns Array of all signal rows
|
|
31958
32332
|
*/
|
|
31959
32333
|
this.list = async () => {
|
|
31960
32334
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_LIST);
|
|
@@ -31963,15 +32337,14 @@ class StorageLiveUtils {
|
|
|
31963
32337
|
};
|
|
31964
32338
|
}
|
|
31965
32339
|
/**
|
|
31966
|
-
* Persists current signal
|
|
31967
|
-
* Sorts by priority and
|
|
31968
|
-
*
|
|
31969
|
-
* @throws Error if storage not initialized
|
|
32340
|
+
* Persists the current signal map to disk storage.
|
|
32341
|
+
* Sorts signals by priority and keeps only the most recent MAX_SIGNALS.
|
|
32342
|
+
* @throws Error if not initialized
|
|
31970
32343
|
*/
|
|
31971
32344
|
async _updateStorage() {
|
|
31972
32345
|
bt.loggerService.info(STORAGE_LIVE_METHOD_NAME_UPDATE_STORAGE);
|
|
31973
32346
|
if (!this._signals) {
|
|
31974
|
-
throw new Error("
|
|
32347
|
+
throw new Error("StoragePersistLiveUtils not initialized. Call waitForInit first.");
|
|
31975
32348
|
}
|
|
31976
32349
|
const signalList = Array.from(this._signals.values());
|
|
31977
32350
|
signalList.sort((a, b) => a.priority - b.priority);
|
|
@@ -31979,36 +32352,385 @@ class StorageLiveUtils {
|
|
|
31979
32352
|
}
|
|
31980
32353
|
}
|
|
31981
32354
|
/**
|
|
31982
|
-
*
|
|
32355
|
+
* In-memory storage adapter for live trading signals.
|
|
31983
32356
|
*
|
|
31984
|
-
*
|
|
31985
|
-
*
|
|
31986
|
-
*
|
|
32357
|
+
* Features:
|
|
32358
|
+
* - Stores signals in memory only (no persistence)
|
|
32359
|
+
* - Fast read/write operations
|
|
32360
|
+
* - Data is lost when application restarts
|
|
32361
|
+
* - Handles signal lifecycle events (opened, closed, scheduled, cancelled)
|
|
32362
|
+
* - Prevents duplicate updates based on timestamp comparison
|
|
31987
32363
|
*
|
|
31988
|
-
*
|
|
31989
|
-
|
|
31990
|
-
|
|
32364
|
+
* Use this adapter for testing or when persistence is not required.
|
|
32365
|
+
*/
|
|
32366
|
+
class StorageMemoryLiveUtils {
|
|
32367
|
+
constructor() {
|
|
32368
|
+
/** Map of signal IDs to signal rows */
|
|
32369
|
+
this._signals = new Map();
|
|
32370
|
+
/**
|
|
32371
|
+
* Handles signal opened event.
|
|
32372
|
+
* Updates in-memory storage with opened status if not stale.
|
|
32373
|
+
* @param tick - The opened signal tick data
|
|
32374
|
+
*/
|
|
32375
|
+
this.handleOpened = async (tick) => {
|
|
32376
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_OPENED, {
|
|
32377
|
+
signalId: tick.signal.id,
|
|
32378
|
+
});
|
|
32379
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32380
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32381
|
+
return;
|
|
32382
|
+
}
|
|
32383
|
+
this._signals.set(tick.signal.id, {
|
|
32384
|
+
...tick.signal,
|
|
32385
|
+
status: "opened",
|
|
32386
|
+
priority: Date.now(),
|
|
32387
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32388
|
+
updatedAt: tick.createdAt,
|
|
32389
|
+
});
|
|
32390
|
+
};
|
|
32391
|
+
/**
|
|
32392
|
+
* Handles signal closed event.
|
|
32393
|
+
* Updates in-memory storage with closed status and PnL if not stale.
|
|
32394
|
+
* @param tick - The closed signal tick data
|
|
32395
|
+
*/
|
|
32396
|
+
this.handleClosed = async (tick) => {
|
|
32397
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CLOSED, {
|
|
32398
|
+
signalId: tick.signal.id,
|
|
32399
|
+
});
|
|
32400
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32401
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32402
|
+
return;
|
|
32403
|
+
}
|
|
32404
|
+
this._signals.set(tick.signal.id, {
|
|
32405
|
+
...tick.signal,
|
|
32406
|
+
status: "closed",
|
|
32407
|
+
priority: Date.now(),
|
|
32408
|
+
pnl: tick.pnl,
|
|
32409
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32410
|
+
updatedAt: tick.createdAt,
|
|
32411
|
+
});
|
|
32412
|
+
};
|
|
32413
|
+
/**
|
|
32414
|
+
* Handles signal scheduled event.
|
|
32415
|
+
* Updates in-memory storage with scheduled status if not stale.
|
|
32416
|
+
* @param tick - The scheduled signal tick data
|
|
32417
|
+
*/
|
|
32418
|
+
this.handleScheduled = async (tick) => {
|
|
32419
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_SCHEDULED, {
|
|
32420
|
+
signalId: tick.signal.id,
|
|
32421
|
+
});
|
|
32422
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32423
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32424
|
+
return;
|
|
32425
|
+
}
|
|
32426
|
+
this._signals.set(tick.signal.id, {
|
|
32427
|
+
...tick.signal,
|
|
32428
|
+
status: "scheduled",
|
|
32429
|
+
priority: Date.now(),
|
|
32430
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32431
|
+
updatedAt: tick.createdAt,
|
|
32432
|
+
});
|
|
32433
|
+
};
|
|
32434
|
+
/**
|
|
32435
|
+
* Handles signal cancelled event.
|
|
32436
|
+
* Updates in-memory storage with cancelled status if not stale.
|
|
32437
|
+
* @param tick - The cancelled signal tick data
|
|
32438
|
+
*/
|
|
32439
|
+
this.handleCancelled = async (tick) => {
|
|
32440
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_HANDLE_CANCELLED, {
|
|
32441
|
+
signalId: tick.signal.id,
|
|
32442
|
+
});
|
|
32443
|
+
const lastStorage = this._signals.get(tick.signal.id);
|
|
32444
|
+
if (lastStorage && lastStorage.updatedAt > tick.createdAt) {
|
|
32445
|
+
return;
|
|
32446
|
+
}
|
|
32447
|
+
this._signals.set(tick.signal.id, {
|
|
32448
|
+
...tick.signal,
|
|
32449
|
+
status: "cancelled",
|
|
32450
|
+
priority: Date.now(),
|
|
32451
|
+
createdAt: lastStorage ? lastStorage.createdAt : tick.createdAt,
|
|
32452
|
+
updatedAt: tick.createdAt,
|
|
32453
|
+
});
|
|
32454
|
+
};
|
|
32455
|
+
/**
|
|
32456
|
+
* Finds a signal by its ID.
|
|
32457
|
+
* @param id - The signal ID to search for
|
|
32458
|
+
* @returns The signal row or null if not found
|
|
32459
|
+
*/
|
|
32460
|
+
this.findById = async (id) => {
|
|
32461
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_FIND_BY_ID, { id });
|
|
32462
|
+
return this._signals.get(id) ?? null;
|
|
32463
|
+
};
|
|
32464
|
+
/**
|
|
32465
|
+
* Lists all stored signals.
|
|
32466
|
+
* @returns Array of all signal rows
|
|
32467
|
+
*/
|
|
32468
|
+
this.list = async () => {
|
|
32469
|
+
bt.loggerService.info(STORAGE_MEMORY_LIVE_METHOD_NAME_LIST);
|
|
32470
|
+
return Array.from(this._signals.values());
|
|
32471
|
+
};
|
|
32472
|
+
}
|
|
32473
|
+
}
|
|
32474
|
+
/**
|
|
32475
|
+
* Dummy storage adapter for live trading signals that discards all writes.
|
|
31991
32476
|
*
|
|
31992
|
-
*
|
|
31993
|
-
*
|
|
32477
|
+
* Features:
|
|
32478
|
+
* - No-op implementation for all methods
|
|
32479
|
+
* - findById always returns null
|
|
32480
|
+
* - list always returns empty array
|
|
31994
32481
|
*
|
|
31995
|
-
*
|
|
31996
|
-
|
|
31997
|
-
|
|
31998
|
-
|
|
32482
|
+
* Use this adapter to disable live signal storage completely.
|
|
32483
|
+
*/
|
|
32484
|
+
class StorageDummyLiveUtils {
|
|
32485
|
+
constructor() {
|
|
32486
|
+
/**
|
|
32487
|
+
* No-op handler for signal opened event.
|
|
32488
|
+
*/
|
|
32489
|
+
this.handleOpened = async () => {
|
|
32490
|
+
};
|
|
32491
|
+
/**
|
|
32492
|
+
* No-op handler for signal closed event.
|
|
32493
|
+
*/
|
|
32494
|
+
this.handleClosed = async () => {
|
|
32495
|
+
};
|
|
32496
|
+
/**
|
|
32497
|
+
* No-op handler for signal scheduled event.
|
|
32498
|
+
*/
|
|
32499
|
+
this.handleScheduled = async () => {
|
|
32500
|
+
};
|
|
32501
|
+
/**
|
|
32502
|
+
* No-op handler for signal cancelled event.
|
|
32503
|
+
*/
|
|
32504
|
+
this.handleCancelled = async () => {
|
|
32505
|
+
};
|
|
32506
|
+
/**
|
|
32507
|
+
* Always returns null (no storage).
|
|
32508
|
+
* @returns null
|
|
32509
|
+
*/
|
|
32510
|
+
this.findById = async () => {
|
|
32511
|
+
return null;
|
|
32512
|
+
};
|
|
32513
|
+
/**
|
|
32514
|
+
* Always returns empty array (no storage).
|
|
32515
|
+
* @returns Empty array
|
|
32516
|
+
*/
|
|
32517
|
+
this.list = async () => {
|
|
32518
|
+
return [];
|
|
32519
|
+
};
|
|
32520
|
+
}
|
|
32521
|
+
}
|
|
32522
|
+
/**
|
|
32523
|
+
* Backtest storage adapter with pluggable storage backend.
|
|
31999
32524
|
*
|
|
32000
|
-
*
|
|
32001
|
-
*
|
|
32002
|
-
*
|
|
32525
|
+
* Features:
|
|
32526
|
+
* - Adapter pattern for swappable storage implementations
|
|
32527
|
+
* - Default adapter: StoragePersistBacktestUtils (persistent storage)
|
|
32528
|
+
* - Alternative adapters: StorageMemoryBacktestUtils, StorageDummyBacktestUtils
|
|
32529
|
+
* - Convenience methods: usePersist(), useMemory(), useDummy()
|
|
32530
|
+
*/
|
|
32531
|
+
class StorageBacktestAdapter {
|
|
32532
|
+
constructor() {
|
|
32533
|
+
/** Internal storage utils instance */
|
|
32534
|
+
this._signalBacktestUtils = new StorageMemoryBacktestUtils();
|
|
32535
|
+
/**
|
|
32536
|
+
* Handles signal opened event.
|
|
32537
|
+
* Proxies call to the underlying storage adapter.
|
|
32538
|
+
* @param tick - The opened signal tick data
|
|
32539
|
+
*/
|
|
32540
|
+
this.handleOpened = async (tick) => {
|
|
32541
|
+
return await this._signalBacktestUtils.handleOpened(tick);
|
|
32542
|
+
};
|
|
32543
|
+
/**
|
|
32544
|
+
* Handles signal closed event.
|
|
32545
|
+
* Proxies call to the underlying storage adapter.
|
|
32546
|
+
* @param tick - The closed signal tick data
|
|
32547
|
+
*/
|
|
32548
|
+
this.handleClosed = async (tick) => {
|
|
32549
|
+
return await this._signalBacktestUtils.handleClosed(tick);
|
|
32550
|
+
};
|
|
32551
|
+
/**
|
|
32552
|
+
* Handles signal scheduled event.
|
|
32553
|
+
* Proxies call to the underlying storage adapter.
|
|
32554
|
+
* @param tick - The scheduled signal tick data
|
|
32555
|
+
*/
|
|
32556
|
+
this.handleScheduled = async (tick) => {
|
|
32557
|
+
return await this._signalBacktestUtils.handleScheduled(tick);
|
|
32558
|
+
};
|
|
32559
|
+
/**
|
|
32560
|
+
* Handles signal cancelled event.
|
|
32561
|
+
* Proxies call to the underlying storage adapter.
|
|
32562
|
+
* @param tick - The cancelled signal tick data
|
|
32563
|
+
*/
|
|
32564
|
+
this.handleCancelled = async (tick) => {
|
|
32565
|
+
return await this._signalBacktestUtils.handleCancelled(tick);
|
|
32566
|
+
};
|
|
32567
|
+
/**
|
|
32568
|
+
* Finds a signal by its ID.
|
|
32569
|
+
* Proxies call to the underlying storage adapter.
|
|
32570
|
+
* @param id - The signal ID to search for
|
|
32571
|
+
* @returns The signal row or null if not found
|
|
32572
|
+
*/
|
|
32573
|
+
this.findById = async (id) => {
|
|
32574
|
+
return await this._signalBacktestUtils.findById(id);
|
|
32575
|
+
};
|
|
32576
|
+
/**
|
|
32577
|
+
* Lists all stored signals.
|
|
32578
|
+
* Proxies call to the underlying storage adapter.
|
|
32579
|
+
* @returns Array of all signal rows
|
|
32580
|
+
*/
|
|
32581
|
+
this.list = async () => {
|
|
32582
|
+
return await this._signalBacktestUtils.list();
|
|
32583
|
+
};
|
|
32584
|
+
/**
|
|
32585
|
+
* Sets the storage adapter constructor.
|
|
32586
|
+
* All future storage operations will use this adapter.
|
|
32587
|
+
*
|
|
32588
|
+
* @param Ctor - Constructor for storage adapter
|
|
32589
|
+
*/
|
|
32590
|
+
this.useStorageAdapter = (Ctor) => {
|
|
32591
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
32592
|
+
this._signalBacktestUtils = Reflect.construct(Ctor, []);
|
|
32593
|
+
};
|
|
32594
|
+
/**
|
|
32595
|
+
* Switches to dummy storage adapter.
|
|
32596
|
+
* All future storage writes will be no-ops.
|
|
32597
|
+
*/
|
|
32598
|
+
this.useDummy = () => {
|
|
32599
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
32600
|
+
this._signalBacktestUtils = new StorageDummyBacktestUtils();
|
|
32601
|
+
};
|
|
32602
|
+
/**
|
|
32603
|
+
* Switches to persistent storage adapter (default).
|
|
32604
|
+
* Signals will be persisted to disk.
|
|
32605
|
+
*/
|
|
32606
|
+
this.usePersist = () => {
|
|
32607
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
32608
|
+
this._signalBacktestUtils = new StoragePersistBacktestUtils();
|
|
32609
|
+
};
|
|
32610
|
+
/**
|
|
32611
|
+
* Switches to in-memory storage adapter.
|
|
32612
|
+
* Signals will be stored in memory only.
|
|
32613
|
+
*/
|
|
32614
|
+
this.useMemory = () => {
|
|
32615
|
+
bt.loggerService.info(STORAGE_BACKTEST_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
32616
|
+
this._signalBacktestUtils = new StorageMemoryBacktestUtils();
|
|
32617
|
+
};
|
|
32618
|
+
}
|
|
32619
|
+
}
|
|
32620
|
+
/**
|
|
32621
|
+
* Live trading storage adapter with pluggable storage backend.
|
|
32622
|
+
*
|
|
32623
|
+
* Features:
|
|
32624
|
+
* - Adapter pattern for swappable storage implementations
|
|
32625
|
+
* - Default adapter: StoragePersistLiveUtils (persistent storage)
|
|
32626
|
+
* - Alternative adapters: StorageMemoryLiveUtils, StorageDummyLiveUtils
|
|
32627
|
+
* - Convenience methods: usePersist(), useMemory(), useDummy()
|
|
32628
|
+
*/
|
|
32629
|
+
class StorageLiveAdapter {
|
|
32630
|
+
constructor() {
|
|
32631
|
+
/** Internal storage utils instance */
|
|
32632
|
+
this._signalLiveUtils = new StoragePersistLiveUtils();
|
|
32633
|
+
/**
|
|
32634
|
+
* Handles signal opened event.
|
|
32635
|
+
* Proxies call to the underlying storage adapter.
|
|
32636
|
+
* @param tick - The opened signal tick data
|
|
32637
|
+
*/
|
|
32638
|
+
this.handleOpened = async (tick) => {
|
|
32639
|
+
return await this._signalLiveUtils.handleOpened(tick);
|
|
32640
|
+
};
|
|
32641
|
+
/**
|
|
32642
|
+
* Handles signal closed event.
|
|
32643
|
+
* Proxies call to the underlying storage adapter.
|
|
32644
|
+
* @param tick - The closed signal tick data
|
|
32645
|
+
*/
|
|
32646
|
+
this.handleClosed = async (tick) => {
|
|
32647
|
+
return await this._signalLiveUtils.handleClosed(tick);
|
|
32648
|
+
};
|
|
32649
|
+
/**
|
|
32650
|
+
* Handles signal scheduled event.
|
|
32651
|
+
* Proxies call to the underlying storage adapter.
|
|
32652
|
+
* @param tick - The scheduled signal tick data
|
|
32653
|
+
*/
|
|
32654
|
+
this.handleScheduled = async (tick) => {
|
|
32655
|
+
return await this._signalLiveUtils.handleScheduled(tick);
|
|
32656
|
+
};
|
|
32657
|
+
/**
|
|
32658
|
+
* Handles signal cancelled event.
|
|
32659
|
+
* Proxies call to the underlying storage adapter.
|
|
32660
|
+
* @param tick - The cancelled signal tick data
|
|
32661
|
+
*/
|
|
32662
|
+
this.handleCancelled = async (tick) => {
|
|
32663
|
+
return await this._signalLiveUtils.handleCancelled(tick);
|
|
32664
|
+
};
|
|
32665
|
+
/**
|
|
32666
|
+
* Finds a signal by its ID.
|
|
32667
|
+
* Proxies call to the underlying storage adapter.
|
|
32668
|
+
* @param id - The signal ID to search for
|
|
32669
|
+
* @returns The signal row or null if not found
|
|
32670
|
+
*/
|
|
32671
|
+
this.findById = async (id) => {
|
|
32672
|
+
return await this._signalLiveUtils.findById(id);
|
|
32673
|
+
};
|
|
32674
|
+
/**
|
|
32675
|
+
* Lists all stored signals.
|
|
32676
|
+
* Proxies call to the underlying storage adapter.
|
|
32677
|
+
* @returns Array of all signal rows
|
|
32678
|
+
*/
|
|
32679
|
+
this.list = async () => {
|
|
32680
|
+
return await this._signalLiveUtils.list();
|
|
32681
|
+
};
|
|
32682
|
+
/**
|
|
32683
|
+
* Sets the storage adapter constructor.
|
|
32684
|
+
* All future storage operations will use this adapter.
|
|
32685
|
+
*
|
|
32686
|
+
* @param Ctor - Constructor for storage adapter
|
|
32687
|
+
*/
|
|
32688
|
+
this.useStorageAdapter = (Ctor) => {
|
|
32689
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_ADAPTER);
|
|
32690
|
+
this._signalLiveUtils = Reflect.construct(Ctor, []);
|
|
32691
|
+
};
|
|
32692
|
+
/**
|
|
32693
|
+
* Switches to dummy storage adapter.
|
|
32694
|
+
* All future storage writes will be no-ops.
|
|
32695
|
+
*/
|
|
32696
|
+
this.useDummy = () => {
|
|
32697
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
32698
|
+
this._signalLiveUtils = new StorageDummyLiveUtils();
|
|
32699
|
+
};
|
|
32700
|
+
/**
|
|
32701
|
+
* Switches to persistent storage adapter (default).
|
|
32702
|
+
* Signals will be persisted to disk.
|
|
32703
|
+
*/
|
|
32704
|
+
this.usePersist = () => {
|
|
32705
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_PERSIST);
|
|
32706
|
+
this._signalLiveUtils = new StoragePersistLiveUtils();
|
|
32707
|
+
};
|
|
32708
|
+
/**
|
|
32709
|
+
* Switches to in-memory storage adapter.
|
|
32710
|
+
* Signals will be stored in memory only.
|
|
32711
|
+
*/
|
|
32712
|
+
this.useMemory = () => {
|
|
32713
|
+
bt.loggerService.info(STORAGE_LIVE_ADAPTER_METHOD_NAME_USE_MEMORY);
|
|
32714
|
+
this._signalLiveUtils = new StorageMemoryLiveUtils();
|
|
32715
|
+
};
|
|
32716
|
+
}
|
|
32717
|
+
}
|
|
32718
|
+
/**
|
|
32719
|
+
* Main storage adapter that manages both backtest and live signal storage.
|
|
32720
|
+
*
|
|
32721
|
+
* Features:
|
|
32722
|
+
* - Subscribes to signal emitters for automatic storage updates
|
|
32723
|
+
* - Provides unified access to both backtest and live signals
|
|
32724
|
+
* - Singleshot enable pattern prevents duplicate subscriptions
|
|
32725
|
+
* - Cleanup function for proper unsubscription
|
|
32003
32726
|
*/
|
|
32004
32727
|
class StorageAdapter {
|
|
32005
32728
|
constructor() {
|
|
32006
|
-
this._signalLiveUtils = new StorageLiveUtils();
|
|
32007
|
-
this._signalBacktestUtils = new StorageBacktestUtils();
|
|
32008
32729
|
/**
|
|
32009
|
-
* Enables signal
|
|
32730
|
+
* Enables signal storage by subscribing to signal emitters.
|
|
32731
|
+
* Uses singleshot to ensure one-time subscription.
|
|
32010
32732
|
*
|
|
32011
|
-
* @returns Cleanup function
|
|
32733
|
+
* @returns Cleanup function that unsubscribes from all emitters
|
|
32012
32734
|
*/
|
|
32013
32735
|
this.enable = functoolsKit.singleshot(() => {
|
|
32014
32736
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_ENABLE);
|
|
@@ -32017,31 +32739,31 @@ class StorageAdapter {
|
|
|
32017
32739
|
{
|
|
32018
32740
|
const unBacktestOpen = signalBacktestEmitter
|
|
32019
32741
|
.filter(({ action }) => action === "opened")
|
|
32020
|
-
.connect((tick) =>
|
|
32742
|
+
.connect((tick) => StorageBacktest.handleOpened(tick));
|
|
32021
32743
|
const unBacktestClose = signalBacktestEmitter
|
|
32022
32744
|
.filter(({ action }) => action === "closed")
|
|
32023
|
-
.connect((tick) =>
|
|
32745
|
+
.connect((tick) => StorageBacktest.handleClosed(tick));
|
|
32024
32746
|
const unBacktestScheduled = signalBacktestEmitter
|
|
32025
32747
|
.filter(({ action }) => action === "scheduled")
|
|
32026
|
-
.connect((tick) =>
|
|
32748
|
+
.connect((tick) => StorageBacktest.handleScheduled(tick));
|
|
32027
32749
|
const unBacktestCancelled = signalBacktestEmitter
|
|
32028
32750
|
.filter(({ action }) => action === "cancelled")
|
|
32029
|
-
.connect((tick) =>
|
|
32751
|
+
.connect((tick) => StorageBacktest.handleCancelled(tick));
|
|
32030
32752
|
unBacktest = functoolsKit.compose(() => unBacktestOpen(), () => unBacktestClose(), () => unBacktestScheduled(), () => unBacktestCancelled());
|
|
32031
32753
|
}
|
|
32032
32754
|
{
|
|
32033
32755
|
const unLiveOpen = signalLiveEmitter
|
|
32034
32756
|
.filter(({ action }) => action === "opened")
|
|
32035
|
-
.connect((tick) =>
|
|
32757
|
+
.connect((tick) => StorageLive.handleOpened(tick));
|
|
32036
32758
|
const unLiveClose = signalLiveEmitter
|
|
32037
32759
|
.filter(({ action }) => action === "closed")
|
|
32038
|
-
.connect((tick) =>
|
|
32760
|
+
.connect((tick) => StorageLive.handleClosed(tick));
|
|
32039
32761
|
const unLiveScheduled = signalLiveEmitter
|
|
32040
32762
|
.filter(({ action }) => action === "scheduled")
|
|
32041
|
-
.connect((tick) =>
|
|
32763
|
+
.connect((tick) => StorageLive.handleScheduled(tick));
|
|
32042
32764
|
const unLiveCancelled = signalLiveEmitter
|
|
32043
32765
|
.filter(({ action }) => action === "cancelled")
|
|
32044
|
-
.connect((tick) =>
|
|
32766
|
+
.connect((tick) => StorageLive.handleCancelled(tick));
|
|
32045
32767
|
unLive = functoolsKit.compose(() => unLiveOpen(), () => unLiveClose(), () => unLiveScheduled(), () => unLiveCancelled());
|
|
32046
32768
|
}
|
|
32047
32769
|
return () => {
|
|
@@ -32051,7 +32773,8 @@ class StorageAdapter {
|
|
|
32051
32773
|
};
|
|
32052
32774
|
});
|
|
32053
32775
|
/**
|
|
32054
|
-
* Disables signal
|
|
32776
|
+
* Disables signal storage by unsubscribing from all emitters.
|
|
32777
|
+
* Safe to call multiple times.
|
|
32055
32778
|
*/
|
|
32056
32779
|
this.disable = () => {
|
|
32057
32780
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_DISABLE);
|
|
@@ -32061,11 +32784,12 @@ class StorageAdapter {
|
|
|
32061
32784
|
}
|
|
32062
32785
|
};
|
|
32063
32786
|
/**
|
|
32064
|
-
* Finds a signal by ID across both backtest and live
|
|
32787
|
+
* Finds a signal by ID across both backtest and live storage.
|
|
32065
32788
|
*
|
|
32066
|
-
* @param id -
|
|
32067
|
-
* @returns
|
|
32068
|
-
* @throws Error if
|
|
32789
|
+
* @param id - The signal ID to search for
|
|
32790
|
+
* @returns The signal row or throws if not found
|
|
32791
|
+
* @throws Error if StorageAdapter is not enabled
|
|
32792
|
+
* @throws Error if signal is not found in either storage
|
|
32069
32793
|
*/
|
|
32070
32794
|
this.findSignalById = async (id) => {
|
|
32071
32795
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_FIND_SIGNAL_BY_ID, { id });
|
|
@@ -32073,41 +32797,57 @@ class StorageAdapter {
|
|
|
32073
32797
|
throw new Error("StorageAdapter is not enabled. Call enable() first.");
|
|
32074
32798
|
}
|
|
32075
32799
|
let result = null;
|
|
32076
|
-
if ((result = await
|
|
32800
|
+
if ((result = await StorageBacktest.findById(id))) {
|
|
32077
32801
|
return result;
|
|
32078
32802
|
}
|
|
32079
|
-
if ((result = await
|
|
32803
|
+
if ((result = await StorageLive.findById(id))) {
|
|
32080
32804
|
return result;
|
|
32081
32805
|
}
|
|
32082
32806
|
throw new Error(`Storage signal with id ${id} not found`);
|
|
32083
32807
|
};
|
|
32084
32808
|
/**
|
|
32085
|
-
* Lists all backtest
|
|
32809
|
+
* Lists all backtest signals from storage.
|
|
32086
32810
|
*
|
|
32087
|
-
* @returns
|
|
32811
|
+
* @returns Array of all backtest signal rows
|
|
32812
|
+
* @throws Error if StorageAdapter is not enabled
|
|
32088
32813
|
*/
|
|
32089
32814
|
this.listSignalBacktest = async () => {
|
|
32090
32815
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_BACKTEST);
|
|
32091
32816
|
if (!this.enable.hasValue()) {
|
|
32092
32817
|
throw new Error("StorageAdapter is not enabled. Call enable() first.");
|
|
32093
32818
|
}
|
|
32094
|
-
return await
|
|
32819
|
+
return await StorageBacktest.list();
|
|
32095
32820
|
};
|
|
32096
32821
|
/**
|
|
32097
|
-
* Lists all live
|
|
32822
|
+
* Lists all live signals from storage.
|
|
32098
32823
|
*
|
|
32099
|
-
* @returns
|
|
32824
|
+
* @returns Array of all live signal rows
|
|
32825
|
+
* @throws Error if StorageAdapter is not enabled
|
|
32100
32826
|
*/
|
|
32101
32827
|
this.listSignalLive = async () => {
|
|
32102
32828
|
bt.loggerService.info(STORAGE_ADAPTER_METHOD_NAME_LIST_SIGNAL_LIVE);
|
|
32103
32829
|
if (!this.enable.hasValue()) {
|
|
32104
32830
|
throw new Error("StorageAdapter is not enabled. Call enable() first.");
|
|
32105
32831
|
}
|
|
32106
|
-
return await
|
|
32832
|
+
return await StorageLive.list();
|
|
32107
32833
|
};
|
|
32108
32834
|
}
|
|
32109
32835
|
}
|
|
32836
|
+
/**
|
|
32837
|
+
* Global singleton instance of StorageAdapter.
|
|
32838
|
+
* Provides unified signal storage management for backtest and live trading.
|
|
32839
|
+
*/
|
|
32110
32840
|
const Storage = new StorageAdapter();
|
|
32841
|
+
/**
|
|
32842
|
+
* Global singleton instance of StorageLiveAdapter.
|
|
32843
|
+
* Provides live trading signal storage with pluggable backends.
|
|
32844
|
+
*/
|
|
32845
|
+
const StorageLive = new StorageLiveAdapter();
|
|
32846
|
+
/**
|
|
32847
|
+
* Global singleton instance of StorageBacktestAdapter.
|
|
32848
|
+
* Provides backtest signal storage with pluggable backends.
|
|
32849
|
+
*/
|
|
32850
|
+
const StorageBacktest = new StorageBacktestAdapter();
|
|
32111
32851
|
|
|
32112
32852
|
const EXCHANGE_METHOD_NAME_GET_CANDLES = "ExchangeUtils.getCandles";
|
|
32113
32853
|
const EXCHANGE_METHOD_NAME_GET_AVERAGE_PRICE = "ExchangeUtils.getAveragePrice";
|
|
@@ -33201,6 +33941,12 @@ class NotificationInstance {
|
|
|
33201
33941
|
currentPrice: data.currentPrice,
|
|
33202
33942
|
priceOpen: data.data.priceOpen,
|
|
33203
33943
|
position: data.data.position,
|
|
33944
|
+
priceTakeProfit: data.data.priceTakeProfit,
|
|
33945
|
+
priceStopLoss: data.data.priceStopLoss,
|
|
33946
|
+
originalPriceTakeProfit: data.data.originalPriceTakeProfit,
|
|
33947
|
+
originalPriceStopLoss: data.data.originalPriceStopLoss,
|
|
33948
|
+
scheduledAt: data.data.scheduledAt,
|
|
33949
|
+
pendingAt: data.data.pendingAt,
|
|
33204
33950
|
createdAt: data.timestamp,
|
|
33205
33951
|
});
|
|
33206
33952
|
};
|
|
@@ -33221,6 +33967,12 @@ class NotificationInstance {
|
|
|
33221
33967
|
currentPrice: data.currentPrice,
|
|
33222
33968
|
priceOpen: data.data.priceOpen,
|
|
33223
33969
|
position: data.data.position,
|
|
33970
|
+
priceTakeProfit: data.data.priceTakeProfit,
|
|
33971
|
+
priceStopLoss: data.data.priceStopLoss,
|
|
33972
|
+
originalPriceTakeProfit: data.data.originalPriceTakeProfit,
|
|
33973
|
+
originalPriceStopLoss: data.data.originalPriceStopLoss,
|
|
33974
|
+
scheduledAt: data.data.scheduledAt,
|
|
33975
|
+
pendingAt: data.data.pendingAt,
|
|
33224
33976
|
createdAt: data.timestamp,
|
|
33225
33977
|
});
|
|
33226
33978
|
};
|
|
@@ -33240,6 +33992,12 @@ class NotificationInstance {
|
|
|
33240
33992
|
currentPrice: data.currentPrice,
|
|
33241
33993
|
priceOpen: data.data.priceOpen,
|
|
33242
33994
|
position: data.data.position,
|
|
33995
|
+
priceTakeProfit: data.data.priceTakeProfit,
|
|
33996
|
+
priceStopLoss: data.data.priceStopLoss,
|
|
33997
|
+
originalPriceTakeProfit: data.data.originalPriceTakeProfit,
|
|
33998
|
+
originalPriceStopLoss: data.data.originalPriceStopLoss,
|
|
33999
|
+
scheduledAt: data.data.scheduledAt,
|
|
34000
|
+
pendingAt: data.data.pendingAt,
|
|
33243
34001
|
createdAt: data.timestamp,
|
|
33244
34002
|
});
|
|
33245
34003
|
};
|
|
@@ -33258,6 +34016,14 @@ class NotificationInstance {
|
|
|
33258
34016
|
exchangeName: data.exchangeName,
|
|
33259
34017
|
percentToClose: data.percentToClose,
|
|
33260
34018
|
currentPrice: data.currentPrice,
|
|
34019
|
+
position: data.position,
|
|
34020
|
+
priceOpen: data.priceOpen,
|
|
34021
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34022
|
+
priceStopLoss: data.priceStopLoss,
|
|
34023
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34024
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34025
|
+
scheduledAt: data.scheduledAt,
|
|
34026
|
+
pendingAt: data.pendingAt,
|
|
33261
34027
|
createdAt: data.timestamp,
|
|
33262
34028
|
});
|
|
33263
34029
|
}
|
|
@@ -33272,6 +34038,14 @@ class NotificationInstance {
|
|
|
33272
34038
|
exchangeName: data.exchangeName,
|
|
33273
34039
|
percentToClose: data.percentToClose,
|
|
33274
34040
|
currentPrice: data.currentPrice,
|
|
34041
|
+
position: data.position,
|
|
34042
|
+
priceOpen: data.priceOpen,
|
|
34043
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34044
|
+
priceStopLoss: data.priceStopLoss,
|
|
34045
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34046
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34047
|
+
scheduledAt: data.scheduledAt,
|
|
34048
|
+
pendingAt: data.pendingAt,
|
|
33275
34049
|
createdAt: data.timestamp,
|
|
33276
34050
|
});
|
|
33277
34051
|
}
|
|
@@ -33285,6 +34059,14 @@ class NotificationInstance {
|
|
|
33285
34059
|
strategyName: data.strategyName,
|
|
33286
34060
|
exchangeName: data.exchangeName,
|
|
33287
34061
|
currentPrice: data.currentPrice,
|
|
34062
|
+
position: data.position,
|
|
34063
|
+
priceOpen: data.priceOpen,
|
|
34064
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34065
|
+
priceStopLoss: data.priceStopLoss,
|
|
34066
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34067
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34068
|
+
scheduledAt: data.scheduledAt,
|
|
34069
|
+
pendingAt: data.pendingAt,
|
|
33288
34070
|
createdAt: data.timestamp,
|
|
33289
34071
|
});
|
|
33290
34072
|
}
|
|
@@ -33299,6 +34081,14 @@ class NotificationInstance {
|
|
|
33299
34081
|
exchangeName: data.exchangeName,
|
|
33300
34082
|
percentShift: data.percentShift,
|
|
33301
34083
|
currentPrice: data.currentPrice,
|
|
34084
|
+
position: data.position,
|
|
34085
|
+
priceOpen: data.priceOpen,
|
|
34086
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34087
|
+
priceStopLoss: data.priceStopLoss,
|
|
34088
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34089
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34090
|
+
scheduledAt: data.scheduledAt,
|
|
34091
|
+
pendingAt: data.pendingAt,
|
|
33302
34092
|
createdAt: data.timestamp,
|
|
33303
34093
|
});
|
|
33304
34094
|
}
|
|
@@ -33313,6 +34103,14 @@ class NotificationInstance {
|
|
|
33313
34103
|
exchangeName: data.exchangeName,
|
|
33314
34104
|
percentShift: data.percentShift,
|
|
33315
34105
|
currentPrice: data.currentPrice,
|
|
34106
|
+
position: data.position,
|
|
34107
|
+
priceOpen: data.priceOpen,
|
|
34108
|
+
priceTakeProfit: data.priceTakeProfit,
|
|
34109
|
+
priceStopLoss: data.priceStopLoss,
|
|
34110
|
+
originalPriceTakeProfit: data.originalPriceTakeProfit,
|
|
34111
|
+
originalPriceStopLoss: data.originalPriceStopLoss,
|
|
34112
|
+
scheduledAt: data.scheduledAt,
|
|
34113
|
+
pendingAt: data.pendingAt,
|
|
33316
34114
|
createdAt: data.timestamp,
|
|
33317
34115
|
});
|
|
33318
34116
|
}
|
|
@@ -34144,6 +34942,8 @@ exports.ReportBase = ReportBase;
|
|
|
34144
34942
|
exports.Risk = Risk;
|
|
34145
34943
|
exports.Schedule = Schedule;
|
|
34146
34944
|
exports.Storage = Storage;
|
|
34945
|
+
exports.StorageBacktest = StorageBacktest;
|
|
34946
|
+
exports.StorageLive = StorageLive;
|
|
34147
34947
|
exports.Strategy = Strategy;
|
|
34148
34948
|
exports.Walker = Walker;
|
|
34149
34949
|
exports.addActionSchema = addActionSchema;
|