@tradejs/cli 3.1.29-beta.288 → 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 +250 -73
- 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 +181 -32
- package/dist/scripts/replayRunner.js +181 -32
- 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 = ({
|
|
@@ -16439,7 +16445,10 @@ var init_portfolioReplayConnector = __esm({
|
|
|
16439
16445
|
return {
|
|
16440
16446
|
__tradejsReplayConnector: true,
|
|
16441
16447
|
__tradejsTestConnector: true,
|
|
16442
|
-
capabilities:
|
|
16448
|
+
capabilities: {
|
|
16449
|
+
...connector.capabilities,
|
|
16450
|
+
orderSubmissionValidation: true
|
|
16451
|
+
},
|
|
16443
16452
|
universe: connector.universe,
|
|
16444
16453
|
accountId: connector.accountId,
|
|
16445
16454
|
deploymentId: connector.deploymentId,
|
|
@@ -16471,6 +16480,7 @@ var init_portfolioReplayConnector = __esm({
|
|
|
16471
16480
|
})
|
|
16472
16481
|
),
|
|
16473
16482
|
placeOrder: async (order) => {
|
|
16483
|
+
const { beforeSubmit, ...submittedOrder } = order;
|
|
16474
16484
|
if (positionsBySymbol.has(order.symbol)) {
|
|
16475
16485
|
return false;
|
|
16476
16486
|
}
|
|
@@ -16487,8 +16497,12 @@ var init_portfolioReplayConnector = __esm({
|
|
|
16487
16497
|
stage: "entry",
|
|
16488
16498
|
signal: order.signal
|
|
16489
16499
|
});
|
|
16500
|
+
await beforeSubmit?.({
|
|
16501
|
+
qty: order.qty,
|
|
16502
|
+
executionPrice: entryPrice
|
|
16503
|
+
});
|
|
16490
16504
|
const nextPosition = {
|
|
16491
|
-
...
|
|
16505
|
+
...submittedOrder,
|
|
16492
16506
|
timestamp: executionTimestamp ?? order.timestamp,
|
|
16493
16507
|
price: entryPrice,
|
|
16494
16508
|
signal: compactReplaySignal(order.signal),
|
|
@@ -16513,7 +16527,7 @@ var init_portfolioReplayConnector = __esm({
|
|
|
16513
16527
|
logOrder({
|
|
16514
16528
|
positionState,
|
|
16515
16529
|
data: {
|
|
16516
|
-
...
|
|
16530
|
+
...submittedOrder,
|
|
16517
16531
|
timestamp: executionTimestamp ?? order.timestamp,
|
|
16518
16532
|
price: entryPrice,
|
|
16519
16533
|
profit,
|
|
@@ -16641,6 +16655,79 @@ var init_hooks = __esm({
|
|
|
16641
16655
|
}
|
|
16642
16656
|
});
|
|
16643
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
|
+
|
|
16644
16731
|
// src/lib/replay/historicalSignalsReplaySkipEvidence.ts
|
|
16645
16732
|
var import_data3, replayScopeKey, appendReplaySignalEvaluationRun, createHistoricalReplaySkipEvidence;
|
|
16646
16733
|
var init_historicalSignalsReplaySkipEvidence = __esm({
|
|
@@ -16731,6 +16818,7 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16731
16818
|
"src/lib/replay/historicalSignalsReplayExecution.ts"() {
|
|
16732
16819
|
"use strict";
|
|
16733
16820
|
init_historicalSignalsReplayPreparation();
|
|
16821
|
+
init_historicalSignalsReplayDecisionTrace();
|
|
16734
16822
|
init_historicalSignalsReplaySkipEvidence();
|
|
16735
16823
|
advanceCycleMarket = async (plan, connector, timestamp) => {
|
|
16736
16824
|
const cycleSymbols = plan.symbolRuntimes.filter(
|
|
@@ -16763,6 +16851,7 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16763
16851
|
context.plan.runtimeLineages,
|
|
16764
16852
|
context.collectSkipEvidence
|
|
16765
16853
|
);
|
|
16854
|
+
const decisionTrace = createReplayDecisionTrace(context.decisionTraceTargets);
|
|
16766
16855
|
const reportProgress = (timestamp) => {
|
|
16767
16856
|
if (adapters.progress.enabled === false) return;
|
|
16768
16857
|
adapters.progress.tick({
|
|
@@ -16791,6 +16880,20 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16791
16880
|
status: "completed",
|
|
16792
16881
|
durationMs: adapters.clock.now() - cycleStartedAt
|
|
16793
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
|
+
}
|
|
16794
16897
|
advanceAbortedCycle(cycleSymbols, timestamp);
|
|
16795
16898
|
reportProgress(timestamp);
|
|
16796
16899
|
continue;
|
|
@@ -16801,6 +16904,17 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16801
16904
|
const btcCandle = symbolRuntime.btcReplayData[symbolRuntime.currentIndex];
|
|
16802
16905
|
const ethCandle = symbolRuntime.ethReplayData[symbolRuntime.currentIndex];
|
|
16803
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
|
+
}
|
|
16804
16918
|
continue;
|
|
16805
16919
|
}
|
|
16806
16920
|
for (const strategyRuntime of symbolRuntime.strategies) {
|
|
@@ -16809,6 +16923,12 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16809
16923
|
btcCandle,
|
|
16810
16924
|
ethCandle?.timestamp === candle.timestamp ? ethCandle : void 0
|
|
16811
16925
|
);
|
|
16926
|
+
decisionTrace.record(
|
|
16927
|
+
strategyRuntime.strategyName,
|
|
16928
|
+
symbolRuntime.symbol,
|
|
16929
|
+
candle,
|
|
16930
|
+
result
|
|
16931
|
+
);
|
|
16812
16932
|
skipEvidence.record({
|
|
16813
16933
|
strategyName: strategyRuntime.strategyName,
|
|
16814
16934
|
symbol: symbolRuntime.symbol,
|
|
@@ -16840,7 +16960,8 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
16840
16960
|
return {
|
|
16841
16961
|
signals: signals2,
|
|
16842
16962
|
abortedCycles,
|
|
16843
|
-
replayLineageScopes: skipEvidence.values()
|
|
16963
|
+
replayLineageScopes: skipEvidence.values(),
|
|
16964
|
+
replayDecisionTraces: decisionTrace.values()
|
|
16844
16965
|
};
|
|
16845
16966
|
};
|
|
16846
16967
|
}
|
|
@@ -16897,7 +17018,8 @@ var init_historicalSignalsReplayResults = __esm({
|
|
|
16897
17018
|
cycleCount: context.cycleCount,
|
|
16898
17019
|
abortedCycles: context.abortedCycles,
|
|
16899
17020
|
runtimeLineages: context.runtimeLineages,
|
|
16900
|
-
replayLineageScopes: context.replayLineageScopes
|
|
17021
|
+
replayLineageScopes: context.replayLineageScopes,
|
|
17022
|
+
...context.replayDecisionTraces?.length ? { replayDecisionTraces: context.replayDecisionTraces } : {}
|
|
16901
17023
|
});
|
|
16902
17024
|
compactHistoricalReplayResultForPortfolio = (result) => ({
|
|
16903
17025
|
...result,
|
|
@@ -16943,7 +17065,10 @@ var init_historicalSignalsReplayResults = __esm({
|
|
|
16943
17065
|
cycleCount: parts.reduce((sum3, part) => sum3 + part.cycleCount, 0),
|
|
16944
17066
|
abortedCycles: parts.reduce((sum3, part) => sum3 + part.abortedCycles, 0),
|
|
16945
17067
|
runtimeLineages: parts.flatMap((part) => part.runtimeLineages),
|
|
16946
|
-
replayLineageScopes: parts.flatMap((part) => part.replayLineageScopes)
|
|
17068
|
+
replayLineageScopes: parts.flatMap((part) => part.replayLineageScopes),
|
|
17069
|
+
replayDecisionTraces: parts.flatMap(
|
|
17070
|
+
(part) => part.replayDecisionTraces ?? []
|
|
17071
|
+
)
|
|
16947
17072
|
};
|
|
16948
17073
|
};
|
|
16949
17074
|
}
|
|
@@ -17119,7 +17244,8 @@ var init_historicalSignalsReplay = __esm({
|
|
|
17119
17244
|
references,
|
|
17120
17245
|
showProgress = true,
|
|
17121
17246
|
collectSkipEvidence = true,
|
|
17122
|
-
collectSignals = true
|
|
17247
|
+
collectSignals = true,
|
|
17248
|
+
decisionTraceTargets
|
|
17123
17249
|
}) => {
|
|
17124
17250
|
const memory = createReplayMemoryProfile();
|
|
17125
17251
|
memory?.("prepare:start");
|
|
@@ -17206,6 +17332,7 @@ var init_historicalSignalsReplay = __esm({
|
|
|
17206
17332
|
connector: replayConnector,
|
|
17207
17333
|
collectSkipEvidence,
|
|
17208
17334
|
collectSignals,
|
|
17335
|
+
decisionTraceTargets,
|
|
17209
17336
|
hooks: projectHooks,
|
|
17210
17337
|
hookContext
|
|
17211
17338
|
},
|
|
@@ -17242,7 +17369,8 @@ var init_historicalSignalsReplay = __esm({
|
|
|
17242
17369
|
cycleCount: plan.orderedTimestamps.length,
|
|
17243
17370
|
abortedCycles: execution.abortedCycles,
|
|
17244
17371
|
runtimeLineages: plan.runtimeLineages,
|
|
17245
|
-
replayLineageScopes: execution.replayLineageScopes
|
|
17372
|
+
replayLineageScopes: execution.replayLineageScopes,
|
|
17373
|
+
replayDecisionTraces: execution.replayDecisionTraces
|
|
17246
17374
|
});
|
|
17247
17375
|
memory?.("result:collected");
|
|
17248
17376
|
return result;
|
|
@@ -17479,6 +17607,7 @@ var init_runtimeParity = __esm({
|
|
|
17479
17607
|
direction: trade.direction,
|
|
17480
17608
|
qty: toFiniteNumberOrNull2(trade.qty),
|
|
17481
17609
|
timestamp: trade.entryTimestamp,
|
|
17610
|
+
...Number.isFinite(trade.signalTimestamp) ? { signalTimestamp: trade.signalTimestamp } : {},
|
|
17482
17611
|
price: toFiniteNumberOrNull2(trade.entryPrice),
|
|
17483
17612
|
orderId: trade.orderId,
|
|
17484
17613
|
signalId: typeof trade.signalId === "string" ? trade.signalId : void 0,
|
|
@@ -18399,6 +18528,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
18399
18528
|
"use strict";
|
|
18400
18529
|
import_trade2 = require("@tradejs/core/trade");
|
|
18401
18530
|
init_runtimeParity();
|
|
18531
|
+
init_historicalSignalsReplayDecisionTrace();
|
|
18402
18532
|
DEFAULT_REPLAY_PARITY_DETAILS_LIMIT = 500;
|
|
18403
18533
|
DEFAULT_REPLAY_PARITY_ARTIFACT_LIMIT = 100;
|
|
18404
18534
|
buildStrategyNameByOrderLinkKey = (strategyNames) => new Map(
|
|
@@ -18473,6 +18603,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
18473
18603
|
direction: entry.direction,
|
|
18474
18604
|
qty: entry.qty ?? null,
|
|
18475
18605
|
timestamp: entry.timestamp,
|
|
18606
|
+
...entry.signalTimestamp != null ? { signalTimestamp: entry.signalTimestamp } : {},
|
|
18476
18607
|
price: entry.price,
|
|
18477
18608
|
exitType: entry.exitType ?? null,
|
|
18478
18609
|
exitTimestamp: entry.exitTimestamp ?? null,
|
|
@@ -18546,7 +18677,8 @@ var init_runtimeParityDetails = __esm({
|
|
|
18546
18677
|
evaluations,
|
|
18547
18678
|
toleranceMs,
|
|
18548
18679
|
timestampOffsetMs,
|
|
18549
|
-
entryTimestampOffsetMs = 0
|
|
18680
|
+
entryTimestampOffsetMs = 0,
|
|
18681
|
+
matchDirection = false
|
|
18550
18682
|
}) => {
|
|
18551
18683
|
const entryStrategy2 = getEntryStrategy(entry);
|
|
18552
18684
|
if (!entryStrategy2) {
|
|
@@ -18556,7 +18688,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
18556
18688
|
let bestDiff = Number.POSITIVE_INFINITY;
|
|
18557
18689
|
const entryTimestamp = entry.timestamp + entryTimestampOffsetMs;
|
|
18558
18690
|
for (const evaluation of evaluations) {
|
|
18559
|
-
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) {
|
|
18560
18692
|
continue;
|
|
18561
18693
|
}
|
|
18562
18694
|
const diff = Math.abs(
|
|
@@ -18902,6 +19034,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
18902
19034
|
replaySignals = [],
|
|
18903
19035
|
replaySignalEvaluations = [],
|
|
18904
19036
|
replayLineageScopes = [],
|
|
19037
|
+
replayDecisionTraces = [],
|
|
18905
19038
|
runtimeLineageScopes = [],
|
|
18906
19039
|
toleranceMs,
|
|
18907
19040
|
backtestTimestampOffsetMs,
|
|
@@ -18910,48 +19043,66 @@ var init_runtimeParityDetails = __esm({
|
|
|
18910
19043
|
const nearestByEntry = new Map(
|
|
18911
19044
|
nearestCandidates.map((candidate) => [candidate.entry, candidate])
|
|
18912
19045
|
);
|
|
19046
|
+
const traceByCandle = new Map(
|
|
19047
|
+
replayDecisionTraces.map((trace) => [replayDecisionTraceKey(trace), trace])
|
|
19048
|
+
);
|
|
18913
19049
|
const artifactLimit = Math.min(limit, resolveReplayParityArtifactLimit());
|
|
18914
19050
|
let runtimeOnlyArtifactsIncluded = 0;
|
|
18915
19051
|
let backtestOnlyArtifactsIncluded = 0;
|
|
18916
19052
|
const runtimeOnlyDiagnostics = runtimeOnly.map((entry, index) => {
|
|
18917
|
-
const
|
|
18918
|
-
|
|
18919
|
-
|
|
18920
|
-
|
|
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
|
+
};
|
|
18921
19062
|
const includeArtifacts = index < artifactLimit;
|
|
18922
19063
|
const nearestCandidate = nearestByEntry.get(entry);
|
|
18923
|
-
const nearestReplaySignal = findNearestSignal({
|
|
18924
|
-
entry,
|
|
19064
|
+
const nearestReplaySignal = decisionEntry && findNearestSignal({
|
|
19065
|
+
entry: decisionEntry,
|
|
18925
19066
|
signals: replaySignals,
|
|
18926
|
-
|
|
18927
|
-
timestampOffsetMs: entryOffsetMs
|
|
19067
|
+
...decisionClock
|
|
18928
19068
|
});
|
|
18929
|
-
const nearestReplayEvaluation = findNearestEvaluation({
|
|
18930
|
-
entry,
|
|
19069
|
+
const nearestReplayEvaluation = decisionEntry && findNearestEvaluation({
|
|
19070
|
+
entry: decisionEntry,
|
|
18931
19071
|
evaluations: replaySignalEvaluations,
|
|
18932
|
-
|
|
18933
|
-
|
|
19072
|
+
matchDirection: isRuntimeTrade,
|
|
19073
|
+
...decisionClock
|
|
18934
19074
|
});
|
|
18935
|
-
const nearestReplayEvaluationOutcome = findNearestReplayEvaluationOutcome({
|
|
18936
|
-
entry,
|
|
19075
|
+
const nearestReplayEvaluationOutcome = decisionEntry && findNearestReplayEvaluationOutcome({
|
|
19076
|
+
entry: decisionEntry,
|
|
18937
19077
|
lineageScopes: replayLineageScopes,
|
|
18938
|
-
|
|
18939
|
-
timestampOffsetMs: entryOffsetMs
|
|
19078
|
+
...decisionClock
|
|
18940
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";
|
|
18941
19089
|
const classification = nearestReplaySignal ? classifySignalDiagnostic(nearestReplaySignal.signal) : nearestReplayEvaluation ? classifyEvaluationDiagnostic(nearestReplayEvaluation.evaluation) : nearestReplayEvaluationOutcome ? {
|
|
18942
|
-
classification:
|
|
19090
|
+
classification: nearestReplayEvaluationOutcome.reason.startsWith(
|
|
19091
|
+
"BACKTEST_ENTRY_DELAY_"
|
|
19092
|
+
) ? "entry_delayed" : "core_skipped",
|
|
18943
19093
|
reason: nearestReplayEvaluationOutcome.reason
|
|
18944
|
-
} : nearestCandidate?.nearest ? {
|
|
19094
|
+
} : !isRuntimeTrade && nearestCandidate?.nearest ? {
|
|
18945
19095
|
classification: "timing_or_price_drift",
|
|
18946
19096
|
reason: nearestCandidate.reason
|
|
18947
19097
|
} : {
|
|
18948
19098
|
classification: "no_replay_candidate",
|
|
18949
|
-
reason:
|
|
19099
|
+
reason: unavailableReason
|
|
18950
19100
|
};
|
|
18951
19101
|
return {
|
|
18952
19102
|
entry,
|
|
18953
19103
|
...classification,
|
|
18954
19104
|
...nearestCandidate ? { nearestCandidate } : {},
|
|
19105
|
+
...replayDecisionTrace ? { replayDecisionTrace } : {},
|
|
18955
19106
|
...nearestReplaySignal ? {
|
|
18956
19107
|
replaySignal: toSignalDiagnostic({
|
|
18957
19108
|
signal: nearestReplaySignal.signal,
|
|
@@ -19077,6 +19228,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
19077
19228
|
replaySignals,
|
|
19078
19229
|
replaySignalEvaluations,
|
|
19079
19230
|
replayLineageScopes,
|
|
19231
|
+
replayDecisionTraces,
|
|
19080
19232
|
runtimeLineageScopes
|
|
19081
19233
|
}) => {
|
|
19082
19234
|
const runtimeDetails = runtimeEntries.map(toRuntimeParityDetail);
|
|
@@ -19137,6 +19289,7 @@ var init_runtimeParityDetails = __esm({
|
|
|
19137
19289
|
replaySignals,
|
|
19138
19290
|
replaySignalEvaluations,
|
|
19139
19291
|
replayLineageScopes,
|
|
19292
|
+
replayDecisionTraces,
|
|
19140
19293
|
runtimeLineageScopes,
|
|
19141
19294
|
toleranceMs,
|
|
19142
19295
|
backtestTimestampOffsetMs,
|
|
@@ -20201,6 +20354,7 @@ var init_runtimeComparison = __esm({
|
|
|
20201
20354
|
replaySignals,
|
|
20202
20355
|
replayLineages,
|
|
20203
20356
|
replayLineageScopes,
|
|
20357
|
+
replayDecisionTraces,
|
|
20204
20358
|
runtimeEvidencePath
|
|
20205
20359
|
}) => {
|
|
20206
20360
|
const { connector, connectorName, window } = getRuntimeCompareContext();
|
|
@@ -20352,7 +20506,8 @@ var init_runtimeComparison = __esm({
|
|
|
20352
20506
|
replaySignals,
|
|
20353
20507
|
replaySignalEvaluations,
|
|
20354
20508
|
runtimeLineageScopes: comparable.runtimeLineageScopes,
|
|
20355
|
-
replayLineageScopes
|
|
20509
|
+
replayLineageScopes,
|
|
20510
|
+
replayDecisionTraces
|
|
20356
20511
|
});
|
|
20357
20512
|
const parityRows = summarizeTradeParityByStrategy({
|
|
20358
20513
|
runtimeEntries: runtimeDedupe.entries,
|
|
@@ -21330,6 +21485,7 @@ var init_replayRunner = __esm({
|
|
|
21330
21485
|
replaySignals: replayResult.signals,
|
|
21331
21486
|
replayLineages: replayResult.runtimeLineages,
|
|
21332
21487
|
replayLineageScopes: replayResult.replayLineageScopes,
|
|
21488
|
+
replayDecisionTraces: replayResult.replayDecisionTraces,
|
|
21333
21489
|
runtimeEvidencePath: replayRuntimeEvidencePath
|
|
21334
21490
|
});
|
|
21335
21491
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
@@ -21679,7 +21835,8 @@ var init_replayRunner = __esm({
|
|
|
21679
21835
|
references: historicalReplayReferences,
|
|
21680
21836
|
showProgress: !replayFlags.portfolioReport,
|
|
21681
21837
|
collectSkipEvidence: !replayFlags.portfolioReport,
|
|
21682
|
-
collectSignals: !replayFlags.portfolioReport
|
|
21838
|
+
collectSignals: !replayFlags.portfolioReport,
|
|
21839
|
+
decisionTraceTargets: replayFlags.portfolioReport ? void 0 : evidenceMetadata?.decisionTraceTargets
|
|
21683
21840
|
});
|
|
21684
21841
|
return replayFlags.portfolioReport ? compactHistoricalReplayResultForPortfolio(result) : result;
|
|
21685
21842
|
};
|
|
@@ -36431,13 +36588,14 @@ var init_runtimeFeedbackArtifacts = __esm({
|
|
|
36431
36588
|
});
|
|
36432
36589
|
|
|
36433
36590
|
// src/lib/runtimeFeedbackReplay.ts
|
|
36434
|
-
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;
|
|
36435
36592
|
var init_runtimeFeedbackReplay = __esm({
|
|
36436
36593
|
"src/lib/runtimeFeedbackReplay.ts"() {
|
|
36437
36594
|
"use strict";
|
|
36438
36595
|
import_node_child_process9 = require("child_process");
|
|
36439
36596
|
import_promises35 = __toESM(require("fs/promises"));
|
|
36440
36597
|
import_node_path32 = __toESM(require("path"));
|
|
36598
|
+
import_mcp2 = require("@tradejs/node/mcp");
|
|
36441
36599
|
init_runtimeEvidenceDeployment();
|
|
36442
36600
|
init_runtimeEvidenceArtifacts();
|
|
36443
36601
|
init_runtimeEvidenceProducer();
|
|
@@ -36571,44 +36729,58 @@ var init_runtimeFeedbackReplay = __esm({
|
|
|
36571
36729
|
env,
|
|
36572
36730
|
logHandle
|
|
36573
36731
|
}) => {
|
|
36574
|
-
await logHandle.
|
|
36575
|
-
|
|
36576
|
-
|
|
36577
|
-
|
|
36578
|
-
|
|
36579
|
-
|
|
36580
|
-
|
|
36581
|
-
|
|
36582
|
-
|
|
36583
|
-
};
|
|
36584
|
-
const child = (0, import_node_child_process9.spawn)(executable, command, {
|
|
36585
|
-
cwd,
|
|
36586
|
-
env,
|
|
36587
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
36588
|
-
});
|
|
36589
|
-
child.stdout.on("data", (chunk) => {
|
|
36590
|
-
process.stdout.write(chunk);
|
|
36591
|
-
appendLog(chunk);
|
|
36592
|
-
});
|
|
36593
|
-
child.stderr.on("data", (chunk) => {
|
|
36594
|
-
process.stderr.write(chunk);
|
|
36595
|
-
appendLog(chunk);
|
|
36596
|
-
});
|
|
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) => {
|
|
36597
36741
|
child.once("error", reject);
|
|
36598
36742
|
child.once("close", (code, signal) => {
|
|
36599
|
-
|
|
36600
|
-
|
|
36601
|
-
resolve();
|
|
36602
|
-
return;
|
|
36603
|
-
}
|
|
36743
|
+
if (code === 0) resolve();
|
|
36744
|
+
else {
|
|
36604
36745
|
reject(
|
|
36605
36746
|
new Error(
|
|
36606
36747
|
`Runtime feedback command failed: exit=${String(code)} signal=${String(signal)}`
|
|
36607
36748
|
)
|
|
36608
36749
|
);
|
|
36609
|
-
}
|
|
36750
|
+
}
|
|
36610
36751
|
});
|
|
36611
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
|
+
}
|
|
36612
36784
|
};
|
|
36613
36785
|
runRuntimeFeedbackReplay = async ({
|
|
36614
36786
|
runtimeEvidencePath,
|
|
@@ -36753,10 +36925,11 @@ var init_runtimeFeedbackReplay2 = __esm({
|
|
|
36753
36925
|
});
|
|
36754
36926
|
|
|
36755
36927
|
// src/lib/runtimeFeedbackNotification.ts
|
|
36756
|
-
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;
|
|
36757
36929
|
var init_runtimeFeedbackNotification = __esm({
|
|
36758
36930
|
"src/lib/runtimeFeedbackNotification.ts"() {
|
|
36759
36931
|
"use strict";
|
|
36932
|
+
import_userSettings7 = require("@tradejs/infra/userSettings");
|
|
36760
36933
|
init_runtimeFeedbackArtifacts();
|
|
36761
36934
|
init_telegramReports();
|
|
36762
36935
|
isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -36869,11 +37042,14 @@ var init_runtimeFeedbackNotification = __esm({
|
|
|
36869
37042
|
}) => {
|
|
36870
37043
|
const verified = await (0, runtimeFeedbackArtifacts_exports.verifyRuntimeFeedbackReplayBundle)(bundleDir);
|
|
36871
37044
|
const message = buildRuntimeFeedbackTelegramMessage(verified.replayEvidence);
|
|
36872
|
-
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 });
|
|
36873
37048
|
return {
|
|
36874
37049
|
artifactId: verified.manifest.artifactId,
|
|
36875
37050
|
userName: verified.manifest.userName,
|
|
36876
|
-
message
|
|
37051
|
+
message,
|
|
37052
|
+
sent
|
|
36877
37053
|
};
|
|
36878
37054
|
};
|
|
36879
37055
|
}
|
|
@@ -36911,7 +37087,9 @@ var init_runtimeFeedbackNotify = __esm({
|
|
|
36911
37087
|
}
|
|
36912
37088
|
const result = await notifyRuntimeFeedbackBundle({ bundleDir });
|
|
36913
37089
|
console.log(
|
|
36914
|
-
import_chalk45.default.green(
|
|
37090
|
+
import_chalk45.default.green(
|
|
37091
|
+
`Runtime feedback notification ${result.sent ? "sent" : "disabled"}: ${result.artifactId}`
|
|
37092
|
+
)
|
|
36915
37093
|
);
|
|
36916
37094
|
};
|
|
36917
37095
|
main39 = runtimeFeedbackNotify;
|
|
@@ -45294,11 +45472,12 @@ __export(signalsSummary_exports, {
|
|
|
45294
45472
|
main: () => main51,
|
|
45295
45473
|
signalsSummary: () => signalsSummary
|
|
45296
45474
|
});
|
|
45297
|
-
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;
|
|
45298
45476
|
var init_signalsSummary = __esm({
|
|
45299
45477
|
"src/scripts/signalsSummary.ts"() {
|
|
45300
45478
|
"use strict";
|
|
45301
45479
|
import_config13 = require("dotenv/config");
|
|
45480
|
+
import_userSettings8 = require("@tradejs/infra/userSettings");
|
|
45302
45481
|
import_args38 = __toESM(require("args"));
|
|
45303
45482
|
import_logger12 = require("@tradejs/infra/logger");
|
|
45304
45483
|
import_connectors19 = require("@tradejs/node/connectors");
|
|
@@ -45832,6 +46011,7 @@ none`
|
|
|
45832
46011
|
};
|
|
45833
46012
|
};
|
|
45834
46013
|
signalsSummary = async () => {
|
|
46014
|
+
const includeDebug = flags34.printOnly || (await (0, import_userSettings8.getUserSettings)(flags34.user)).NOTIFY_RUNTIME_DEBUG !== false;
|
|
45835
46015
|
const hours = Math.max(
|
|
45836
46016
|
1,
|
|
45837
46017
|
Number.parseInt(String(flags34.hours ?? 24), 10) || 24
|
|
@@ -45952,18 +46132,15 @@ none`
|
|
|
45952
46132
|
content: signalsMessage,
|
|
45953
46133
|
deploymentId: scope.deploymentId
|
|
45954
46134
|
});
|
|
45955
|
-
const tradesMessageWithAttachmentSummary = appendReportAttachmentSummary({
|
|
46135
|
+
const tradesMessageWithAttachmentSummary = includeDebug ? appendReportAttachmentSummary({
|
|
45956
46136
|
message: tradesMessage,
|
|
45957
46137
|
signalsFilename: signalsAttachment.filename,
|
|
45958
46138
|
filename: debugAttachment?.filename,
|
|
45959
46139
|
tradesCount: debugAttachment ? scopeTrades.length : void 0,
|
|
45960
46140
|
signalsCount: debugAttachment ? debugAttachment.summary?.signals ?? debugSignals.length : void 0,
|
|
45961
46141
|
evaluationsCount: debugAttachment ? debugAttachment.summary?.evaluations ?? 0 : void 0
|
|
45962
|
-
});
|
|
45963
|
-
const attachments = [
|
|
45964
|
-
signalsAttachment,
|
|
45965
|
-
...debugAttachment ? [debugAttachment] : []
|
|
45966
|
-
];
|
|
46142
|
+
}) : tradesMessage;
|
|
46143
|
+
const attachments = includeDebug ? [signalsAttachment, ...debugAttachment ? [debugAttachment] : []] : [];
|
|
45967
46144
|
if (flags34.printOnly) {
|
|
45968
46145
|
console.log(tradesMessageWithAttachmentSummary);
|
|
45969
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:
|