@tradejs/cli 3.1.29-beta.289 → 3.1.29-beta.290
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 +239 -70
- package/dist/lib/runtimeFeedbackNotification.js +6 -2
- package/dist/lib/runtimeFeedbackReplay.js +44 -29
- package/dist/lib/runtimeParity.js +1 -0
- package/dist/lib/runtimeParityDetails.js +51 -21
- package/dist/scripts/replay.js +170 -29
- package/dist/scripts/replayRunner.js +170 -29
- package/dist/scripts/runtimeFeedbackNotify.js +11 -3
- package/dist/scripts/runtimeFeedbackReplay.js +44 -29
- package/dist/scripts/runtimeParity.js +1 -0
- package/dist/scripts/signalsSummary.js +5 -6
- package/package.json +7 -7
package/dist/cli.js
CHANGED
|
@@ -16039,7 +16039,13 @@ var init_runtimeEvidenceSource = __esm({
|
|
|
16039
16039
|
userName: artifact.userName,
|
|
16040
16040
|
startTime: artifact.startTime,
|
|
16041
16041
|
endTime: artifact.endTime,
|
|
16042
|
-
deployment: artifact.deployment
|
|
16042
|
+
deployment: artifact.deployment,
|
|
16043
|
+
decisionTraceTargets: unwrapRows(
|
|
16044
|
+
artifact.runtime.trades,
|
|
16045
|
+
"trade"
|
|
16046
|
+
).flatMap(
|
|
16047
|
+
({ strategy, symbol, signalTimestamp }) => typeof signalTimestamp === "number" && Number.isFinite(signalTimestamp) && artifact.startTime != null && artifact.endTime != null && signalTimestamp >= artifact.startTime && signalTimestamp < artifact.endTime ? [{ strategy, symbol, signalTimestamp }] : []
|
|
16048
|
+
)
|
|
16043
16049
|
};
|
|
16044
16050
|
};
|
|
16045
16051
|
buildRuntimeEvidenceLineageScopes = ({
|
|
@@ -16649,6 +16655,79 @@ var init_hooks = __esm({
|
|
|
16649
16655
|
}
|
|
16650
16656
|
});
|
|
16651
16657
|
|
|
16658
|
+
// src/lib/replay/historicalSignalsReplayDecisionTrace.ts
|
|
16659
|
+
var replayDecisionTraceKey, describeOutcome, createReplayDecisionTrace;
|
|
16660
|
+
var init_historicalSignalsReplayDecisionTrace = __esm({
|
|
16661
|
+
"src/lib/replay/historicalSignalsReplayDecisionTrace.ts"() {
|
|
16662
|
+
"use strict";
|
|
16663
|
+
replayDecisionTraceKey = ({
|
|
16664
|
+
strategy,
|
|
16665
|
+
symbol,
|
|
16666
|
+
signalTimestamp
|
|
16667
|
+
}) => JSON.stringify([strategy, symbol, signalTimestamp]);
|
|
16668
|
+
describeOutcome = (result) => {
|
|
16669
|
+
if (typeof result === "string") {
|
|
16670
|
+
return {
|
|
16671
|
+
stage: result.startsWith("BACKTEST_ENTRY_DELAY_") ? "entry_delay" : /(?:NO_PATTERN|POSITION_EXISTS)$/.test(result) ? "core" : "evaluation",
|
|
16672
|
+
reason: result
|
|
16673
|
+
};
|
|
16674
|
+
}
|
|
16675
|
+
if (!result) return { stage: "evaluation", reason: "NO_SIGNAL" };
|
|
16676
|
+
const reason = result.orderSkipReason || result.orderFailureReason || result.orderStatus || "SIGNAL";
|
|
16677
|
+
const patternContext = result.additionalIndicators?.tradingPatternsContext;
|
|
16678
|
+
return {
|
|
16679
|
+
stage: result.riskDecision?.status === "rejected" || /^ENTRY_(?:RR_BELOW|RISK_EXCEEDS)/.test(reason) ? "risk" : /^(?:AI_|ML_|HOOK_BEFORE_ENTRY_GATE|RESEARCH_ENTRY_POLICY)/.test(
|
|
16680
|
+
reason
|
|
16681
|
+
) ? "gate" : result.orderStatus ? "execution" : "evaluation",
|
|
16682
|
+
reason,
|
|
16683
|
+
direction: result.direction,
|
|
16684
|
+
orderStatus: result.orderStatus,
|
|
16685
|
+
...typeof patternContext?.selectedPattern === "string" ? { pattern: patternContext.selectedPattern } : {},
|
|
16686
|
+
...typeof patternContext?.sourceCode === "string" ? { patternCode: patternContext.sourceCode } : {}
|
|
16687
|
+
};
|
|
16688
|
+
};
|
|
16689
|
+
createReplayDecisionTrace = (targets = []) => {
|
|
16690
|
+
const traces = /* @__PURE__ */ new Map();
|
|
16691
|
+
const symbols = new Set(targets.map(({ symbol }) => symbol));
|
|
16692
|
+
for (const target of targets) {
|
|
16693
|
+
traces.set(replayDecisionTraceKey(target), {
|
|
16694
|
+
...target,
|
|
16695
|
+
decision: {
|
|
16696
|
+
stage: "not_evaluated",
|
|
16697
|
+
reason: "REPLAY_CANDLE_NOT_EVALUATED"
|
|
16698
|
+
}
|
|
16699
|
+
});
|
|
16700
|
+
}
|
|
16701
|
+
const record = (strategy, symbol, candle, result, notEvaluatedReason) => {
|
|
16702
|
+
if (!symbols.has(symbol)) return;
|
|
16703
|
+
const { timestamp, open, high, low, close, volume } = candle;
|
|
16704
|
+
const trace = traces.get(
|
|
16705
|
+
replayDecisionTraceKey({ strategy, symbol, signalTimestamp: timestamp })
|
|
16706
|
+
);
|
|
16707
|
+
if (result && typeof result !== "string" && result.timestamp !== timestamp) {
|
|
16708
|
+
const original = traces.get(
|
|
16709
|
+
replayDecisionTraceKey({
|
|
16710
|
+
strategy,
|
|
16711
|
+
symbol,
|
|
16712
|
+
signalTimestamp: result.timestamp
|
|
16713
|
+
})
|
|
16714
|
+
);
|
|
16715
|
+
if (original)
|
|
16716
|
+
original.followUp = {
|
|
16717
|
+
...describeOutcome(result),
|
|
16718
|
+
candleTimestamp: timestamp
|
|
16719
|
+
};
|
|
16720
|
+
notEvaluatedReason = "REPLAY_PROCESSED_DELAYED_ENTRY";
|
|
16721
|
+
}
|
|
16722
|
+
if (!trace) return;
|
|
16723
|
+
trace.candle = { timestamp, open, high, low, close, volume };
|
|
16724
|
+
trace.decision = notEvaluatedReason ? { stage: "not_evaluated", reason: notEvaluatedReason } : describeOutcome(result);
|
|
16725
|
+
};
|
|
16726
|
+
return { record, values: () => [...traces.values()] };
|
|
16727
|
+
};
|
|
16728
|
+
}
|
|
16729
|
+
});
|
|
16730
|
+
|
|
16652
16731
|
// src/lib/replay/historicalSignalsReplaySkipEvidence.ts
|
|
16653
16732
|
var import_data3, replayScopeKey, appendReplaySignalEvaluationRun, createHistoricalReplaySkipEvidence;
|
|
16654
16733
|
var init_historicalSignalsReplaySkipEvidence = __esm({
|
|
@@ -16739,6 +16818,7 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16739
16818
|
"src/lib/replay/historicalSignalsReplayExecution.ts"() {
|
|
16740
16819
|
"use strict";
|
|
16741
16820
|
init_historicalSignalsReplayPreparation();
|
|
16821
|
+
init_historicalSignalsReplayDecisionTrace();
|
|
16742
16822
|
init_historicalSignalsReplaySkipEvidence();
|
|
16743
16823
|
advanceCycleMarket = async (plan, connector, timestamp) => {
|
|
16744
16824
|
const cycleSymbols = plan.symbolRuntimes.filter(
|
|
@@ -16771,6 +16851,7 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16771
16851
|
context.plan.runtimeLineages,
|
|
16772
16852
|
context.collectSkipEvidence
|
|
16773
16853
|
);
|
|
16854
|
+
const decisionTrace = createReplayDecisionTrace(context.decisionTraceTargets);
|
|
16774
16855
|
const reportProgress = (timestamp) => {
|
|
16775
16856
|
if (adapters.progress.enabled === false) return;
|
|
16776
16857
|
adapters.progress.tick({
|
|
@@ -16799,6 +16880,20 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16799
16880
|
status: "completed",
|
|
16800
16881
|
durationMs: adapters.clock.now() - cycleStartedAt
|
|
16801
16882
|
});
|
|
16883
|
+
if (context.decisionTraceTargets?.length) {
|
|
16884
|
+
for (const symbolRuntime of cycleSymbols) {
|
|
16885
|
+
const candle = symbolRuntime.replayData[symbolRuntime.currentIndex];
|
|
16886
|
+
for (const strategy of symbolRuntime.strategies) {
|
|
16887
|
+
decisionTrace.record(
|
|
16888
|
+
strategy.strategyName,
|
|
16889
|
+
symbolRuntime.symbol,
|
|
16890
|
+
candle,
|
|
16891
|
+
void 0,
|
|
16892
|
+
"REPLAY_CYCLE_ABORTED"
|
|
16893
|
+
);
|
|
16894
|
+
}
|
|
16895
|
+
}
|
|
16896
|
+
}
|
|
16802
16897
|
advanceAbortedCycle(cycleSymbols, timestamp);
|
|
16803
16898
|
reportProgress(timestamp);
|
|
16804
16899
|
continue;
|
|
@@ -16809,6 +16904,17 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16809
16904
|
const btcCandle = symbolRuntime.btcReplayData[symbolRuntime.currentIndex];
|
|
16810
16905
|
const ethCandle = symbolRuntime.ethReplayData[symbolRuntime.currentIndex];
|
|
16811
16906
|
if (!candle || !btcCandle || candle.timestamp + (symbolRuntime.timestampOffsetMs ?? 0) !== timestamp || btcCandle.timestamp !== candle.timestamp) {
|
|
16907
|
+
if (candle && context.decisionTraceTargets?.length) {
|
|
16908
|
+
for (const strategy of symbolRuntime.strategies) {
|
|
16909
|
+
decisionTrace.record(
|
|
16910
|
+
strategy.strategyName,
|
|
16911
|
+
symbolRuntime.symbol,
|
|
16912
|
+
candle,
|
|
16913
|
+
void 0,
|
|
16914
|
+
"REPLAY_CANDLE_OR_REFERENCE_NOT_ALIGNED"
|
|
16915
|
+
);
|
|
16916
|
+
}
|
|
16917
|
+
}
|
|
16812
16918
|
continue;
|
|
16813
16919
|
}
|
|
16814
16920
|
for (const strategyRuntime of symbolRuntime.strategies) {
|
|
@@ -16817,6 +16923,12 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16817
16923
|
btcCandle,
|
|
16818
16924
|
ethCandle?.timestamp === candle.timestamp ? ethCandle : void 0
|
|
16819
16925
|
);
|
|
16926
|
+
decisionTrace.record(
|
|
16927
|
+
strategyRuntime.strategyName,
|
|
16928
|
+
symbolRuntime.symbol,
|
|
16929
|
+
candle,
|
|
16930
|
+
result
|
|
16931
|
+
);
|
|
16820
16932
|
skipEvidence.record({
|
|
16821
16933
|
strategyName: strategyRuntime.strategyName,
|
|
16822
16934
|
symbol: symbolRuntime.symbol,
|
|
@@ -16848,7 +16960,8 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16848
16960
|
return {
|
|
16849
16961
|
signals: signals2,
|
|
16850
16962
|
abortedCycles,
|
|
16851
|
-
replayLineageScopes: skipEvidence.values()
|
|
16963
|
+
replayLineageScopes: skipEvidence.values(),
|
|
16964
|
+
replayDecisionTraces: decisionTrace.values()
|
|
16852
16965
|
};
|
|
16853
16966
|
};
|
|
16854
16967
|
}
|
|
@@ -16905,7 +17018,8 @@ var init_historicalSignalsReplayResults = __esm({
|
|
|
16905
17018
|
cycleCount: context.cycleCount,
|
|
16906
17019
|
abortedCycles: context.abortedCycles,
|
|
16907
17020
|
runtimeLineages: context.runtimeLineages,
|
|
16908
|
-
replayLineageScopes: context.replayLineageScopes
|
|
17021
|
+
replayLineageScopes: context.replayLineageScopes,
|
|
17022
|
+
...context.replayDecisionTraces?.length ? { replayDecisionTraces: context.replayDecisionTraces } : {}
|
|
16909
17023
|
});
|
|
16910
17024
|
compactHistoricalReplayResultForPortfolio = (result) => ({
|
|
16911
17025
|
...result,
|
|
@@ -16951,7 +17065,10 @@ var init_historicalSignalsReplayResults = __esm({
|
|
|
16951
17065
|
cycleCount: parts.reduce((sum3, part) => sum3 + part.cycleCount, 0),
|
|
16952
17066
|
abortedCycles: parts.reduce((sum3, part) => sum3 + part.abortedCycles, 0),
|
|
16953
17067
|
runtimeLineages: parts.flatMap((part) => part.runtimeLineages),
|
|
16954
|
-
replayLineageScopes: parts.flatMap((part) => part.replayLineageScopes)
|
|
17068
|
+
replayLineageScopes: parts.flatMap((part) => part.replayLineageScopes),
|
|
17069
|
+
replayDecisionTraces: parts.flatMap(
|
|
17070
|
+
(part) => part.replayDecisionTraces ?? []
|
|
17071
|
+
)
|
|
16955
17072
|
};
|
|
16956
17073
|
};
|
|
16957
17074
|
}
|
|
@@ -17127,7 +17244,8 @@ var init_historicalSignalsReplay = __esm({
|
|
|
17127
17244
|
references,
|
|
17128
17245
|
showProgress = true,
|
|
17129
17246
|
collectSkipEvidence = true,
|
|
17130
|
-
collectSignals = true
|
|
17247
|
+
collectSignals = true,
|
|
17248
|
+
decisionTraceTargets
|
|
17131
17249
|
}) => {
|
|
17132
17250
|
const memory = createReplayMemoryProfile();
|
|
17133
17251
|
memory?.("prepare:start");
|
|
@@ -17214,6 +17332,7 @@ var init_historicalSignalsReplay = __esm({
|
|
|
17214
17332
|
connector: replayConnector,
|
|
17215
17333
|
collectSkipEvidence,
|
|
17216
17334
|
collectSignals,
|
|
17335
|
+
decisionTraceTargets,
|
|
17217
17336
|
hooks: projectHooks,
|
|
17218
17337
|
hookContext
|
|
17219
17338
|
},
|
|
@@ -17250,7 +17369,8 @@ var init_historicalSignalsReplay = __esm({
|
|
|
17250
17369
|
cycleCount: plan.orderedTimestamps.length,
|
|
17251
17370
|
abortedCycles: execution.abortedCycles,
|
|
17252
17371
|
runtimeLineages: plan.runtimeLineages,
|
|
17253
|
-
replayLineageScopes: execution.replayLineageScopes
|
|
17372
|
+
replayLineageScopes: execution.replayLineageScopes,
|
|
17373
|
+
replayDecisionTraces: execution.replayDecisionTraces
|
|
17254
17374
|
});
|
|
17255
17375
|
memory?.("result:collected");
|
|
17256
17376
|
return result;
|
|
@@ -17487,6 +17607,7 @@ var init_runtimeParity = __esm({
|
|
|
17487
17607
|
direction: trade.direction,
|
|
17488
17608
|
qty: toFiniteNumberOrNull2(trade.qty),
|
|
17489
17609
|
timestamp: trade.entryTimestamp,
|
|
17610
|
+
...Number.isFinite(trade.signalTimestamp) ? { signalTimestamp: trade.signalTimestamp } : {},
|
|
17490
17611
|
price: toFiniteNumberOrNull2(trade.entryPrice),
|
|
17491
17612
|
orderId: trade.orderId,
|
|
17492
17613
|
signalId: typeof trade.signalId === "string" ? trade.signalId : void 0,
|
|
@@ -18407,6 +18528,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
18407
18528
|
"use strict";
|
|
18408
18529
|
import_trade2 = require("@tradejs/core/trade");
|
|
18409
18530
|
init_runtimeParity();
|
|
18531
|
+
init_historicalSignalsReplayDecisionTrace();
|
|
18410
18532
|
DEFAULT_REPLAY_PARITY_DETAILS_LIMIT = 500;
|
|
18411
18533
|
DEFAULT_REPLAY_PARITY_ARTIFACT_LIMIT = 100;
|
|
18412
18534
|
buildStrategyNameByOrderLinkKey = (strategyNames) => new Map(
|
|
@@ -18481,6 +18603,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
18481
18603
|
direction: entry.direction,
|
|
18482
18604
|
qty: entry.qty ?? null,
|
|
18483
18605
|
timestamp: entry.timestamp,
|
|
18606
|
+
...entry.signalTimestamp != null ? { signalTimestamp: entry.signalTimestamp } : {},
|
|
18484
18607
|
price: entry.price,
|
|
18485
18608
|
exitType: entry.exitType ?? null,
|
|
18486
18609
|
exitTimestamp: entry.exitTimestamp ?? null,
|
|
@@ -18554,7 +18677,8 @@ var init_runtimeParityDetails = __esm({
|
|
|
18554
18677
|
evaluations,
|
|
18555
18678
|
toleranceMs,
|
|
18556
18679
|
timestampOffsetMs,
|
|
18557
|
-
entryTimestampOffsetMs = 0
|
|
18680
|
+
entryTimestampOffsetMs = 0,
|
|
18681
|
+
matchDirection = false
|
|
18558
18682
|
}) => {
|
|
18559
18683
|
const entryStrategy2 = getEntryStrategy(entry);
|
|
18560
18684
|
if (!entryStrategy2) {
|
|
@@ -18564,7 +18688,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
18564
18688
|
let bestDiff = Number.POSITIVE_INFINITY;
|
|
18565
18689
|
const entryTimestamp = entry.timestamp + entryTimestampOffsetMs;
|
|
18566
18690
|
for (const evaluation of evaluations) {
|
|
18567
|
-
if (evaluation.strategy !== entryStrategy2 || evaluation.symbol !== entry.symbol) {
|
|
18691
|
+
if (evaluation.strategy !== entryStrategy2 || evaluation.symbol !== entry.symbol || matchDirection && evaluation.direction != null && evaluation.direction !== entry.direction) {
|
|
18568
18692
|
continue;
|
|
18569
18693
|
}
|
|
18570
18694
|
const diff = Math.abs(
|
|
@@ -18910,6 +19034,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
18910
19034
|
replaySignals = [],
|
|
18911
19035
|
replaySignalEvaluations = [],
|
|
18912
19036
|
replayLineageScopes = [],
|
|
19037
|
+
replayDecisionTraces = [],
|
|
18913
19038
|
runtimeLineageScopes = [],
|
|
18914
19039
|
toleranceMs,
|
|
18915
19040
|
backtestTimestampOffsetMs,
|
|
@@ -18918,48 +19043,66 @@ var init_runtimeParityDetails = __esm({
|
|
|
18918
19043
|
const nearestByEntry = new Map(
|
|
18919
19044
|
nearestCandidates.map((candidate) => [candidate.entry, candidate])
|
|
18920
19045
|
);
|
|
19046
|
+
const traceByCandle = new Map(
|
|
19047
|
+
replayDecisionTraces.map((trace) => [replayDecisionTraceKey(trace), trace])
|
|
19048
|
+
);
|
|
18921
19049
|
const artifactLimit = Math.min(limit, resolveReplayParityArtifactLimit());
|
|
18922
19050
|
let runtimeOnlyArtifactsIncluded = 0;
|
|
18923
19051
|
let backtestOnlyArtifactsIncluded = 0;
|
|
18924
19052
|
const runtimeOnlyDiagnostics = runtimeOnly.map((entry, index) => {
|
|
18925
|
-
const
|
|
18926
|
-
|
|
18927
|
-
|
|
18928
|
-
|
|
19053
|
+
const isRuntimeTrade = entry.source === "runtime";
|
|
19054
|
+
const decisionEntry = isRuntimeTrade ? entry.signalTimestamp == null ? null : { ...entry, timestamp: entry.signalTimestamp } : entry;
|
|
19055
|
+
const decisionClock = {
|
|
19056
|
+
toleranceMs: isRuntimeTrade ? 0 : toleranceMs,
|
|
19057
|
+
timestampOffsetMs: isRuntimeTrade ? 0 : resolveTradeParityTimestampOffset(
|
|
19058
|
+
getEntryStrategy(entry) ?? "",
|
|
19059
|
+
backtestTimestampOffsetMs
|
|
19060
|
+
)
|
|
19061
|
+
};
|
|
18929
19062
|
const includeArtifacts = index < artifactLimit;
|
|
18930
19063
|
const nearestCandidate = nearestByEntry.get(entry);
|
|
18931
|
-
const nearestReplaySignal = findNearestSignal({
|
|
18932
|
-
entry,
|
|
19064
|
+
const nearestReplaySignal = decisionEntry && findNearestSignal({
|
|
19065
|
+
entry: decisionEntry,
|
|
18933
19066
|
signals: replaySignals,
|
|
18934
|
-
|
|
18935
|
-
timestampOffsetMs: entryOffsetMs
|
|
19067
|
+
...decisionClock
|
|
18936
19068
|
});
|
|
18937
|
-
const nearestReplayEvaluation = findNearestEvaluation({
|
|
18938
|
-
entry,
|
|
19069
|
+
const nearestReplayEvaluation = decisionEntry && findNearestEvaluation({
|
|
19070
|
+
entry: decisionEntry,
|
|
18939
19071
|
evaluations: replaySignalEvaluations,
|
|
18940
|
-
|
|
18941
|
-
|
|
19072
|
+
matchDirection: isRuntimeTrade,
|
|
19073
|
+
...decisionClock
|
|
18942
19074
|
});
|
|
18943
|
-
const nearestReplayEvaluationOutcome = findNearestReplayEvaluationOutcome({
|
|
18944
|
-
entry,
|
|
19075
|
+
const nearestReplayEvaluationOutcome = decisionEntry && findNearestReplayEvaluationOutcome({
|
|
19076
|
+
entry: decisionEntry,
|
|
18945
19077
|
lineageScopes: replayLineageScopes,
|
|
18946
|
-
|
|
18947
|
-
timestampOffsetMs: entryOffsetMs
|
|
19078
|
+
...decisionClock
|
|
18948
19079
|
});
|
|
19080
|
+
const strategy = getEntryStrategy(entry);
|
|
19081
|
+
const replayDecisionTrace = isRuntimeTrade && strategy && decisionEntry ? traceByCandle.get(
|
|
19082
|
+
replayDecisionTraceKey({
|
|
19083
|
+
strategy,
|
|
19084
|
+
symbol: entry.symbol,
|
|
19085
|
+
signalTimestamp: decisionEntry.timestamp
|
|
19086
|
+
})
|
|
19087
|
+
) : void 0;
|
|
19088
|
+
const unavailableReason = !isRuntimeTrade ? "no_replay_signal_or_backtest_candidate" : !decisionEntry ? "replay_signal_timestamp_unavailable" : replayDecisionTrace?.decision.stage === "not_evaluated" ? replayDecisionTrace.decision.reason : "replay_evaluation_unavailable";
|
|
18949
19089
|
const classification = nearestReplaySignal ? classifySignalDiagnostic(nearestReplaySignal.signal) : nearestReplayEvaluation ? classifyEvaluationDiagnostic(nearestReplayEvaluation.evaluation) : nearestReplayEvaluationOutcome ? {
|
|
18950
|
-
classification:
|
|
19090
|
+
classification: nearestReplayEvaluationOutcome.reason.startsWith(
|
|
19091
|
+
"BACKTEST_ENTRY_DELAY_"
|
|
19092
|
+
) ? "entry_delayed" : "core_skipped",
|
|
18951
19093
|
reason: nearestReplayEvaluationOutcome.reason
|
|
18952
|
-
} : nearestCandidate?.nearest ? {
|
|
19094
|
+
} : !isRuntimeTrade && nearestCandidate?.nearest ? {
|
|
18953
19095
|
classification: "timing_or_price_drift",
|
|
18954
19096
|
reason: nearestCandidate.reason
|
|
18955
19097
|
} : {
|
|
18956
19098
|
classification: "no_replay_candidate",
|
|
18957
|
-
reason:
|
|
19099
|
+
reason: unavailableReason
|
|
18958
19100
|
};
|
|
18959
19101
|
return {
|
|
18960
19102
|
entry,
|
|
18961
19103
|
...classification,
|
|
18962
19104
|
...nearestCandidate ? { nearestCandidate } : {},
|
|
19105
|
+
...replayDecisionTrace ? { replayDecisionTrace } : {},
|
|
18963
19106
|
...nearestReplaySignal ? {
|
|
18964
19107
|
replaySignal: toSignalDiagnostic({
|
|
18965
19108
|
signal: nearestReplaySignal.signal,
|
|
@@ -19085,6 +19228,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
19085
19228
|
replaySignals,
|
|
19086
19229
|
replaySignalEvaluations,
|
|
19087
19230
|
replayLineageScopes,
|
|
19231
|
+
replayDecisionTraces,
|
|
19088
19232
|
runtimeLineageScopes
|
|
19089
19233
|
}) => {
|
|
19090
19234
|
const runtimeDetails = runtimeEntries.map(toRuntimeParityDetail);
|
|
@@ -19145,6 +19289,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
19145
19289
|
replaySignals,
|
|
19146
19290
|
replaySignalEvaluations,
|
|
19147
19291
|
replayLineageScopes,
|
|
19292
|
+
replayDecisionTraces,
|
|
19148
19293
|
runtimeLineageScopes,
|
|
19149
19294
|
toleranceMs,
|
|
19150
19295
|
backtestTimestampOffsetMs,
|
|
@@ -20209,6 +20354,7 @@ var init_runtimeComparison = __esm({
|
|
|
20209
20354
|
replaySignals,
|
|
20210
20355
|
replayLineages,
|
|
20211
20356
|
replayLineageScopes,
|
|
20357
|
+
replayDecisionTraces,
|
|
20212
20358
|
runtimeEvidencePath
|
|
20213
20359
|
}) => {
|
|
20214
20360
|
const { connector, connectorName, window } = getRuntimeCompareContext();
|
|
@@ -20360,7 +20506,8 @@ var init_runtimeComparison = __esm({
|
|
|
20360
20506
|
replaySignals,
|
|
20361
20507
|
replaySignalEvaluations,
|
|
20362
20508
|
runtimeLineageScopes: comparable.runtimeLineageScopes,
|
|
20363
|
-
replayLineageScopes
|
|
20509
|
+
replayLineageScopes,
|
|
20510
|
+
replayDecisionTraces
|
|
20364
20511
|
});
|
|
20365
20512
|
const parityRows = summarizeTradeParityByStrategy({
|
|
20366
20513
|
runtimeEntries: runtimeDedupe.entries,
|
|
@@ -21338,6 +21485,7 @@ var init_replayRunner = __esm({
|
|
|
21338
21485
|
replaySignals: replayResult.signals,
|
|
21339
21486
|
replayLineages: replayResult.runtimeLineages,
|
|
21340
21487
|
replayLineageScopes: replayResult.replayLineageScopes,
|
|
21488
|
+
replayDecisionTraces: replayResult.replayDecisionTraces,
|
|
21341
21489
|
runtimeEvidencePath: replayRuntimeEvidencePath
|
|
21342
21490
|
});
|
|
21343
21491
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
@@ -21687,7 +21835,8 @@ var init_replayRunner = __esm({
|
|
|
21687
21835
|
references: historicalReplayReferences,
|
|
21688
21836
|
showProgress: !replayFlags.portfolioReport,
|
|
21689
21837
|
collectSkipEvidence: !replayFlags.portfolioReport,
|
|
21690
|
-
collectSignals: !replayFlags.portfolioReport
|
|
21838
|
+
collectSignals: !replayFlags.portfolioReport,
|
|
21839
|
+
decisionTraceTargets: replayFlags.portfolioReport ? void 0 : evidenceMetadata?.decisionTraceTargets
|
|
21691
21840
|
});
|
|
21692
21841
|
return replayFlags.portfolioReport ? compactHistoricalReplayResultForPortfolio(result) : result;
|
|
21693
21842
|
};
|
|
@@ -36439,13 +36588,14 @@ var init_runtimeFeedbackArtifacts = __esm({
|
|
|
36439
36588
|
});
|
|
36440
36589
|
|
|
36441
36590
|
// src/lib/runtimeFeedbackReplay.ts
|
|
36442
|
-
var import_node_child_process9, import_promises35, import_node_path32, REQUIRED_ENV, FORBIDDEN_SECRET_ENV, unsafeRedisHosts, safeSegment, assertRuntimeFeedbackReplaySafety, buildRuntimeFeedbackReplayCommands, runLoggedCommand, runRuntimeFeedbackReplay;
|
|
36591
|
+
var import_node_child_process9, import_promises35, import_node_path32, import_mcp2, REQUIRED_ENV, FORBIDDEN_SECRET_ENV, unsafeRedisHosts, safeSegment, assertRuntimeFeedbackReplaySafety, buildRuntimeFeedbackReplayCommands, runLoggedCommand, runRuntimeFeedbackReplay;
|
|
36443
36592
|
var init_runtimeFeedbackReplay = __esm({
|
|
36444
36593
|
"src/lib/runtimeFeedbackReplay.ts"() {
|
|
36445
36594
|
"use strict";
|
|
36446
36595
|
import_node_child_process9 = require("child_process");
|
|
36447
36596
|
import_promises35 = __toESM(require("fs/promises"));
|
|
36448
36597
|
import_node_path32 = __toESM(require("path"));
|
|
36598
|
+
import_mcp2 = require("@tradejs/node/mcp");
|
|
36449
36599
|
init_runtimeEvidenceDeployment();
|
|
36450
36600
|
init_runtimeEvidenceArtifacts();
|
|
36451
36601
|
init_runtimeEvidenceProducer();
|
|
@@ -36579,44 +36729,58 @@ var init_runtimeFeedbackReplay = __esm({
|
|
|
36579
36729
|
env,
|
|
36580
36730
|
logHandle
|
|
36581
36731
|
}) => {
|
|
36582
|
-
await logHandle.
|
|
36583
|
-
|
|
36584
|
-
|
|
36585
|
-
|
|
36586
|
-
|
|
36587
|
-
|
|
36588
|
-
|
|
36589
|
-
|
|
36590
|
-
|
|
36591
|
-
};
|
|
36592
|
-
const child = (0, import_node_child_process9.spawn)(executable, command, {
|
|
36593
|
-
cwd,
|
|
36594
|
-
env,
|
|
36595
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
36596
|
-
});
|
|
36597
|
-
child.stdout.on("data", (chunk) => {
|
|
36598
|
-
process.stdout.write(chunk);
|
|
36599
|
-
appendLog(chunk);
|
|
36600
|
-
});
|
|
36601
|
-
child.stderr.on("data", (chunk) => {
|
|
36602
|
-
process.stderr.write(chunk);
|
|
36603
|
-
appendLog(chunk);
|
|
36604
|
-
});
|
|
36732
|
+
await logHandle.writeFile(
|
|
36733
|
+
"\n" + (0, import_mcp2.formatMcpArtifactLogLine)(`$ ${[executable, ...command].join(" ")}`)
|
|
36734
|
+
);
|
|
36735
|
+
const child = (0, import_node_child_process9.spawn)(executable, command, {
|
|
36736
|
+
cwd,
|
|
36737
|
+
env,
|
|
36738
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
36739
|
+
});
|
|
36740
|
+
const exit = new Promise((resolve, reject) => {
|
|
36605
36741
|
child.once("error", reject);
|
|
36606
36742
|
child.once("close", (code, signal) => {
|
|
36607
|
-
|
|
36608
|
-
|
|
36609
|
-
resolve();
|
|
36610
|
-
return;
|
|
36611
|
-
}
|
|
36743
|
+
if (code === 0) resolve();
|
|
36744
|
+
else {
|
|
36612
36745
|
reject(
|
|
36613
36746
|
new Error(
|
|
36614
36747
|
`Runtime feedback command failed: exit=${String(code)} signal=${String(signal)}`
|
|
36615
36748
|
)
|
|
36616
36749
|
);
|
|
36617
|
-
}
|
|
36750
|
+
}
|
|
36618
36751
|
});
|
|
36619
36752
|
});
|
|
36753
|
+
let pendingLogWrite = Promise.resolve();
|
|
36754
|
+
const copyLog = async (input, output) => {
|
|
36755
|
+
const writeLine2 = async (line) => {
|
|
36756
|
+
const formatted = (0, import_mcp2.formatMcpArtifactLogLine)(line);
|
|
36757
|
+
pendingLogWrite = pendingLogWrite.then(
|
|
36758
|
+
() => logHandle.writeFile(formatted)
|
|
36759
|
+
);
|
|
36760
|
+
await pendingLogWrite;
|
|
36761
|
+
output.write(formatted);
|
|
36762
|
+
};
|
|
36763
|
+
let pendingLine = "";
|
|
36764
|
+
try {
|
|
36765
|
+
for await (const chunk of input.setEncoding("utf8")) {
|
|
36766
|
+
const lines = (pendingLine + chunk).split("\n");
|
|
36767
|
+
pendingLine = lines.pop() ?? "";
|
|
36768
|
+
for (const line of lines) await writeLine2(line);
|
|
36769
|
+
}
|
|
36770
|
+
if (pendingLine) await writeLine2(pendingLine);
|
|
36771
|
+
} catch (error) {
|
|
36772
|
+
child.kill();
|
|
36773
|
+
throw error;
|
|
36774
|
+
}
|
|
36775
|
+
};
|
|
36776
|
+
const results2 = await Promise.allSettled([
|
|
36777
|
+
copyLog(child.stdout, process.stdout),
|
|
36778
|
+
copyLog(child.stderr, process.stderr),
|
|
36779
|
+
exit
|
|
36780
|
+
]);
|
|
36781
|
+
for (const result of results2) {
|
|
36782
|
+
if (result.status === "rejected") throw result.reason;
|
|
36783
|
+
}
|
|
36620
36784
|
};
|
|
36621
36785
|
runRuntimeFeedbackReplay = async ({
|
|
36622
36786
|
runtimeEvidencePath,
|
|
@@ -36761,10 +36925,11 @@ var init_runtimeFeedbackReplay2 = __esm({
|
|
|
36761
36925
|
});
|
|
36762
36926
|
|
|
36763
36927
|
// src/lib/runtimeFeedbackNotification.ts
|
|
36764
|
-
var isRecord, asRecord6, asArray3, finiteNumber5, requiredTimestamp, escapeHtml5, formatMskDateTime2, formatConnectorName, sumRows, buildRuntimeFeedbackTelegramMessage, notifyRuntimeFeedbackBundle;
|
|
36928
|
+
var import_userSettings7, isRecord, asRecord6, asArray3, finiteNumber5, requiredTimestamp, escapeHtml5, formatMskDateTime2, formatConnectorName, sumRows, buildRuntimeFeedbackTelegramMessage, notifyRuntimeFeedbackBundle;
|
|
36765
36929
|
var init_runtimeFeedbackNotification = __esm({
|
|
36766
36930
|
"src/lib/runtimeFeedbackNotification.ts"() {
|
|
36767
36931
|
"use strict";
|
|
36932
|
+
import_userSettings7 = require("@tradejs/infra/userSettings");
|
|
36768
36933
|
init_runtimeFeedbackArtifacts();
|
|
36769
36934
|
init_telegramReports();
|
|
36770
36935
|
isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -36877,11 +37042,14 @@ var init_runtimeFeedbackNotification = __esm({
|
|
|
36877
37042
|
}) => {
|
|
36878
37043
|
const verified = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(bundleDir);
|
|
36879
37044
|
const message = buildRuntimeFeedbackTelegramMessage(verified.replayEvidence);
|
|
36880
|
-
await
|
|
37045
|
+
const settings = await (0, import_userSettings7.getUserSettings)(verified.manifest.userName);
|
|
37046
|
+
const sent = settings.NOTIFY_RUNTIME_DEBUG !== false;
|
|
37047
|
+
if (sent) await send(message, { userName: verified.manifest.userName });
|
|
36881
37048
|
return {
|
|
36882
37049
|
artifactId: verified.manifest.artifactId,
|
|
36883
37050
|
userName: verified.manifest.userName,
|
|
36884
|
-
message
|
|
37051
|
+
message,
|
|
37052
|
+
sent
|
|
36885
37053
|
};
|
|
36886
37054
|
};
|
|
36887
37055
|
}
|
|
@@ -36919,7 +37087,9 @@ var init_runtimeFeedbackNotify = __esm({
|
|
|
36919
37087
|
}
|
|
36920
37088
|
const result = await notifyRuntimeFeedbackBundle({ bundleDir });
|
|
36921
37089
|
console.log(
|
|
36922
|
-
import_chalk45.default.green(
|
|
37090
|
+
import_chalk45.default.green(
|
|
37091
|
+
`Runtime feedback notification ${result.sent ? "sent" : "disabled"}: ${result.artifactId}`
|
|
37092
|
+
)
|
|
36923
37093
|
);
|
|
36924
37094
|
};
|
|
36925
37095
|
main39 = runtimeFeedbackNotify;
|
|
@@ -45302,11 +45472,12 @@ __export(signalsSummary_exports, {
|
|
|
45302
45472
|
main: () => main51,
|
|
45303
45473
|
signalsSummary: () => signalsSummary
|
|
45304
45474
|
});
|
|
45305
|
-
var import_config13, import_args38, import_logger12, import_connectors19, import_runtimeStrategies9, flags34, projectRoot17, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml8, formatMskDateTime4, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main51;
|
|
45475
|
+
var import_config13, import_userSettings8, import_args38, import_logger12, import_connectors19, import_runtimeStrategies9, flags34, projectRoot17, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml8, formatMskDateTime4, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main51;
|
|
45306
45476
|
var init_signalsSummary = __esm({
|
|
45307
45477
|
"src/scripts/signalsSummary.ts"() {
|
|
45308
45478
|
"use strict";
|
|
45309
45479
|
import_config13 = require("dotenv/config");
|
|
45480
|
+
import_userSettings8 = require("@tradejs/infra/userSettings");
|
|
45310
45481
|
import_args38 = __toESM(require("args"));
|
|
45311
45482
|
import_logger12 = require("@tradejs/infra/logger");
|
|
45312
45483
|
import_connectors19 = require("@tradejs/node/connectors");
|
|
@@ -45840,6 +46011,7 @@ none`
|
|
|
45840
46011
|
};
|
|
45841
46012
|
};
|
|
45842
46013
|
signalsSummary = async () => {
|
|
46014
|
+
const includeDebug = flags34.printOnly || (await (0, import_userSettings8.getUserSettings)(flags34.user)).NOTIFY_RUNTIME_DEBUG !== false;
|
|
45843
46015
|
const hours = Math.max(
|
|
45844
46016
|
1,
|
|
45845
46017
|
Number.parseInt(String(flags34.hours ?? 24), 10) || 24
|
|
@@ -45960,18 +46132,15 @@ none`
|
|
|
45960
46132
|
content: signalsMessage,
|
|
45961
46133
|
deploymentId: scope.deploymentId
|
|
45962
46134
|
});
|
|
45963
|
-
const tradesMessageWithAttachmentSummary = appendReportAttachmentSummary({
|
|
46135
|
+
const tradesMessageWithAttachmentSummary = includeDebug ? appendReportAttachmentSummary({
|
|
45964
46136
|
message: tradesMessage,
|
|
45965
46137
|
signalsFilename: signalsAttachment.filename,
|
|
45966
46138
|
filename: debugAttachment?.filename,
|
|
45967
46139
|
tradesCount: debugAttachment ? scopeTrades.length : void 0,
|
|
45968
46140
|
signalsCount: debugAttachment ? debugAttachment.summary?.signals ?? debugSignals.length : void 0,
|
|
45969
46141
|
evaluationsCount: debugAttachment ? debugAttachment.summary?.evaluations ?? 0 : void 0
|
|
45970
|
-
});
|
|
45971
|
-
const attachments = [
|
|
45972
|
-
signalsAttachment,
|
|
45973
|
-
...debugAttachment ? [debugAttachment] : []
|
|
45974
|
-
];
|
|
46142
|
+
}) : tradesMessage;
|
|
46143
|
+
const attachments = includeDebug ? [signalsAttachment, ...debugAttachment ? [debugAttachment] : []] : [];
|
|
45975
46144
|
if (flags34.printOnly) {
|
|
45976
46145
|
console.log(tradesMessageWithAttachmentSummary);
|
|
45977
46146
|
console.log("");
|
|
@@ -25,6 +25,7 @@ __export(runtimeFeedbackNotification_exports, {
|
|
|
25
25
|
notifyRuntimeFeedbackBundle: () => notifyRuntimeFeedbackBundle
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(runtimeFeedbackNotification_exports);
|
|
28
|
+
var import_userSettings = require("@tradejs/infra/userSettings");
|
|
28
29
|
|
|
29
30
|
// src/lib/runtimeFeedbackArtifacts.ts
|
|
30
31
|
var runtimeFeedbackArtifacts_exports = {};
|
|
@@ -210,11 +211,14 @@ var notifyRuntimeFeedbackBundle = async ({
|
|
|
210
211
|
}) => {
|
|
211
212
|
const verified = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(bundleDir);
|
|
212
213
|
const message = buildRuntimeFeedbackTelegramMessage(verified.replayEvidence);
|
|
213
|
-
await
|
|
214
|
+
const settings = await (0, import_userSettings.getUserSettings)(verified.manifest.userName);
|
|
215
|
+
const sent = settings.NOTIFY_RUNTIME_DEBUG !== false;
|
|
216
|
+
if (sent) await send(message, { userName: verified.manifest.userName });
|
|
214
217
|
return {
|
|
215
218
|
artifactId: verified.manifest.artifactId,
|
|
216
219
|
userName: verified.manifest.userName,
|
|
217
|
-
message
|
|
220
|
+
message,
|
|
221
|
+
sent
|
|
218
222
|
};
|
|
219
223
|
};
|
|
220
224
|
// Annotate the CommonJS export names for ESM import in node:
|