@tradejs/cli 3.1.29-beta.289 → 3.1.29-beta.291
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 +2574 -1236
- package/dist/lib/aiPocketSearch.js +37 -3
- package/dist/lib/aiTrainDataset.js +1 -0
- package/dist/lib/aiTrainEvaluationDump.js +7 -2
- package/dist/lib/aiTrainResearch.js +11 -7
- package/dist/lib/coreResearch.js +12 -4
- package/dist/lib/researchMetricSnapshot.js +74 -0
- package/dist/lib/researchVisuals.js +910 -0
- 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/lib/strategyRelease.js +8 -2
- package/dist/lib/strategyResearch.js +133 -33
- package/dist/lib/tickerProfiles.js +76 -0
- package/dist/scripts/aiPocketSearch.js +38 -3
- package/dist/scripts/aiTrain.js +29 -17
- package/dist/scripts/coreResearch.js +12 -4
- package/dist/scripts/replay.js +223 -33
- package/dist/scripts/replayRunner.js +223 -33
- package/dist/scripts/researchVisuals.js +955 -0
- 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/dist/scripts/strategyRelease.js +59 -7
- package/dist/scripts/strategyResearch.js +136 -36
- package/dist/scripts/tickerProfiles.js +114 -0
- package/package.json +8 -7
|
@@ -34,6 +34,7 @@ __export(aiPocketSearch_exports, {
|
|
|
34
34
|
module.exports = __toCommonJS(aiPocketSearch_exports);
|
|
35
35
|
|
|
36
36
|
// src/lib/aiPocketSearch/features.ts
|
|
37
|
+
var import_aiFeatures = require("@tradejs/core/aiFeatures");
|
|
37
38
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
38
39
|
var DAYS_PER_WEEK = 7;
|
|
39
40
|
var DAYS_PER_MONTH = 30.4375;
|
|
@@ -402,15 +403,25 @@ var addFlattenedFeatures = ({
|
|
|
402
403
|
value,
|
|
403
404
|
segments,
|
|
404
405
|
maxDepth,
|
|
405
|
-
shouldSkipPath = () => false
|
|
406
|
+
shouldSkipPath = () => false,
|
|
407
|
+
onFeatureExcluded
|
|
406
408
|
}) => {
|
|
407
409
|
if (!segments.length && !isPlainRecord(value)) {
|
|
408
410
|
return;
|
|
409
411
|
}
|
|
410
|
-
if (segments.length > maxDepth || isOutcomePath(segments)
|
|
412
|
+
if (segments.length > maxDepth || isOutcomePath(segments)) {
|
|
413
|
+
onFeatureExcluded?.({
|
|
414
|
+
path: segments.join("."),
|
|
415
|
+
classification: segments.length > maxDepth ? "depth-limit" : "derived-policy"
|
|
416
|
+
});
|
|
411
417
|
return;
|
|
412
418
|
}
|
|
419
|
+
if (shouldSkipPath(segments)) return;
|
|
413
420
|
if (Array.isArray(value)) {
|
|
421
|
+
onFeatureExcluded?.({
|
|
422
|
+
path: segments.join("."),
|
|
423
|
+
classification: "unprojected-array"
|
|
424
|
+
});
|
|
414
425
|
return;
|
|
415
426
|
}
|
|
416
427
|
if (isFeaturePrimitive(value)) {
|
|
@@ -432,7 +443,8 @@ var addFlattenedFeatures = ({
|
|
|
432
443
|
value: child,
|
|
433
444
|
segments: [...segments, key],
|
|
434
445
|
maxDepth,
|
|
435
|
-
shouldSkipPath
|
|
446
|
+
shouldSkipPath,
|
|
447
|
+
onFeatureExcluded
|
|
436
448
|
});
|
|
437
449
|
}
|
|
438
450
|
};
|
|
@@ -644,7 +656,10 @@ var collectAiPocketFeatureSnapshot = ({
|
|
|
644
656
|
value: source,
|
|
645
657
|
segments: [],
|
|
646
658
|
maxDepth: 8,
|
|
659
|
+
onFeatureExcluded,
|
|
647
660
|
shouldSkipPath: (segments) => {
|
|
661
|
+
if (segments.join(".") === "additionalIndicators.baseContext.tickerProfile" || segments.join(".") === "additionalIndicators.tickerProfile" || segments.join(".") === "additionalIndicators.portfolioContext")
|
|
662
|
+
return true;
|
|
648
663
|
if (isOperatorExcluded(segments.join("."))) {
|
|
649
664
|
return true;
|
|
650
665
|
}
|
|
@@ -662,6 +677,10 @@ var collectAiPocketFeatureSnapshot = ({
|
|
|
662
677
|
return true;
|
|
663
678
|
}
|
|
664
679
|
if (featureProfile === "compact" && isCompactFeaturePathSkipped(segments)) {
|
|
680
|
+
onFeatureExcluded?.({
|
|
681
|
+
path: segments.join("."),
|
|
682
|
+
classification: "compact-profile"
|
|
683
|
+
});
|
|
665
684
|
return true;
|
|
666
685
|
}
|
|
667
686
|
if (featurePolicy !== "causal-stationary") {
|
|
@@ -696,6 +715,21 @@ var collectAiPocketFeatureSnapshot = ({
|
|
|
696
715
|
delete features[key];
|
|
697
716
|
}
|
|
698
717
|
}
|
|
718
|
+
const registered = payload.featureSnapshot;
|
|
719
|
+
if (registered) {
|
|
720
|
+
(0, import_aiFeatures.validateAiFeatureSnapshot)(registered);
|
|
721
|
+
for (const definition of registered.definitions) {
|
|
722
|
+
const path = `registered.${definition.id}`;
|
|
723
|
+
if (isOperatorExcluded(path)) continue;
|
|
724
|
+
const value = registered.values[definition.id];
|
|
725
|
+
const classification = definition.role === "outcome" || definition.role === "policy" ? "derived-policy" : definition.role !== "input" ? definition.role : featurePolicy === "causal-stationary" && !definition.stationary ? "raw-nonstationary" : value === null || value === "unknown" ? "data-quality" : "eligible";
|
|
726
|
+
if (classification !== "eligible") {
|
|
727
|
+
onFeatureExcluded?.({ path, classification });
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
features[path] = value;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
699
733
|
return { features, featureCoverage };
|
|
700
734
|
};
|
|
701
735
|
var collectAiPocketFeatures = (options) => collectAiPocketFeatureSnapshot(options).features;
|
|
@@ -27,6 +27,7 @@ var extractSignalFromAiDatasetRow = (row) => {
|
|
|
27
27
|
const { payload } = row;
|
|
28
28
|
return {
|
|
29
29
|
...payload.signal,
|
|
30
|
+
aiFeatureReplay: { snapshot: payload.featureSnapshot ?? null },
|
|
30
31
|
strategy: payload.signal.strategy,
|
|
31
32
|
figures: payload.figures ?? {},
|
|
32
33
|
indicators: payload.indicators ?? {},
|
|
@@ -30,7 +30,9 @@ var BASE_CONTEXT_FEATURE_SECTIONS = [
|
|
|
30
30
|
"relative",
|
|
31
31
|
"derivatives",
|
|
32
32
|
"mtf",
|
|
33
|
-
"gateFeatures"
|
|
33
|
+
"gateFeatures",
|
|
34
|
+
"tickerProfile",
|
|
35
|
+
"portfolioContext"
|
|
34
36
|
];
|
|
35
37
|
var asRecord = (value) => typeof value === "object" && value != null && !Array.isArray(value) ? value : null;
|
|
36
38
|
var collectStrategyGateFeatures = (baseContext) => {
|
|
@@ -47,6 +49,7 @@ var pickBaseContextFeatureSections = (baseContext) => Object.fromEntries(
|
|
|
47
49
|
);
|
|
48
50
|
var buildAiTrainEvaluationFeatureSnapshot = ({
|
|
49
51
|
additionalIndicators,
|
|
52
|
+
featureSnapshot,
|
|
50
53
|
mode
|
|
51
54
|
}) => {
|
|
52
55
|
if (mode === "none") {
|
|
@@ -56,12 +59,14 @@ var buildAiTrainEvaluationFeatureSnapshot = ({
|
|
|
56
59
|
const baseContext = asRecord(additional?.baseContext);
|
|
57
60
|
if (!baseContext) {
|
|
58
61
|
return {
|
|
59
|
-
baseContextAvailable: false
|
|
62
|
+
baseContextAvailable: false,
|
|
63
|
+
...featureSnapshot ? { featureSnapshot } : {}
|
|
60
64
|
};
|
|
61
65
|
}
|
|
62
66
|
const strategyGateFeatures = collectStrategyGateFeatures(baseContext);
|
|
63
67
|
const snapshot = {
|
|
64
68
|
baseContextAvailable: true,
|
|
69
|
+
...featureSnapshot ? { featureSnapshot } : {},
|
|
65
70
|
gateFeatures: baseContext.gateFeatures ?? null,
|
|
66
71
|
...strategyGateFeatures ? { strategyGateFeatures } : {}
|
|
67
72
|
};
|
|
@@ -405,6 +405,8 @@ var RESEARCH_CONTEXT_ENV_KEYS = [
|
|
|
405
405
|
"INTERVAL",
|
|
406
406
|
"DERIVATIVES_CONTEXT_ENABLED",
|
|
407
407
|
"DERIVATIVES_CONTEXT_TARGET_ENABLED",
|
|
408
|
+
"TICKER_PROFILES_PROVIDER",
|
|
409
|
+
"TICKER_PROFILES_UNIVERSE",
|
|
408
410
|
"DERIVATIVES_CONTEXT_LOOKBACK_HOURS",
|
|
409
411
|
"DERIVATIVES_CONTEXT_EXTRA_REFERENCE_SYMBOLS",
|
|
410
412
|
"DERIVATIVES_CONTEXT_EXCHANGE_PRIORITY",
|
|
@@ -439,13 +441,15 @@ var writeAiTrainResearchSnapshot = async ({
|
|
|
439
441
|
}) => {
|
|
440
442
|
const resolvedPath = import_node_path2.default.resolve(outputPath);
|
|
441
443
|
await import_promises2.default.mkdir(import_node_path2.default.dirname(resolvedPath), { recursive: true });
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
"
|
|
447
|
-
|
|
448
|
-
|
|
444
|
+
const bytes = `${JSON.stringify(result)}
|
|
445
|
+
`;
|
|
446
|
+
await import_promises2.default.writeFile(resolvedPath, bytes, "utf8");
|
|
447
|
+
return {
|
|
448
|
+
schema: "tradejs-research-report-receipt/v1",
|
|
449
|
+
path: resolvedPath,
|
|
450
|
+
bytes: Buffer.byteLength(bytes),
|
|
451
|
+
sha256: (0, import_node_crypto2.createHash)("sha256").update(bytes).digest("hex")
|
|
452
|
+
};
|
|
449
453
|
};
|
|
450
454
|
var normalizeForStableJson = (value) => {
|
|
451
455
|
if (Array.isArray(value)) {
|
package/dist/lib/coreResearch.js
CHANGED
|
@@ -66,7 +66,7 @@ var import_node_path = __toESM(require("path"));
|
|
|
66
66
|
|
|
67
67
|
// src/lib/coreResearch/types.ts
|
|
68
68
|
var CORE_RESEARCH_SCHEMA = "tradejs-core-research/v1";
|
|
69
|
-
var CORE_RESEARCH_RESULT_SCHEMA = "tradejs-core-research-result/
|
|
69
|
+
var CORE_RESEARCH_RESULT_SCHEMA = "tradejs-core-research-result/v2";
|
|
70
70
|
var CORE_RESEARCH_LEDGER_SCHEMA = "tradejs-core-research-ledger/v1";
|
|
71
71
|
|
|
72
72
|
// src/lib/coreResearch/io.ts
|
|
@@ -740,6 +740,14 @@ var writeCoreResearchTrades = async (params) => {
|
|
|
740
740
|
}
|
|
741
741
|
await closeOutput(output);
|
|
742
742
|
};
|
|
743
|
+
var summarizeCoreResearchComparison = (comparison) => {
|
|
744
|
+
const { matchedPairs, ...summary } = comparison;
|
|
745
|
+
return {
|
|
746
|
+
...summary,
|
|
747
|
+
exitReasonChanges: matchedPairs.filter((pair) => pair.exitReasonChanged).length,
|
|
748
|
+
exitCodeChanges: matchedPairs.filter((pair) => pair.exitCodeChanged).length
|
|
749
|
+
};
|
|
750
|
+
};
|
|
743
751
|
|
|
744
752
|
// src/lib/coreResearch/metrics.ts
|
|
745
753
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -1815,7 +1823,7 @@ var buildCurveSvg = (tradesByVariant, cohort, curve) => {
|
|
|
1815
1823
|
)}</svg><div class="legend">${series.map((entry) => `<span><i style="background:${entry.color}"></i>${escapeHtml(entry.id)}</span>`).join("")}</div>`;
|
|
1816
1824
|
};
|
|
1817
1825
|
var comparisonCards = (comparisons) => comparisons.map(
|
|
1818
|
-
(comparison) => `<article class="card"><h3>${escapeHtml(comparison.candidateId)} vs ${escapeHtml(comparison.controlId)}</h3><p class="verdict ${comparison.selection.passed ? "positive" : "negative"}">${comparison.selection.passed ? "PASS selection" : "REJECT selection"}</p><dl><dt>Matched</dt><dd>${comparison.matched}</dd><dt>Control only</dt><dd>${comparison.controlOnly}</dd><dt>Candidate only</dt><dd>${comparison.candidateOnly}</dd><dt>Identity retained</dt><dd>${format(comparison.matchedIdentityPctOfControl)}%</dd><dt>Exit reason changes</dt><dd>${comparison.
|
|
1826
|
+
(comparison) => `<article class="card"><h3>${escapeHtml(comparison.candidateId)} vs ${escapeHtml(comparison.controlId)}</h3><p class="verdict ${comparison.selection.passed ? "positive" : "negative"}">${comparison.selection.passed ? "PASS selection" : "REJECT selection"}</p><dl><dt>Matched</dt><dd>${comparison.matched}</dd><dt>Control only</dt><dd>${comparison.controlOnly}</dd><dt>Candidate only</dt><dd>${comparison.candidateOnly}</dd><dt>Identity retained</dt><dd>${format(comparison.matchedIdentityPctOfControl)}%</dd><dt>Exit reason changes</dt><dd>${comparison.exitReasonChanges}</dd><dt>Exit code changes</dt><dd>${comparison.exitCodeChanges}</dd><dt>Matched \u0394PnL</dt><dd>${format(comparison.cohorts.ALL.matchedPnlDelta)}</dd><dt>Removed control PnL</dt><dd>${format(comparison.cohorts.ALL.controlOnlyPnl)}</dd><dt>Added candidate PnL</dt><dd>${format(comparison.cohorts.ALL.candidateOnlyPnl)}</dd><dt>Aggregate \u0394PnL</dt><dd>${format(comparison.cohorts.ALL.delta.pnl)}</dd><dt>Aggregate \u0394DD</dt><dd>${format(comparison.cohorts.ALL.delta.realizedMaxDrawdown)}</dd><dt>Bootstrap P(\u0394>0)</dt><dd>${format(comparison.bootstrap.probabilityPositive, 4)}</dd><dt>Holm p</dt><dd>${format(comparison.bootstrap.holmAdjustedPValue, 4)}</dd></dl><p>${comparison.selection.failedRules.length ? escapeHtml(comparison.selection.failedRules.map((rule) => `${rule.scope}.${rule.metric} ${rule.expected}`).join("; ")) : "All preregistered rules passed."}</p></article>`
|
|
1819
1827
|
).join("");
|
|
1820
1828
|
var regimeRows = (variants) => {
|
|
1821
1829
|
const keys = [
|
|
@@ -2472,7 +2480,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
|
|
|
2472
2480
|
regimeCausality: "signal-time payload.additionalIndicators.baseContext only"
|
|
2473
2481
|
},
|
|
2474
2482
|
variants: analyses,
|
|
2475
|
-
comparisons,
|
|
2483
|
+
comparisons: comparisons.map(summarizeCoreResearchComparison),
|
|
2476
2484
|
multipleTesting: {
|
|
2477
2485
|
family: spec.hypothesis.family,
|
|
2478
2486
|
hypotheses: Math.max(comparisons.length, familyHypotheses),
|
|
@@ -2505,7 +2513,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
|
|
|
2505
2513
|
artifactHashes: sourceHashes
|
|
2506
2514
|
};
|
|
2507
2515
|
await writeJsonAtomic(paths.resultPath, result);
|
|
2508
|
-
await writeJsonAtomic(paths.comparisonPath, comparisons);
|
|
2516
|
+
await writeJsonAtomic(paths.comparisonPath, result.comparisons);
|
|
2509
2517
|
await writeCoreResearchMatches({ filePath: paths.matchesPath, comparisons });
|
|
2510
2518
|
await writeCoreResearchTrades({
|
|
2511
2519
|
filePath: paths.tradesPath,
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/lib/researchMetricSnapshot.ts
|
|
21
|
+
var researchMetricSnapshot_exports = {};
|
|
22
|
+
__export(researchMetricSnapshot_exports, {
|
|
23
|
+
decodeResearchMetricSnapshot: () => decodeResearchMetricSnapshot,
|
|
24
|
+
encodeResearchMetricSnapshot: () => encodeResearchMetricSnapshot,
|
|
25
|
+
validatePermanentResearchMetrics: () => validatePermanentResearchMetrics
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(researchMetricSnapshot_exports);
|
|
28
|
+
var import_node_crypto = require("crypto");
|
|
29
|
+
var import_node_zlib = require("zlib");
|
|
30
|
+
var MAX_BYTES = 256 * 1024 * 1024;
|
|
31
|
+
var hash = (bytes) => (0, import_node_crypto.createHash)("sha256").update(bytes).digest("hex");
|
|
32
|
+
var validatePermanentResearchMetrics = (value) => {
|
|
33
|
+
if (!value || typeof value !== "object") return;
|
|
34
|
+
for (const [key, child] of Object.entries(value)) {
|
|
35
|
+
if (["matchedPairs", "tradeRows", "allProjectedLeaves"].includes(key) && Array.isArray(child) && child.length)
|
|
36
|
+
throw new Error(`Temporary payload ${key} is not a permanent metric`);
|
|
37
|
+
if (key === "trades" && Array.isArray(child) && child.some(
|
|
38
|
+
(row) => row && typeof row === "object" && ("signalId" in row || "entryTimestamp" in row)
|
|
39
|
+
))
|
|
40
|
+
throw new Error("Temporary trade records are not permanent metrics");
|
|
41
|
+
validatePermanentResearchMetrics(child);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var encodeResearchMetricSnapshot = (metrics) => {
|
|
45
|
+
validatePermanentResearchMetrics(metrics);
|
|
46
|
+
const bytes = Buffer.from(JSON.stringify(metrics));
|
|
47
|
+
if (bytes.length > MAX_BYTES)
|
|
48
|
+
throw new Error("Metric snapshot exceeds decoded size limit");
|
|
49
|
+
return {
|
|
50
|
+
schema: "tradejs-metric-snapshot/v1",
|
|
51
|
+
encoding: "gzip+base64",
|
|
52
|
+
decodedBytes: bytes.length,
|
|
53
|
+
sha256: hash(bytes),
|
|
54
|
+
payload: (0, import_node_zlib.gzipSync)(bytes, { level: 9 }).toString("base64")
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
var decodeResearchMetricSnapshot = (snapshot) => {
|
|
58
|
+
if (!snapshot || typeof snapshot !== "object" || !("schema" in snapshot) || snapshot.schema !== "tradejs-metric-snapshot/v1" || !("encoding" in snapshot) || snapshot.encoding !== "gzip+base64" || !("decodedBytes" in snapshot) || typeof snapshot.decodedBytes !== "number" || !Number.isSafeInteger(snapshot.decodedBytes) || snapshot.decodedBytes <= 0 || snapshot.decodedBytes > MAX_BYTES || !("sha256" in snapshot) || typeof snapshot.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(snapshot.sha256) || !("payload" in snapshot) || typeof snapshot.payload !== "string")
|
|
59
|
+
throw new Error("Invalid metric snapshot envelope");
|
|
60
|
+
const bytes = (0, import_node_zlib.gunzipSync)(Buffer.from(snapshot.payload, "base64"), {
|
|
61
|
+
maxOutputLength: snapshot.decodedBytes
|
|
62
|
+
});
|
|
63
|
+
if (bytes.length !== snapshot.decodedBytes || hash(bytes) !== snapshot.sha256)
|
|
64
|
+
throw new Error("Metric snapshot checksum or size mismatch");
|
|
65
|
+
const metrics = JSON.parse(bytes.toString("utf8"));
|
|
66
|
+
validatePermanentResearchMetrics(metrics);
|
|
67
|
+
return metrics;
|
|
68
|
+
};
|
|
69
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
70
|
+
0 && (module.exports = {
|
|
71
|
+
decodeResearchMetricSnapshot,
|
|
72
|
+
encodeResearchMetricSnapshot,
|
|
73
|
+
validatePermanentResearchMetrics
|
|
74
|
+
});
|