@tradejs/cli 3.1.16 → 3.1.17
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 +581 -839
- package/dist/lib/runtimeDebugEvidence.js +7 -20
- package/dist/lib/runtimeEvidenceArtifacts.js +165 -0
- package/dist/lib/runtimeEvidenceDeployment.js +84 -4
- package/dist/lib/runtimeEvidenceSync.js +171 -112
- package/dist/lib/runtimeLineage.js +28 -306
- package/dist/lib/runtimeRedis.js +1 -3
- package/dist/lib/runtimeScorecard.js +177 -135
- package/dist/lib/strategyRelease.js +1 -1
- package/dist/scripts/replay.js +165 -370
- package/dist/scripts/replayRunner.js +165 -370
- package/dist/scripts/replayRuntimeEvidence.js +5 -16
- package/dist/scripts/runtimeEvidence.js +319 -187
- package/dist/scripts/runtimeEvidenceSync.js +172 -106
- package/dist/scripts/runtimeParity.js +1 -3
- package/dist/scripts/runtimeScorecard.js +220 -167
- package/dist/scripts/signals.js +47 -316
- package/dist/scripts/signalsDaemon.js +47 -316
- package/dist/scripts/signalsSummary.js +3 -8
- package/package.json +7 -7
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/lib/runtimeScorecard.ts
|
|
@@ -36,21 +26,7 @@ __export(runtimeScorecard_exports, {
|
|
|
36
26
|
module.exports = __toCommonJS(runtimeScorecard_exports);
|
|
37
27
|
|
|
38
28
|
// src/lib/runtimeLineage.ts
|
|
39
|
-
var import_node_child_process = require("child_process");
|
|
40
|
-
var import_node_crypto2 = require("crypto");
|
|
41
|
-
var import_promises2 = __toESM(require("fs/promises"));
|
|
42
|
-
var import_node_path2 = __toESM(require("path"));
|
|
43
|
-
var import_types = require("@tradejs/types");
|
|
44
|
-
var import_strategies = require("@tradejs/node/strategies");
|
|
45
|
-
var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
|
|
46
|
-
|
|
47
|
-
// src/lib/strategyGateFingerprint.ts
|
|
48
29
|
var import_node_crypto = require("crypto");
|
|
49
|
-
var import_node_module = require("module");
|
|
50
|
-
var import_promises = __toESM(require("fs/promises"));
|
|
51
|
-
var import_node_path = __toESM(require("path"));
|
|
52
|
-
|
|
53
|
-
// src/lib/runtimeLineage.ts
|
|
54
30
|
var normalizeForStableJson = (value) => {
|
|
55
31
|
if (Array.isArray(value)) {
|
|
56
32
|
return value.map(normalizeForStableJson);
|
|
@@ -62,26 +38,174 @@ var normalizeForStableJson = (value) => {
|
|
|
62
38
|
}
|
|
63
39
|
return value;
|
|
64
40
|
};
|
|
65
|
-
var fingerprintRuntimeValue = (value) => (0,
|
|
66
|
-
var runtimeLineageKey = (lineage) =>
|
|
41
|
+
var fingerprintRuntimeValue = (value) => (0, import_node_crypto.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
|
|
42
|
+
var runtimeLineageKey = (lineage) => [
|
|
67
43
|
"v3",
|
|
68
44
|
lineage.deploymentCompositionId,
|
|
69
45
|
lineage.strategyRevision,
|
|
70
46
|
lineage.strategyPackageVersion,
|
|
71
|
-
`deps:${fingerprintRuntimeValue(
|
|
72
|
-
lineage.strategyDependencyVersions
|
|
73
|
-
).slice(0, 16)}`,
|
|
47
|
+
`deps:${fingerprintRuntimeValue(lineage.strategyDependencyVersions).slice(0, 16)}`,
|
|
74
48
|
lineage.runtimePackageVersion
|
|
75
|
-
].join(":") : [
|
|
76
|
-
lineage.schemaVersion,
|
|
77
|
-
lineage.compositionId ?? "unbound-composition",
|
|
78
|
-
lineage.gitSha ?? "unknown",
|
|
79
|
-
lineage.gitDirty == null ? "unknown" : lineage.gitDirty ? "dirty" : "clean",
|
|
80
|
-
lineage.gateFingerprint,
|
|
81
|
-
lineage.configFingerprint,
|
|
82
|
-
lineage.contextFingerprint
|
|
83
49
|
].join(":");
|
|
84
50
|
|
|
51
|
+
// src/lib/runtimeEvidenceDeployment.ts
|
|
52
|
+
var import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
|
|
53
|
+
var isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
54
|
+
var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
|
|
55
|
+
var isPackageVersionMap = (value) => isRecord(value) && Object.keys(value).length > 0 && Object.entries(value).every(
|
|
56
|
+
([name, version]) => name.startsWith("@tradejs/") && isNonEmptyString(version)
|
|
57
|
+
);
|
|
58
|
+
var INTERVALS = /* @__PURE__ */ new Set([
|
|
59
|
+
"1",
|
|
60
|
+
"3",
|
|
61
|
+
"5",
|
|
62
|
+
"15",
|
|
63
|
+
"30",
|
|
64
|
+
"60",
|
|
65
|
+
"120",
|
|
66
|
+
"240",
|
|
67
|
+
"360",
|
|
68
|
+
"720",
|
|
69
|
+
"D",
|
|
70
|
+
"W",
|
|
71
|
+
"M"
|
|
72
|
+
]);
|
|
73
|
+
var UNIVERSES = /* @__PURE__ */ new Set(["crypto", "tradfi"]);
|
|
74
|
+
var isRuntimeStrategySelection = (value) => value === void 0 || isRecord(value) && Object.keys(value).length === 1 && Object.keys(value).every((key) => key === "tickers") && Array.isArray(value.tickers) && value.tickers.length > 0 && value.tickers.every((ticker) => isNonEmptyString(ticker));
|
|
75
|
+
var samePackageVersions = (left, right) => {
|
|
76
|
+
if (!left || !right) return false;
|
|
77
|
+
const leftEntries = Object.entries(left).sort(
|
|
78
|
+
([a], [b]) => a.localeCompare(b)
|
|
79
|
+
);
|
|
80
|
+
const rightEntries = Object.entries(right).sort(
|
|
81
|
+
([a], [b]) => a.localeCompare(b)
|
|
82
|
+
);
|
|
83
|
+
return JSON.stringify(leftEntries) === JSON.stringify(rightEntries);
|
|
84
|
+
};
|
|
85
|
+
var runtimeLineageMatchesStrategySnapshot = ({
|
|
86
|
+
lineage,
|
|
87
|
+
deployment,
|
|
88
|
+
strategy
|
|
89
|
+
}) => lineage?.schemaVersion === 3 && lineage.strategyRevision === strategy.strategyRevision && lineage.deploymentCompositionId === deployment.deploymentCompositionId && lineage.strategyPackageVersion === strategy.strategyPackageVersion && lineage.runtimePackageVersion === strategy.runtimePackageVersion && samePackageVersions(
|
|
90
|
+
lineage.strategyDependencyVersions,
|
|
91
|
+
strategy.strategyDependencyVersions
|
|
92
|
+
);
|
|
93
|
+
var parseRuntimeEvidenceDeploymentSnapshot = (value) => {
|
|
94
|
+
if (!isRecord(value) || value.schemaVersion !== 2 || !isNonEmptyString(value.id) || !isNonEmptyString(value.deploymentCompositionId) || !/^dc1:[a-f0-9]{16}$/.test(value.deploymentCompositionId) || !isNonEmptyString(value.label) || !isNonEmptyString(value.connectorName) || !isNonEmptyString(value.provider) || !isNonEmptyString(value.accountId) || typeof value.enabled !== "boolean" || !Array.isArray(value.strategies)) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
"Runtime evidence deployment snapshot is missing or invalid"
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
const strategies = value.strategies.map((candidate) => {
|
|
100
|
+
if (!isRecord(candidate) || !isNonEmptyString(candidate.strategyName) || !isNonEmptyString(candidate.strategyRevision) || !/^sr1:[a-f0-9]{16}$/.test(candidate.strategyRevision) || typeof candidate.enabled !== "boolean" || !["active", "entries_paused"].includes(String(candidate.controlState)) || !INTERVALS.has(String(candidate.interval)) || !UNIVERSES.has(String(candidate.universe)) || !isNonEmptyString(candidate.strategyPackage) || !isNonEmptyString(candidate.strategyPackageVersion) || !isPackageVersionMap(candidate.strategyDependencyVersions) || !isNonEmptyString(candidate.runtimePackageVersion) || !isRecord(candidate.strategyConfig) || !isRuntimeStrategySelection(candidate.selection)) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
"Runtime evidence deployment strategy snapshot is invalid"
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
if (String(candidate.strategyConfig.INTERVAL) !== String(candidate.interval) || String(candidate.strategyConfig.UNIVERSE) !== String(candidate.universe)) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Runtime evidence strategy config does not match its scope: ${candidate.strategyName}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
if (candidate.accountId != null && (!isNonEmptyString(candidate.accountId) || candidate.accountId !== value.accountId)) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Runtime evidence strategy account does not match deployment: ${candidate.strategyName}`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
return candidate;
|
|
116
|
+
});
|
|
117
|
+
const identities = /* @__PURE__ */ new Set();
|
|
118
|
+
for (const strategy of strategies) {
|
|
119
|
+
if (identities.has(strategy.strategyName)) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
`Duplicate runtime evidence strategy: ${strategy.strategyName}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
identities.add(strategy.strategyName);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
...value,
|
|
128
|
+
strategies
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
var activeRuntimeEvidenceStrategies = (deployment) => deployment.enabled ? deployment.strategies.filter((strategy) => strategy.enabled) : [];
|
|
132
|
+
var unwrapRuntimeEvidenceRows = (value, field) => (Array.isArray(value) ? value : []).map((candidate) => {
|
|
133
|
+
const record = isRecord(candidate) ? candidate : null;
|
|
134
|
+
const nested = record && isRecord(record[field]) ? record[field] : null;
|
|
135
|
+
return nested ?? record;
|
|
136
|
+
}).filter((record) => record != null);
|
|
137
|
+
var assertCurrentRuntimeEvidenceArtifact = (artifact) => {
|
|
138
|
+
if (!isRecord(artifact) || artifact.reportType !== "runtime-evidence") {
|
|
139
|
+
throw new Error("Invalid runtime evidence artifact");
|
|
140
|
+
}
|
|
141
|
+
const deployment = parseRuntimeEvidenceDeploymentSnapshot(
|
|
142
|
+
artifact.deployment
|
|
143
|
+
);
|
|
144
|
+
const activeStrategies = activeRuntimeEvidenceStrategies(deployment);
|
|
145
|
+
if (activeStrategies.length === 0) {
|
|
146
|
+
throw new Error("Runtime evidence deployment has no enabled strategies");
|
|
147
|
+
}
|
|
148
|
+
const runtime = isRecord(artifact.runtime) ? artifact.runtime : null;
|
|
149
|
+
if (!runtime) {
|
|
150
|
+
throw new Error("Runtime evidence payload is missing");
|
|
151
|
+
}
|
|
152
|
+
if ("strategyConfigs" in runtime) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
"Runtime evidence payload contains removed strategyConfigs data"
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const rowFields = [
|
|
158
|
+
"trades",
|
|
159
|
+
"signals",
|
|
160
|
+
"evaluations",
|
|
161
|
+
"lineageScopes"
|
|
162
|
+
];
|
|
163
|
+
for (const field of rowFields) {
|
|
164
|
+
if (!Array.isArray(runtime[field])) {
|
|
165
|
+
throw new Error(`Runtime evidence payload ${field} must be an array`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const snapshots = new Map(
|
|
169
|
+
activeStrategies.map((strategy) => [strategy.strategyName, strategy])
|
|
170
|
+
);
|
|
171
|
+
const assertRows = (label, rows, lineageField) => {
|
|
172
|
+
for (const row of rows) {
|
|
173
|
+
const strategyName = String(row.strategy ?? "").trim();
|
|
174
|
+
const strategy = snapshots.get(strategyName);
|
|
175
|
+
if (!strategy || row.deploymentId !== deployment.id || row.accountId !== deployment.accountId || !runtimeLineageMatchesStrategySnapshot({
|
|
176
|
+
lineage: isRecord(row[lineageField]) ? row[lineageField] : void 0,
|
|
177
|
+
deployment,
|
|
178
|
+
strategy
|
|
179
|
+
})) {
|
|
180
|
+
throw new Error(
|
|
181
|
+
`Runtime evidence ${label} row is outside the current embedded deployment lineage`
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
assertRows(
|
|
187
|
+
"trade",
|
|
188
|
+
unwrapRuntimeEvidenceRows(runtime.trades, "trade"),
|
|
189
|
+
"runtimeLineage"
|
|
190
|
+
);
|
|
191
|
+
assertRows(
|
|
192
|
+
"signal",
|
|
193
|
+
unwrapRuntimeEvidenceRows(runtime.signals, "signal"),
|
|
194
|
+
"runtimeLineage"
|
|
195
|
+
);
|
|
196
|
+
assertRows(
|
|
197
|
+
"evaluation",
|
|
198
|
+
unwrapRuntimeEvidenceRows(runtime.evaluations, "evaluation"),
|
|
199
|
+
"runtimeLineage"
|
|
200
|
+
);
|
|
201
|
+
assertRows(
|
|
202
|
+
"lineage scope",
|
|
203
|
+
unwrapRuntimeEvidenceRows(runtime.lineageScopes, "lineageScope"),
|
|
204
|
+
"lineage"
|
|
205
|
+
);
|
|
206
|
+
return deployment;
|
|
207
|
+
};
|
|
208
|
+
|
|
85
209
|
// src/lib/runtimeScorecard.ts
|
|
86
210
|
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
87
211
|
var asArray = (value) => Array.isArray(value) ? value : [];
|
|
@@ -120,75 +244,6 @@ var extractRuntimeRows = (artifact) => {
|
|
|
120
244
|
statsBuckets: asArray(runtime.evaluationStatsBuckets).map(asRecord).filter((item) => item != null)
|
|
121
245
|
};
|
|
122
246
|
};
|
|
123
|
-
var buildRuntimeLineageSummary = (rows) => {
|
|
124
|
-
const lineageRows = [
|
|
125
|
-
...rows.evaluations,
|
|
126
|
-
...rows.signals,
|
|
127
|
-
...rows.trades,
|
|
128
|
-
...rows.lineageScopes.map((scope) => ({
|
|
129
|
-
runtimeLineage: scope.lineage
|
|
130
|
-
}))
|
|
131
|
-
];
|
|
132
|
-
const lineages = lineageRows.map((row) => asRecord(row.runtimeLineage)).filter((lineage) => lineage != null);
|
|
133
|
-
const identities = /* @__PURE__ */ new Map();
|
|
134
|
-
for (const lineage of lineages) {
|
|
135
|
-
const identity2 = lineage.schemaVersion === 3 ? {
|
|
136
|
-
schemaVersion: 3,
|
|
137
|
-
strategyRevision: finiteString(lineage.strategyRevision),
|
|
138
|
-
deploymentCompositionId: finiteString(
|
|
139
|
-
lineage.deploymentCompositionId
|
|
140
|
-
),
|
|
141
|
-
strategyPackageVersion: finiteString(
|
|
142
|
-
lineage.strategyPackageVersion
|
|
143
|
-
),
|
|
144
|
-
strategyDependencyVersions: packageVersionMap(
|
|
145
|
-
lineage.strategyDependencyVersions
|
|
146
|
-
),
|
|
147
|
-
runtimePackageVersion: finiteString(lineage.runtimePackageVersion),
|
|
148
|
-
maxLossValue: finiteNumber(lineage.maxLossValue)
|
|
149
|
-
} : {
|
|
150
|
-
schemaVersion: 1,
|
|
151
|
-
compositionId: finiteString(lineage.compositionId),
|
|
152
|
-
gitSha: finiteString(lineage.gitSha),
|
|
153
|
-
gitDirty: typeof lineage.gitDirty === "boolean" ? lineage.gitDirty : null,
|
|
154
|
-
gateFingerprint: finiteString(lineage.gateFingerprint),
|
|
155
|
-
configFingerprint: finiteString(lineage.configFingerprint),
|
|
156
|
-
contextFingerprint: finiteString(lineage.contextFingerprint),
|
|
157
|
-
maxLossValue: finiteNumber(lineage.maxLossValue)
|
|
158
|
-
};
|
|
159
|
-
identities.set(JSON.stringify(identity2), identity2);
|
|
160
|
-
}
|
|
161
|
-
const identity = identities.size === 1 ? [...identities.values()][0] : null;
|
|
162
|
-
const schemaVersion = finiteNumber(identity?.schemaVersion);
|
|
163
|
-
const identityComplete = lineages.length > 0 && identity != null && (schemaVersion === 3 && finiteString(identity.strategyRevision) != null && finiteString(identity.deploymentCompositionId) != null && finiteString(identity.strategyPackageVersion) != null && packageVersionMap(identity.strategyDependencyVersions) != null && finiteString(identity.runtimePackageVersion) != null || schemaVersion === 1 && identity.compositionId != null && identity.gitSha != null && identity.gitDirty === false && identity.gateFingerprint != null && identity.configFingerprint != null && identity.contextFingerprint != null) && identity.maxLossValue != null;
|
|
164
|
-
const coverageComplete = lineageRows.length > 0 && lineages.length === lineageRows.length;
|
|
165
|
-
const complete = identityComplete && coverageComplete;
|
|
166
|
-
const lineageKey = identityComplete ? runtimeLineageKey(identity) : null;
|
|
167
|
-
return {
|
|
168
|
-
complete,
|
|
169
|
-
identityComplete,
|
|
170
|
-
coverageComplete,
|
|
171
|
-
conflicts: identities.size > 1,
|
|
172
|
-
rows: lineageRows.length,
|
|
173
|
-
rowsWithLineage: lineages.length,
|
|
174
|
-
schemaVersion,
|
|
175
|
-
lineageKey,
|
|
176
|
-
strategyRevision: finiteString(identity?.strategyRevision),
|
|
177
|
-
deploymentCompositionId: finiteString(identity?.deploymentCompositionId),
|
|
178
|
-
strategyPackageVersion: finiteString(identity?.strategyPackageVersion),
|
|
179
|
-
strategyDependencyVersions: packageVersionMap(
|
|
180
|
-
identity?.strategyDependencyVersions
|
|
181
|
-
),
|
|
182
|
-
runtimePackageVersion: finiteString(identity?.runtimePackageVersion),
|
|
183
|
-
compositionId: finiteString(identity?.compositionId),
|
|
184
|
-
gitSha: finiteString(identity?.gitSha),
|
|
185
|
-
gitDirty: typeof identity?.gitDirty === "boolean" ? identity.gitDirty : null,
|
|
186
|
-
gateFingerprint: finiteString(identity?.gateFingerprint),
|
|
187
|
-
configFingerprint: finiteString(identity?.configFingerprint),
|
|
188
|
-
contextFingerprint: finiteString(identity?.contextFingerprint),
|
|
189
|
-
maxLossValue: finiteNumber(identity?.maxLossValue)
|
|
190
|
-
};
|
|
191
|
-
};
|
|
192
247
|
var buildEmbeddedLineageScope = ({
|
|
193
248
|
artifact,
|
|
194
249
|
rows,
|
|
@@ -300,12 +355,6 @@ var buildEmbeddedLineageScope = ({
|
|
|
300
355
|
strategyPackageVersion: singleTarget?.strategyPackageVersion ?? null,
|
|
301
356
|
strategyDependencyVersions: singleTarget?.strategyDependencyVersions ?? null,
|
|
302
357
|
runtimePackageVersion: singleTarget?.runtimePackageVersion ?? null,
|
|
303
|
-
compositionId: null,
|
|
304
|
-
gitSha: null,
|
|
305
|
-
gitDirty: null,
|
|
306
|
-
gateFingerprint: null,
|
|
307
|
-
configFingerprint: null,
|
|
308
|
-
contextFingerprint: null,
|
|
309
358
|
maxLossValue: commonRiskValues.size === 1 ? [...commonRiskValues][0] : null,
|
|
310
359
|
strategyScopes: Object.fromEntries(
|
|
311
360
|
targetValues.map((target) => [
|
|
@@ -321,12 +370,6 @@ var buildEmbeddedLineageScope = ({
|
|
|
321
370
|
}
|
|
322
371
|
};
|
|
323
372
|
};
|
|
324
|
-
var belongsToRuntimeLineage = (row, summary) => {
|
|
325
|
-
if (!summary.identityComplete || !summary.lineageKey) return false;
|
|
326
|
-
const lineage = asRecord(row.runtimeLineage);
|
|
327
|
-
if (!lineage) return false;
|
|
328
|
-
return runtimeLineageKey(lineage) === summary.lineageKey && finiteNumber(lineage.maxLossValue) === summary.maxLossValue;
|
|
329
|
-
};
|
|
330
373
|
var runtimeDeploymentBinding = (artifact) => {
|
|
331
374
|
const deployment = asRecord(asRecord(artifact)?.deployment);
|
|
332
375
|
return {
|
|
@@ -508,10 +551,6 @@ var replayCountsForStrategy = (replayComparison, strategy) => {
|
|
|
508
551
|
runtimeOnly: finiteNumber(counts?.runtimeOnly) ?? 0
|
|
509
552
|
};
|
|
510
553
|
};
|
|
511
|
-
var getCalibrationSummary = (artifact) => {
|
|
512
|
-
const root = asRecord(artifact) ?? {};
|
|
513
|
-
return asRecord(asRecord(root.summary)?.all) ?? null;
|
|
514
|
-
};
|
|
515
554
|
var getProspectiveSummary = (artifact) => {
|
|
516
555
|
const root = asRecord(artifact);
|
|
517
556
|
if (!root || root.reportType !== "strategy-prospective-evidence") return null;
|
|
@@ -537,6 +576,10 @@ var buildRuntimeScorecard = ({
|
|
|
537
576
|
strategy = null,
|
|
538
577
|
llmComparatorPolicy = "ai_approved_only"
|
|
539
578
|
}) => {
|
|
579
|
+
assertCurrentRuntimeEvidenceArtifact(runtimeArtifact);
|
|
580
|
+
for (const artifact of historyRuntimeArtifacts) {
|
|
581
|
+
assertCurrentRuntimeEvidenceArtifact(artifact);
|
|
582
|
+
}
|
|
540
583
|
const scopedRuntimeArtifact = filterArtifactByStrategy(
|
|
541
584
|
runtimeArtifact,
|
|
542
585
|
strategy
|
|
@@ -551,7 +594,12 @@ var buildRuntimeScorecard = ({
|
|
|
551
594
|
rows,
|
|
552
595
|
strategy
|
|
553
596
|
});
|
|
554
|
-
|
|
597
|
+
if (!embeddedLineageScope) {
|
|
598
|
+
throw new Error(
|
|
599
|
+
"Runtime scorecard requires the current embedded deployment lineage"
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
const runtimeLineage = embeddedLineageScope.summary;
|
|
555
603
|
const window = runtimeWindow(runtimeArtifact);
|
|
556
604
|
const startTime = finiteNumber(window.startTime) ?? generatedAt - 864e5;
|
|
557
605
|
const endTime = finiteNumber(window.endTime) ?? generatedAt;
|
|
@@ -599,32 +647,26 @@ var buildRuntimeScorecard = ({
|
|
|
599
647
|
const lineage = asRecord(replayComparison?.lineage);
|
|
600
648
|
const lineageReason = finiteString(lineage?.reason);
|
|
601
649
|
const calibrationRoot = asRecord(calibrationArtifact) ?? {};
|
|
602
|
-
const
|
|
603
|
-
const calibrationSamples = asArray(calibrationRoot.samples).map(asRecord).filter((item) => item != null).filter((item) => !strategy || finiteString(item.strategy) === strategy).filter(
|
|
604
|
-
(item) => !embeddedLineageScope || embeddedLineageScope.belongs(item)
|
|
605
|
-
);
|
|
650
|
+
const calibrationSamples = asArray(calibrationRoot.samples).map(asRecord).filter((item) => item != null).filter((item) => !strategy || finiteString(item.strategy) === strategy).filter((item) => embeddedLineageScope.belongs(item));
|
|
606
651
|
const averageSampleMetric = (field) => {
|
|
607
652
|
const values = calibrationSamples.map((sample) => finiteNumber(sample[field])).filter((value) => value != null);
|
|
608
653
|
return values.length ? round(sum(values) / values.length) : null;
|
|
609
654
|
};
|
|
610
|
-
const
|
|
611
|
-
const
|
|
612
|
-
const residualVsModelBps = embeddedLineageScope ? averageSampleMetric("residualVsCurrentModelBps") : finiteNumber(
|
|
613
|
-
asRecord(fallbackCalibration?.residualVsCurrentModelBps)?.avg
|
|
614
|
-
);
|
|
655
|
+
const actualSlippageBps = averageSampleMetric("signalToFillAdverseBps");
|
|
656
|
+
const residualVsModelBps = averageSampleMetric("residualVsCurrentModelBps");
|
|
615
657
|
const prospective = getProspectiveSummary(prospectiveEvidenceArtifact);
|
|
616
658
|
const historyTrades = dedupeTrades([
|
|
617
659
|
...scopedHistoryArtifacts,
|
|
618
660
|
scopedRuntimeArtifact
|
|
619
661
|
]);
|
|
620
662
|
const comparableHistoryTrades = historyTrades.filter(
|
|
621
|
-
(trade) => belongsToRuntimeDeployment(trade, deploymentBinding) &&
|
|
663
|
+
(trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && embeddedLineageScope.belongs(trade)
|
|
622
664
|
);
|
|
623
665
|
const comparableCurrentClosedTrades = currentClosedTrades.filter(
|
|
624
|
-
(trade) => belongsToRuntimeDeployment(trade, deploymentBinding) &&
|
|
666
|
+
(trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && embeddedLineageScope.belongs(trade)
|
|
625
667
|
);
|
|
626
668
|
const comparableFills = rows.trades.filter(
|
|
627
|
-
(trade) => belongsToRuntimeDeployment(trade, deploymentBinding) &&
|
|
669
|
+
(trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && embeddedLineageScope.belongs(trade)
|
|
628
670
|
);
|
|
629
671
|
const currentDistributions = buildDistributions(rows);
|
|
630
672
|
const previousArtifact = scopedHistoryArtifacts.map((artifact) => ({ artifact, window: runtimeWindow(artifact) })).filter(({ window: candidateWindow }) => {
|
|
@@ -122,7 +122,7 @@ var buildStrategyLiveDiagnosisFromScorecard = ({
|
|
|
122
122
|
);
|
|
123
123
|
const orderFailureRate = scorecard.funnel.orderAttempts ? scorecard.funnel.orderFailures / scorecard.funnel.orderAttempts : null;
|
|
124
124
|
const lineage = scorecard.lineage;
|
|
125
|
-
const lineageComparable = scorecard.parity.lineageReason == null && lineage?.complete === true && lineage.conflicts === false && lineage.
|
|
125
|
+
const lineageComparable = scorecard.parity.lineageReason == null && lineage?.complete === true && lineage.conflicts === false && lineage.schemaVersion === 3 && lineage.strategyRevision != null && lineage.deploymentCompositionId != null && lineage.strategyPackageVersion != null && lineage.strategyDependencyVersions != null && lineage.runtimePackageVersion != null;
|
|
126
126
|
const releaseMaxLossValue = manifest.composition.maxLossValue;
|
|
127
127
|
const runtimeMaxLossValue = lineage?.maxLossValue ?? null;
|
|
128
128
|
const riskScaleComparable = Number.isFinite(releaseMaxLossValue) && releaseMaxLossValue > 0 && runtimeMaxLossValue != null && Number.isFinite(runtimeMaxLossValue) && runtimeMaxLossValue > 0;
|