@tradejs/cli 3.1.26 → 3.1.27-beta.247
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/dist/cli.js +436 -45
- package/dist/lib/runtimeDebugEvidence.js +1 -0
- package/dist/lib/runtimeParityDetails.js +128 -6
- package/dist/lib/runtimeScorecard.js +103 -20
- package/dist/lib/runtimeSignalsLoader.js +1 -0
- package/dist/lib/runtimeSignalsStorage.js +33 -0
- package/dist/scripts/replay.js +266 -19
- package/dist/scripts/replayRunner.js +266 -19
- package/dist/scripts/replayRuntimeEvidence.js +14 -1
- package/dist/scripts/runtimeEvidence.js +1 -0
- package/dist/scripts/runtimeParity.js +1 -0
- package/dist/scripts/runtimeScorecard.js +109 -20
- package/dist/scripts/signals.js +37 -0
- package/dist/scripts/signalsDaemon.js +37 -0
- package/dist/scripts/signalsSummary.js +1 -0
- package/package.json +7 -7
|
@@ -758,6 +758,20 @@ var countBy = (items, getter) => {
|
|
|
758
758
|
Object.entries(counts).sort(([left], [right]) => left.localeCompare(right))
|
|
759
759
|
);
|
|
760
760
|
};
|
|
761
|
+
var resolveGateDecision = (evaluation) => {
|
|
762
|
+
const analysis = asRecord2(evaluation.aiAnalysis);
|
|
763
|
+
const explicit = finiteString(analysis?.gateDecision);
|
|
764
|
+
if (explicit === "approved" || explicit === "rejected") {
|
|
765
|
+
return { decision: explicit, source: "gate_decision" };
|
|
766
|
+
}
|
|
767
|
+
if (typeof analysis?.approved === "boolean") {
|
|
768
|
+
return {
|
|
769
|
+
decision: analysis.approved ? "approved" : "rejected",
|
|
770
|
+
source: "legacy_approved_fallback"
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
return null;
|
|
774
|
+
};
|
|
761
775
|
var buildDistributions = ({
|
|
762
776
|
evaluations,
|
|
763
777
|
signals
|
|
@@ -938,18 +952,15 @@ var buildRuntimeScorecard = ({
|
|
|
938
952
|
const signalEvaluations = rows.evaluations.filter(
|
|
939
953
|
(evaluation) => evaluation.status === "signal"
|
|
940
954
|
);
|
|
941
|
-
const gateDecisions = signalEvaluations.map(
|
|
942
|
-
|
|
943
|
-
decision: finiteString(asRecord2(evaluation.aiAnalysis)?.gateDecision)
|
|
944
|
-
})).filter(
|
|
945
|
-
({ decision }) => decision === "approved" || decision === "rejected"
|
|
955
|
+
const gateDecisions = signalEvaluations.map(resolveGateDecision).filter(
|
|
956
|
+
(decision) => Boolean(decision)
|
|
946
957
|
);
|
|
947
958
|
const llmEligibleEvaluations = llmComparatorPolicy === "disabled" ? [] : llmComparatorPolicy === "ai_approved_only" ? signalEvaluations.filter(
|
|
948
|
-
(evaluation) =>
|
|
959
|
+
(evaluation) => resolveGateDecision(evaluation)?.decision === "approved"
|
|
949
960
|
) : signalEvaluations;
|
|
950
961
|
const gateComparisons = llmEligibleEvaluations.map((evaluation) => {
|
|
951
962
|
const analysis = asRecord2(evaluation.aiAnalysis);
|
|
952
|
-
const gateDecision =
|
|
963
|
+
const gateDecision = resolveGateDecision(evaluation)?.decision ?? null;
|
|
953
964
|
const llmDecision = finiteString(analysis?.llmDecision);
|
|
954
965
|
if (gateDecision !== "approved" && gateDecision !== "rejected" || llmDecision !== "approved" && llmDecision !== "rejected") {
|
|
955
966
|
return null;
|
|
@@ -984,6 +995,27 @@ var buildRuntimeScorecard = ({
|
|
|
984
995
|
};
|
|
985
996
|
const actualSlippageBps = averageSampleMetric("signalToFillAdverseBps");
|
|
986
997
|
const residualVsModelBps = averageSampleMetric("residualVsCurrentModelBps");
|
|
998
|
+
const signalToArrivalAdverseBps = averageSampleMetric(
|
|
999
|
+
"signalToArrivalAdverseBps"
|
|
1000
|
+
);
|
|
1001
|
+
const arrivalToFillAdverseBps = averageSampleMetric(
|
|
1002
|
+
"arrivalToFillAdverseBps"
|
|
1003
|
+
);
|
|
1004
|
+
const averageSignalCloseToSubmitMs = averageSampleMetric(
|
|
1005
|
+
"signalCloseToSubmitMs"
|
|
1006
|
+
);
|
|
1007
|
+
const averageSubmitToFillMs = averageSampleMetric("submitToFillMs");
|
|
1008
|
+
const fullTelemetryTrades = calibrationSamples.filter(
|
|
1009
|
+
(sample) => finiteString(sample.telemetryQuality) === "full"
|
|
1010
|
+
).length;
|
|
1011
|
+
const arrivalQuoteTrades = calibrationSamples.filter(
|
|
1012
|
+
(sample) => finiteNumber(sample.arrivalMid) != null
|
|
1013
|
+
).length;
|
|
1014
|
+
const arrivalQuoteCoverage = calibrationSamples.length ? round(arrivalQuoteTrades / calibrationSamples.length) : null;
|
|
1015
|
+
const hasTelemetryQuality = calibrationSamples.some(
|
|
1016
|
+
(sample) => finiteString(sample.telemetryQuality) != null
|
|
1017
|
+
);
|
|
1018
|
+
const maximumSignalCloseToSubmitMs = thresholds.maximumSignalCloseToSubmitMs ?? 3e4;
|
|
987
1019
|
const prospective = getProspectiveSummary(prospectiveEvidenceArtifact);
|
|
988
1020
|
const historyTrades = dedupeTrades([
|
|
989
1021
|
...scopedHistoryArtifacts,
|
|
@@ -1040,7 +1072,28 @@ var buildRuntimeScorecard = ({
|
|
|
1040
1072
|
reactions.push({
|
|
1041
1073
|
code: "SLIPPAGE_DRIFT",
|
|
1042
1074
|
severity: "warning",
|
|
1043
|
-
message: `
|
|
1075
|
+
message: `Signal-close-to-fill residual ${round(residualVsModelBps, 2)} bps exceeds ${thresholds.maximumSlippageResidualBps} bps.`
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
if (averageSignalCloseToSubmitMs != null && averageSignalCloseToSubmitMs > maximumSignalCloseToSubmitMs) {
|
|
1079
|
+
reactions.push({
|
|
1080
|
+
code: "PRE_SUBMIT_LATENCY",
|
|
1081
|
+
severity: "warning",
|
|
1082
|
+
message: `Average signal-close-to-submit latency ${round(averageSignalCloseToSubmitMs, 3)} ms exceeds ${maximumSignalCloseToSubmitMs} ms.`
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
if (hasTelemetryQuality && calibrationSamples.length > 0 && fullTelemetryTrades < calibrationSamples.length) {
|
|
1086
|
+
reactions.push({
|
|
1087
|
+
code: "EXECUTION_TELEMETRY_INCOMPLETE",
|
|
1088
|
+
severity: "info",
|
|
1089
|
+
message: `Full arrival and fill telemetry is available for ${fullTelemetryTrades}/${calibrationSamples.length} trades.`
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1092
|
+
if (riskDecisions.some((decision) => decision.status === "rejected")) {
|
|
1093
|
+
reactions.push({
|
|
1094
|
+
code: "RISK_PLAN_EXCEEDS_DECLARED_LIMIT",
|
|
1095
|
+
severity: "warning",
|
|
1096
|
+
message: "At least one observed order plan exceeds its declared MAX_LOSS_VALUE; telemetry is not yet enforced."
|
|
1044
1097
|
});
|
|
1045
1098
|
}
|
|
1046
1099
|
if (sevenDay.closedTrades >= thresholds.minimumClosedTrades && sevenDay.expectancy != null && sevenDay.expectancy < thresholds.minimumExpectancy) {
|
|
@@ -1069,7 +1122,10 @@ var buildRuntimeScorecard = ({
|
|
|
1069
1122
|
deployment: deploymentBinding,
|
|
1070
1123
|
lineage: runtimeLineage,
|
|
1071
1124
|
promotionStatus,
|
|
1072
|
-
thresholds
|
|
1125
|
+
thresholds: {
|
|
1126
|
+
...thresholds,
|
|
1127
|
+
maximumSignalCloseToSubmitMs
|
|
1128
|
+
},
|
|
1073
1129
|
funnel: {
|
|
1074
1130
|
evaluations: rows.evaluations.length,
|
|
1075
1131
|
coreCandidates: signalEvaluations.length,
|
|
@@ -1081,25 +1137,38 @@ var buildRuntimeScorecard = ({
|
|
|
1081
1137
|
rejected: gateDecisions.filter(
|
|
1082
1138
|
({ decision }) => decision === "rejected"
|
|
1083
1139
|
).length,
|
|
1084
|
-
coverage: signalEvaluations.length ? round(gateDecisions.length / signalEvaluations.length) : null
|
|
1140
|
+
coverage: signalEvaluations.length ? round(gateDecisions.length / signalEvaluations.length) : null,
|
|
1141
|
+
legacyApprovedFallback: gateDecisions.filter(
|
|
1142
|
+
({ source }) => source === "legacy_approved_fallback"
|
|
1143
|
+
).length
|
|
1085
1144
|
},
|
|
1086
1145
|
allocator: {
|
|
1087
1146
|
available: allocatorDecisions.length > 0,
|
|
1088
1147
|
approved: allocatorDecisions.filter(
|
|
1089
|
-
(decision) => decision.
|
|
1148
|
+
(decision) => decision.status === "approved"
|
|
1090
1149
|
).length,
|
|
1091
1150
|
rejected: allocatorDecisions.filter(
|
|
1092
|
-
(decision) => decision.
|
|
1151
|
+
(decision) => decision.status === "rejected"
|
|
1152
|
+
).length,
|
|
1153
|
+
notApplicable: allocatorDecisions.filter(
|
|
1154
|
+
(decision) => decision.status === "not_applicable"
|
|
1155
|
+
).length,
|
|
1156
|
+
unavailable: allocatorDecisions.filter(
|
|
1157
|
+
(decision) => decision.status === "unavailable"
|
|
1093
1158
|
).length
|
|
1094
1159
|
},
|
|
1095
1160
|
risk: {
|
|
1096
1161
|
available: riskDecisions.length > 0,
|
|
1097
1162
|
approved: riskDecisions.filter(
|
|
1098
|
-
(decision) => decision.
|
|
1163
|
+
(decision) => decision.status === "approved"
|
|
1099
1164
|
).length,
|
|
1100
1165
|
rejected: riskDecisions.filter(
|
|
1101
|
-
(decision) => decision.
|
|
1102
|
-
).length
|
|
1166
|
+
(decision) => decision.status === "rejected"
|
|
1167
|
+
).length,
|
|
1168
|
+
unavailable: riskDecisions.filter(
|
|
1169
|
+
(decision) => decision.status === "unavailable"
|
|
1170
|
+
).length,
|
|
1171
|
+
enforced: riskDecisions.some((decision) => decision.enforced === true)
|
|
1103
1172
|
},
|
|
1104
1173
|
orderAttempts: orderAttempts.length,
|
|
1105
1174
|
orderFailures: orderAttempts.filter(
|
|
@@ -1161,8 +1230,16 @@ var buildRuntimeScorecard = ({
|
|
|
1161
1230
|
},
|
|
1162
1231
|
execution: {
|
|
1163
1232
|
available: actualSlippageBps != null || residualVsModelBps != null,
|
|
1233
|
+
metricScope: arrivalToFillAdverseBps == null ? "signal_close_to_fill" : "signal_and_exchange_components",
|
|
1234
|
+
samples: calibrationSamples.length,
|
|
1235
|
+
fullTelemetryTrades,
|
|
1236
|
+
arrivalQuoteCoverage,
|
|
1164
1237
|
actualSignalToFillSlippageBps: actualSlippageBps,
|
|
1165
|
-
residualVsCurrentModelBps: residualVsModelBps
|
|
1238
|
+
residualVsCurrentModelBps: residualVsModelBps,
|
|
1239
|
+
signalToArrivalAdverseBps,
|
|
1240
|
+
arrivalToFillAdverseBps,
|
|
1241
|
+
averageSignalCloseToSubmitMs,
|
|
1242
|
+
averageSubmitToFillMs
|
|
1166
1243
|
},
|
|
1167
1244
|
prospective,
|
|
1168
1245
|
rolling,
|
|
@@ -1216,10 +1293,10 @@ Window: ${new Date(scorecard.window.startTime).toISOString()} \u2014 ${new Date(
|
|
|
1216
1293
|
|
|
1217
1294
|
- Evaluations: ${scorecard.funnel.evaluations}
|
|
1218
1295
|
- Core candidates: ${scorecard.funnel.coreCandidates}
|
|
1219
|
-
- Gate approvals/rejects: ${scorecard.funnel.gate.approved}/${scorecard.funnel.gate.rejected}
|
|
1296
|
+
- Gate approvals/rejects: ${scorecard.funnel.gate.approved}/${scorecard.funnel.gate.rejected} (legacy fallback: ${scorecard.funnel.gate.legacyApprovedFallback})
|
|
1220
1297
|
- AI / LLM disagreement: ${scorecard.gateComparison.disagreements}/${scorecard.gateComparison.compared}
|
|
1221
|
-
-
|
|
1222
|
-
- Risk
|
|
1298
|
+
- Runtime admission approved/rejected/not-applicable: ${scorecard.funnel.allocator.available ? `${scorecard.funnel.allocator.approved}/${scorecard.funnel.allocator.rejected}/${scorecard.funnel.allocator.notApplicable}` : "unavailable"}
|
|
1299
|
+
- Risk assessment within/exceeds/unavailable: ${scorecard.funnel.risk.available ? `${scorecard.funnel.risk.approved}/${scorecard.funnel.risk.rejected}/${scorecard.funnel.risk.unavailable}` : "unavailable"} (enforced: ${scorecard.funnel.risk.enforced})
|
|
1223
1300
|
- Order attempts/failures: ${scorecard.funnel.orderAttempts}/${scorecard.funnel.orderFailures}
|
|
1224
1301
|
- Fills: ${scorecard.funnel.fills}
|
|
1225
1302
|
- Closed trades: ${scorecard.funnel.closedTrades}
|
|
@@ -1228,8 +1305,14 @@ Window: ${new Date(scorecard.window.startTime).toISOString()} \u2014 ${new Date(
|
|
|
1228
1305
|
|
|
1229
1306
|
- Parity: ${scorecard.parity.ratio == null ? "n/a" : `${round(scorecard.parity.ratio * 100, 2)}%`}
|
|
1230
1307
|
- Runtime/replay mismatches: ${scorecard.parity.backtestOnly + scorecard.parity.runtimeOnly}
|
|
1231
|
-
-
|
|
1308
|
+
- Execution metric scope: ${scorecard.execution.metricScope}
|
|
1309
|
+
- Telemetry samples/full/arrival coverage: ${scorecard.execution.samples}/${scorecard.execution.fullTelemetryTrades}/${scorecard.execution.arrivalQuoteCoverage == null ? "n/a" : `${round(scorecard.execution.arrivalQuoteCoverage * 100, 2)}%`}
|
|
1310
|
+
- Signal-close-to-fill adverse move: ${scorecard.execution.actualSignalToFillSlippageBps ?? "n/a"} bps
|
|
1311
|
+
- Signal-to-arrival adverse move: ${scorecard.execution.signalToArrivalAdverseBps ?? "n/a"} bps
|
|
1312
|
+
- Arrival-to-fill exchange slippage: ${scorecard.execution.arrivalToFillAdverseBps ?? "n/a"} bps
|
|
1232
1313
|
- Residual vs current model: ${scorecard.execution.residualVsCurrentModelBps ?? "n/a"} bps
|
|
1314
|
+
- Average signal-close-to-submit: ${scorecard.execution.averageSignalCloseToSubmitMs ?? "n/a"} ms
|
|
1315
|
+
- Average submit-to-fill: ${scorecard.execution.averageSubmitToFillMs ?? "n/a"} ms
|
|
1233
1316
|
|
|
1234
1317
|
## Rolling performance
|
|
1235
1318
|
|
|
@@ -1938,6 +2021,11 @@ import_args.default.option(
|
|
|
1938
2021
|
"Maximum acceptable execution residual in bps",
|
|
1939
2022
|
3
|
|
1940
2023
|
);
|
|
2024
|
+
import_args.default.option(
|
|
2025
|
+
["L", "maximumSignalCloseToSubmitMs"],
|
|
2026
|
+
"Maximum acceptable average signal-close-to-submit latency in milliseconds",
|
|
2027
|
+
3e4
|
|
2028
|
+
);
|
|
1941
2029
|
import_args.default.option(
|
|
1942
2030
|
["T", "minimumClosedTrades"],
|
|
1943
2031
|
"Minimum 7d closed trades for expectancy reactions",
|
|
@@ -2030,6 +2118,7 @@ var runtimeScorecard = async () => {
|
|
|
2030
2118
|
thresholds: {
|
|
2031
2119
|
minimumParityRatio: Number(flags.minimumParityRatio),
|
|
2032
2120
|
maximumSlippageResidualBps: Number(flags.maximumSlippageResidualBps),
|
|
2121
|
+
maximumSignalCloseToSubmitMs: Number(flags.maximumSignalCloseToSubmitMs),
|
|
2033
2122
|
minimumClosedTrades: Number(flags.minimumClosedTrades),
|
|
2034
2123
|
minimumExpectancy: Number(flags.minimumExpectancy)
|
|
2035
2124
|
},
|
package/dist/scripts/signals.js
CHANGED
|
@@ -3778,7 +3778,38 @@ var import_logger = require("@tradejs/infra/logger");
|
|
|
3778
3778
|
|
|
3779
3779
|
// src/lib/runtimeSignalsStorage.ts
|
|
3780
3780
|
var import_constants2 = require("@tradejs/core/constants");
|
|
3781
|
+
var import_data = require("@tradejs/core/data");
|
|
3781
3782
|
var import_time2 = require("@tradejs/core/time");
|
|
3783
|
+
var appendRuntimeSignalEvaluationRun = (runs = [], evaluation) => {
|
|
3784
|
+
if (evaluation.status !== "skip") {
|
|
3785
|
+
return [...runs];
|
|
3786
|
+
}
|
|
3787
|
+
const stepMs = (0, import_data.intervalToMs)(evaluation.interval);
|
|
3788
|
+
const reason = evaluation.reason?.trim() || "NO_SIGNAL";
|
|
3789
|
+
const existing = runs.find(
|
|
3790
|
+
(run) => run.status === "skip" && run.reason === reason && run.stepMs === stepMs && evaluation.timestamp >= run.firstTimestamp && evaluation.timestamp <= run.lastTimestamp && (evaluation.timestamp - run.firstTimestamp) % stepMs === 0
|
|
3791
|
+
);
|
|
3792
|
+
if (existing) {
|
|
3793
|
+
return [...runs];
|
|
3794
|
+
}
|
|
3795
|
+
const last = runs.at(-1);
|
|
3796
|
+
if (last?.status === "skip" && last.reason === reason && last.stepMs === stepMs && evaluation.timestamp === last.lastTimestamp + stepMs) {
|
|
3797
|
+
return [
|
|
3798
|
+
...runs.slice(0, -1),
|
|
3799
|
+
{ ...last, lastTimestamp: evaluation.timestamp }
|
|
3800
|
+
];
|
|
3801
|
+
}
|
|
3802
|
+
return [
|
|
3803
|
+
...runs,
|
|
3804
|
+
{
|
|
3805
|
+
status: "skip",
|
|
3806
|
+
reason,
|
|
3807
|
+
firstTimestamp: evaluation.timestamp,
|
|
3808
|
+
lastTimestamp: evaluation.timestamp,
|
|
3809
|
+
stepMs
|
|
3810
|
+
}
|
|
3811
|
+
];
|
|
3812
|
+
};
|
|
3782
3813
|
var SECONDS_PER_DAY = 86400;
|
|
3783
3814
|
var RUNTIME_SIGNAL_RETENTION_DAYS_ENV = "RUNTIME_SIGNAL_RETENTION_DAYS";
|
|
3784
3815
|
var DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS = import_constants2.TTL_3D;
|
|
@@ -4091,6 +4122,10 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4091
4122
|
lastTimestamp: Math.max(
|
|
4092
4123
|
existing?.lastTimestamp ?? evaluation.timestamp,
|
|
4093
4124
|
evaluation.timestamp
|
|
4125
|
+
),
|
|
4126
|
+
evaluationRuns: appendRuntimeSignalEvaluationRun(
|
|
4127
|
+
existing?.evaluationRuns,
|
|
4128
|
+
evaluation
|
|
4094
4129
|
)
|
|
4095
4130
|
};
|
|
4096
4131
|
runtimeLineageScopeCache.set(cacheKey, scope);
|
|
@@ -4812,6 +4847,8 @@ var createSignalsTickerEvaluator = ({
|
|
|
4812
4847
|
orderStatus: signal.orderStatus,
|
|
4813
4848
|
orderSkipReason: signal.orderSkipReason,
|
|
4814
4849
|
...signal.aiAnalysis ? { aiAnalysis: signal.aiAnalysis } : {},
|
|
4850
|
+
...signal.allocatorDecision ? { allocatorDecision: signal.allocatorDecision } : {},
|
|
4851
|
+
...signal.riskDecision ? { riskDecision: signal.riskDecision } : {},
|
|
4815
4852
|
...signal.ml ? { ml: signal.ml } : {}
|
|
4816
4853
|
});
|
|
4817
4854
|
import_logger3.logger.info("Signal found %s by strategy %s", symbol, strategyName);
|
|
@@ -3776,7 +3776,38 @@ var import_logger = require("@tradejs/infra/logger");
|
|
|
3776
3776
|
|
|
3777
3777
|
// src/lib/runtimeSignalsStorage.ts
|
|
3778
3778
|
var import_constants2 = require("@tradejs/core/constants");
|
|
3779
|
+
var import_data = require("@tradejs/core/data");
|
|
3779
3780
|
var import_time2 = require("@tradejs/core/time");
|
|
3781
|
+
var appendRuntimeSignalEvaluationRun = (runs = [], evaluation) => {
|
|
3782
|
+
if (evaluation.status !== "skip") {
|
|
3783
|
+
return [...runs];
|
|
3784
|
+
}
|
|
3785
|
+
const stepMs = (0, import_data.intervalToMs)(evaluation.interval);
|
|
3786
|
+
const reason = evaluation.reason?.trim() || "NO_SIGNAL";
|
|
3787
|
+
const existing = runs.find(
|
|
3788
|
+
(run) => run.status === "skip" && run.reason === reason && run.stepMs === stepMs && evaluation.timestamp >= run.firstTimestamp && evaluation.timestamp <= run.lastTimestamp && (evaluation.timestamp - run.firstTimestamp) % stepMs === 0
|
|
3789
|
+
);
|
|
3790
|
+
if (existing) {
|
|
3791
|
+
return [...runs];
|
|
3792
|
+
}
|
|
3793
|
+
const last = runs.at(-1);
|
|
3794
|
+
if (last?.status === "skip" && last.reason === reason && last.stepMs === stepMs && evaluation.timestamp === last.lastTimestamp + stepMs) {
|
|
3795
|
+
return [
|
|
3796
|
+
...runs.slice(0, -1),
|
|
3797
|
+
{ ...last, lastTimestamp: evaluation.timestamp }
|
|
3798
|
+
];
|
|
3799
|
+
}
|
|
3800
|
+
return [
|
|
3801
|
+
...runs,
|
|
3802
|
+
{
|
|
3803
|
+
status: "skip",
|
|
3804
|
+
reason,
|
|
3805
|
+
firstTimestamp: evaluation.timestamp,
|
|
3806
|
+
lastTimestamp: evaluation.timestamp,
|
|
3807
|
+
stepMs
|
|
3808
|
+
}
|
|
3809
|
+
];
|
|
3810
|
+
};
|
|
3780
3811
|
var SECONDS_PER_DAY = 86400;
|
|
3781
3812
|
var RUNTIME_SIGNAL_RETENTION_DAYS_ENV = "RUNTIME_SIGNAL_RETENTION_DAYS";
|
|
3782
3813
|
var DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS = import_constants2.TTL_3D;
|
|
@@ -4089,6 +4120,10 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4089
4120
|
lastTimestamp: Math.max(
|
|
4090
4121
|
existing?.lastTimestamp ?? evaluation.timestamp,
|
|
4091
4122
|
evaluation.timestamp
|
|
4123
|
+
),
|
|
4124
|
+
evaluationRuns: appendRuntimeSignalEvaluationRun(
|
|
4125
|
+
existing?.evaluationRuns,
|
|
4126
|
+
evaluation
|
|
4092
4127
|
)
|
|
4093
4128
|
};
|
|
4094
4129
|
runtimeLineageScopeCache.set(cacheKey, scope);
|
|
@@ -4810,6 +4845,8 @@ var createSignalsTickerEvaluator = ({
|
|
|
4810
4845
|
orderStatus: signal.orderStatus,
|
|
4811
4846
|
orderSkipReason: signal.orderSkipReason,
|
|
4812
4847
|
...signal.aiAnalysis ? { aiAnalysis: signal.aiAnalysis } : {},
|
|
4848
|
+
...signal.allocatorDecision ? { allocatorDecision: signal.allocatorDecision } : {},
|
|
4849
|
+
...signal.riskDecision ? { riskDecision: signal.riskDecision } : {},
|
|
4813
4850
|
...signal.ml ? { ml: signal.ml } : {}
|
|
4814
4851
|
});
|
|
4815
4852
|
import_logger3.logger.info("Signal found %s by strategy %s", symbol, strategyName);
|
|
@@ -436,6 +436,7 @@ var import_redis3 = require("@tradejs/infra/redis");
|
|
|
436
436
|
|
|
437
437
|
// src/lib/runtimeSignalsStorage.ts
|
|
438
438
|
var import_constants2 = require("@tradejs/core/constants");
|
|
439
|
+
var import_data = require("@tradejs/core/data");
|
|
439
440
|
var import_time3 = require("@tradejs/core/time");
|
|
440
441
|
var isRuntimeSignalBucketRef = (value) => {
|
|
441
442
|
if (!value || typeof value !== "object") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/cli",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.27-beta.247",
|
|
4
4
|
"description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -36,13 +36,13 @@
|
|
|
36
36
|
"tradejs": "dist/cli.js"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@tradejs/connectors": "^3.1.
|
|
40
|
-
"@tradejs/core": "^3.1.
|
|
41
|
-
"@tradejs/indicators": "^3.1.
|
|
42
|
-
"@tradejs/infra": "^3.1.
|
|
43
|
-
"@tradejs/node": "^3.1.
|
|
39
|
+
"@tradejs/connectors": "^3.1.27-beta.247",
|
|
40
|
+
"@tradejs/core": "^3.1.27-beta.247",
|
|
41
|
+
"@tradejs/indicators": "^3.1.27-beta.247",
|
|
42
|
+
"@tradejs/infra": "^3.1.27-beta.247",
|
|
43
|
+
"@tradejs/node": "^3.1.27-beta.247",
|
|
44
44
|
"@tradejs/strategy-kit": "3.0.4",
|
|
45
|
-
"@tradejs/types": "^3.1.
|
|
45
|
+
"@tradejs/types": "^3.1.27-beta.247",
|
|
46
46
|
"args": "^5.0.3",
|
|
47
47
|
"bcryptjs": "^2.4.3",
|
|
48
48
|
"chalk": "4.1.2",
|