@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
|
@@ -75,10 +75,10 @@ var init_io = __esm({
|
|
|
75
75
|
sha256Text = (value) => (0, import_node_crypto.createHash)("sha256").update(value).digest("hex");
|
|
76
76
|
sha256Json = (value) => sha256Text(canonicalJson(value));
|
|
77
77
|
sha256File = async (filePath) => {
|
|
78
|
-
const
|
|
78
|
+
const hash2 = (0, import_node_crypto.createHash)("sha256");
|
|
79
79
|
const input = (0, import_node_fs.createReadStream)(filePath);
|
|
80
|
-
for await (const chunk of input)
|
|
81
|
-
return
|
|
80
|
+
for await (const chunk of input) hash2.update(chunk);
|
|
81
|
+
return hash2.digest("hex");
|
|
82
82
|
};
|
|
83
83
|
assertFinite = (value, name) => {
|
|
84
84
|
assert(typeof value === "number" && Number.isFinite(value), name);
|
|
@@ -342,14 +342,14 @@ __export(io_exports, {
|
|
|
342
342
|
verifyResearchState: () => verifyResearchState,
|
|
343
343
|
withResearchLock: () => withResearchLock
|
|
344
344
|
});
|
|
345
|
-
var import_promises2, import_node_path2, import_node_os,
|
|
345
|
+
var import_promises2, import_node_path2, import_node_os, import_node_crypto3, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
|
|
346
346
|
var init_io2 = __esm({
|
|
347
347
|
"src/lib/strategyResearch/io.ts"() {
|
|
348
348
|
"use strict";
|
|
349
349
|
import_promises2 = __toESM(require("fs/promises"));
|
|
350
350
|
import_node_path2 = __toESM(require("path"));
|
|
351
351
|
import_node_os = __toESM(require("os"));
|
|
352
|
-
|
|
352
|
+
import_node_crypto3 = require("crypto");
|
|
353
353
|
init_io();
|
|
354
354
|
researchDirectory = (projectRoot, spec) => import_node_path2.default.join(projectRoot, "data/research/strategy", spec.core.researchId);
|
|
355
355
|
readJson = async (file) => JSON.parse(await import_promises2.default.readFile(file, "utf8"));
|
|
@@ -378,7 +378,7 @@ var init_io2 = __esm({
|
|
|
378
378
|
"data/research/strategy/.lock"
|
|
379
379
|
);
|
|
380
380
|
await import_promises2.default.mkdir(import_node_path2.default.dirname(file), { recursive: true });
|
|
381
|
-
const token = (0,
|
|
381
|
+
const token = (0, import_node_crypto3.randomUUID)();
|
|
382
382
|
const acquire = () => import_promises2.default.writeFile(
|
|
383
383
|
file,
|
|
384
384
|
JSON.stringify({ pid: process.pid, host: import_node_os.default.hostname(), token }),
|
|
@@ -474,15 +474,15 @@ var init_io2 = __esm({
|
|
|
474
474
|
await writeJsonAtomic(file, state);
|
|
475
475
|
return state;
|
|
476
476
|
};
|
|
477
|
-
isRetainedDeletion = async (directory, file,
|
|
477
|
+
isRetainedDeletion = async (directory, file, hash2) => {
|
|
478
478
|
try {
|
|
479
479
|
const inventory = await readJson(import_node_path2.default.join(directory, "retention.json"));
|
|
480
480
|
const index = inventory.entries.findIndex(
|
|
481
|
-
(entry) => entry.path === file && entry.sha256 ===
|
|
481
|
+
(entry) => entry.path === file && entry.sha256 === hash2
|
|
482
482
|
);
|
|
483
483
|
if (index < 0) return false;
|
|
484
484
|
const receipt = await readJson(import_node_path2.default.join(directory, "retention", `${index}.json`));
|
|
485
|
-
return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 ===
|
|
485
|
+
return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 === hash2;
|
|
486
486
|
} catch (error) {
|
|
487
487
|
if (error.code === "ENOENT") return false;
|
|
488
488
|
throw error;
|
|
@@ -504,6 +504,7 @@ var import_node_path16 = __toESM(require("path"));
|
|
|
504
504
|
init_io();
|
|
505
505
|
|
|
506
506
|
// src/lib/aiPocketSearch/features.ts
|
|
507
|
+
var import_aiFeatures = require("@tradejs/core/aiFeatures");
|
|
507
508
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
508
509
|
var DAYS_PER_WEEK = 7;
|
|
509
510
|
var DAYS_PER_MONTH = 30.4375;
|
|
@@ -872,15 +873,25 @@ var addFlattenedFeatures = ({
|
|
|
872
873
|
value,
|
|
873
874
|
segments,
|
|
874
875
|
maxDepth,
|
|
875
|
-
shouldSkipPath = () => false
|
|
876
|
+
shouldSkipPath = () => false,
|
|
877
|
+
onFeatureExcluded
|
|
876
878
|
}) => {
|
|
877
879
|
if (!segments.length && !isPlainRecord(value)) {
|
|
878
880
|
return;
|
|
879
881
|
}
|
|
880
|
-
if (segments.length > maxDepth || isOutcomePath(segments)
|
|
882
|
+
if (segments.length > maxDepth || isOutcomePath(segments)) {
|
|
883
|
+
onFeatureExcluded?.({
|
|
884
|
+
path: segments.join("."),
|
|
885
|
+
classification: segments.length > maxDepth ? "depth-limit" : "derived-policy"
|
|
886
|
+
});
|
|
881
887
|
return;
|
|
882
888
|
}
|
|
889
|
+
if (shouldSkipPath(segments)) return;
|
|
883
890
|
if (Array.isArray(value)) {
|
|
891
|
+
onFeatureExcluded?.({
|
|
892
|
+
path: segments.join("."),
|
|
893
|
+
classification: "unprojected-array"
|
|
894
|
+
});
|
|
884
895
|
return;
|
|
885
896
|
}
|
|
886
897
|
if (isFeaturePrimitive(value)) {
|
|
@@ -902,7 +913,8 @@ var addFlattenedFeatures = ({
|
|
|
902
913
|
value: child,
|
|
903
914
|
segments: [...segments, key],
|
|
904
915
|
maxDepth,
|
|
905
|
-
shouldSkipPath
|
|
916
|
+
shouldSkipPath,
|
|
917
|
+
onFeatureExcluded
|
|
906
918
|
});
|
|
907
919
|
}
|
|
908
920
|
};
|
|
@@ -1114,7 +1126,10 @@ var collectAiPocketFeatureSnapshot = ({
|
|
|
1114
1126
|
value: source,
|
|
1115
1127
|
segments: [],
|
|
1116
1128
|
maxDepth: 8,
|
|
1129
|
+
onFeatureExcluded,
|
|
1117
1130
|
shouldSkipPath: (segments) => {
|
|
1131
|
+
if (segments.join(".") === "additionalIndicators.baseContext.tickerProfile" || segments.join(".") === "additionalIndicators.tickerProfile" || segments.join(".") === "additionalIndicators.portfolioContext")
|
|
1132
|
+
return true;
|
|
1118
1133
|
if (isOperatorExcluded(segments.join("."))) {
|
|
1119
1134
|
return true;
|
|
1120
1135
|
}
|
|
@@ -1132,6 +1147,10 @@ var collectAiPocketFeatureSnapshot = ({
|
|
|
1132
1147
|
return true;
|
|
1133
1148
|
}
|
|
1134
1149
|
if (featureProfile === "compact" && isCompactFeaturePathSkipped(segments)) {
|
|
1150
|
+
onFeatureExcluded?.({
|
|
1151
|
+
path: segments.join("."),
|
|
1152
|
+
classification: "compact-profile"
|
|
1153
|
+
});
|
|
1135
1154
|
return true;
|
|
1136
1155
|
}
|
|
1137
1156
|
if (featurePolicy !== "causal-stationary") {
|
|
@@ -1166,6 +1185,21 @@ var collectAiPocketFeatureSnapshot = ({
|
|
|
1166
1185
|
delete features[key];
|
|
1167
1186
|
}
|
|
1168
1187
|
}
|
|
1188
|
+
const registered = payload.featureSnapshot;
|
|
1189
|
+
if (registered) {
|
|
1190
|
+
(0, import_aiFeatures.validateAiFeatureSnapshot)(registered);
|
|
1191
|
+
for (const definition of registered.definitions) {
|
|
1192
|
+
const path17 = `registered.${definition.id}`;
|
|
1193
|
+
if (isOperatorExcluded(path17)) continue;
|
|
1194
|
+
const value = registered.values[definition.id];
|
|
1195
|
+
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";
|
|
1196
|
+
if (classification !== "eligible") {
|
|
1197
|
+
onFeatureExcluded?.({ path: path17, classification });
|
|
1198
|
+
continue;
|
|
1199
|
+
}
|
|
1200
|
+
features[path17] = value;
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1169
1203
|
return { features, featureCoverage };
|
|
1170
1204
|
};
|
|
1171
1205
|
var collectAiPocketFeatures = (options) => collectAiPocketFeatureSnapshot(options).features;
|
|
@@ -1784,15 +1818,15 @@ var createPocketResult = (rows, predicates, mask, validationRows, testRows, obje
|
|
|
1784
1818
|
};
|
|
1785
1819
|
};
|
|
1786
1820
|
var hashMask = (mask) => {
|
|
1787
|
-
let
|
|
1821
|
+
let hash2 = 2166136261;
|
|
1788
1822
|
for (let index = 0; index < mask.length; index += 1) {
|
|
1789
1823
|
if (mask[index] !== 1) {
|
|
1790
1824
|
continue;
|
|
1791
1825
|
}
|
|
1792
|
-
|
|
1793
|
-
|
|
1826
|
+
hash2 ^= index + 1;
|
|
1827
|
+
hash2 = Math.imul(hash2, 16777619);
|
|
1794
1828
|
}
|
|
1795
|
-
return (
|
|
1829
|
+
return (hash2 >>> 0).toString(36);
|
|
1796
1830
|
};
|
|
1797
1831
|
var isBetterRepresentativePocket = (candidate, existing, compare) => candidate.depth < existing.depth || candidate.depth === existing.depth && candidate.condition.length < existing.condition.length || candidate.depth === existing.depth && candidate.condition.length === existing.condition.length && compare(candidate, existing) < 0;
|
|
1798
1832
|
var estimateCombinationCount = (poolSize, maxDepth, maxCombinations) => {
|
|
@@ -2489,6 +2523,51 @@ var policyVariant = (spec, coreId, policy, id, jev) => {
|
|
|
2489
2523
|
|
|
2490
2524
|
// src/lib/strategyResearch/orchestrator.ts
|
|
2491
2525
|
var import_promises5 = __toESM(require("fs/promises"));
|
|
2526
|
+
|
|
2527
|
+
// src/lib/researchMetricSnapshot.ts
|
|
2528
|
+
var import_node_crypto2 = require("crypto");
|
|
2529
|
+
var import_node_zlib = require("zlib");
|
|
2530
|
+
var MAX_BYTES = 256 * 1024 * 1024;
|
|
2531
|
+
var hash = (bytes) => (0, import_node_crypto2.createHash)("sha256").update(bytes).digest("hex");
|
|
2532
|
+
var validatePermanentResearchMetrics = (value) => {
|
|
2533
|
+
if (!value || typeof value !== "object") return;
|
|
2534
|
+
for (const [key, child] of Object.entries(value)) {
|
|
2535
|
+
if (["matchedPairs", "tradeRows", "allProjectedLeaves"].includes(key) && Array.isArray(child) && child.length)
|
|
2536
|
+
throw new Error(`Temporary payload ${key} is not a permanent metric`);
|
|
2537
|
+
if (key === "trades" && Array.isArray(child) && child.some(
|
|
2538
|
+
(row) => row && typeof row === "object" && ("signalId" in row || "entryTimestamp" in row)
|
|
2539
|
+
))
|
|
2540
|
+
throw new Error("Temporary trade records are not permanent metrics");
|
|
2541
|
+
validatePermanentResearchMetrics(child);
|
|
2542
|
+
}
|
|
2543
|
+
};
|
|
2544
|
+
var encodeResearchMetricSnapshot = (metrics) => {
|
|
2545
|
+
validatePermanentResearchMetrics(metrics);
|
|
2546
|
+
const bytes = Buffer.from(JSON.stringify(metrics));
|
|
2547
|
+
if (bytes.length > MAX_BYTES)
|
|
2548
|
+
throw new Error("Metric snapshot exceeds decoded size limit");
|
|
2549
|
+
return {
|
|
2550
|
+
schema: "tradejs-metric-snapshot/v1",
|
|
2551
|
+
encoding: "gzip+base64",
|
|
2552
|
+
decodedBytes: bytes.length,
|
|
2553
|
+
sha256: hash(bytes),
|
|
2554
|
+
payload: (0, import_node_zlib.gzipSync)(bytes, { level: 9 }).toString("base64")
|
|
2555
|
+
};
|
|
2556
|
+
};
|
|
2557
|
+
var decodeResearchMetricSnapshot = (snapshot) => {
|
|
2558
|
+
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")
|
|
2559
|
+
throw new Error("Invalid metric snapshot envelope");
|
|
2560
|
+
const bytes = (0, import_node_zlib.gunzipSync)(Buffer.from(snapshot.payload, "base64"), {
|
|
2561
|
+
maxOutputLength: snapshot.decodedBytes
|
|
2562
|
+
});
|
|
2563
|
+
if (bytes.length !== snapshot.decodedBytes || hash(bytes) !== snapshot.sha256)
|
|
2564
|
+
throw new Error("Metric snapshot checksum or size mismatch");
|
|
2565
|
+
const metrics = JSON.parse(bytes.toString("utf8"));
|
|
2566
|
+
validatePermanentResearchMetrics(metrics);
|
|
2567
|
+
return metrics;
|
|
2568
|
+
};
|
|
2569
|
+
|
|
2570
|
+
// src/lib/strategyResearch/orchestrator.ts
|
|
2492
2571
|
var import_node_path6 = __toESM(require("path"));
|
|
2493
2572
|
|
|
2494
2573
|
// src/lib/coreResearch/metrics.ts
|
|
@@ -3695,7 +3774,7 @@ var import_node_path5 = __toESM(require("path"));
|
|
|
3695
3774
|
// src/lib/strategyRelease/researchRetention.ts
|
|
3696
3775
|
var import_promises3 = __toESM(require("fs/promises"));
|
|
3697
3776
|
var import_node_path4 = __toESM(require("path"));
|
|
3698
|
-
var
|
|
3777
|
+
var import_node_crypto4 = require("crypto");
|
|
3699
3778
|
var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
|
|
3700
3779
|
|
|
3701
3780
|
// src/lib/strategyRelease/researchFileConsumers.ts
|
|
@@ -3844,7 +3923,7 @@ var mapFiles = async (entries, visit) => {
|
|
|
3844
3923
|
if (worker.status === "rejected") throw worker.reason;
|
|
3845
3924
|
return results;
|
|
3846
3925
|
};
|
|
3847
|
-
var fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0,
|
|
3926
|
+
var fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto4.createHash)("sha256").update(await import_promises3.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence.strategyEvidenceFileSha256)(file);
|
|
3848
3927
|
var inside = (root, file) => {
|
|
3849
3928
|
const relative = import_node_path4.default.relative(root, file);
|
|
3850
3929
|
return relative !== "" && !relative.startsWith(`..${import_node_path4.default.sep}`) && relative !== ".." && !import_node_path4.default.isAbsolute(relative);
|
|
@@ -3888,13 +3967,27 @@ var applyResearchRetention = async (options) => {
|
|
|
3888
3967
|
const header = Buffer.alloc(4096);
|
|
3889
3968
|
const { bytesRead } = await handle.read(header, 0, header.length, 0);
|
|
3890
3969
|
const frontmatter = header.subarray(0, bytesRead).toString("utf8").match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
3891
|
-
if (!frontmatter || !/^schema:\s*tradejs-research\/
|
|
3970
|
+
if (!frontmatter || !/^schema:\s*tradejs-research\/v[12]\s*$/m.test(frontmatter[1]) || !(retired ? /^reproduction:\s*(?:complete|partial|blocked|legacy-partial)\s*$/m.test(
|
|
3892
3971
|
frontmatter[1]
|
|
3893
3972
|
) : /^reproduction:\s*complete\s*$/m.test(frontmatter[1]))) {
|
|
3894
3973
|
throw new Error(
|
|
3895
3974
|
`Research note must have reproduction: complete: ${file}`
|
|
3896
3975
|
);
|
|
3897
3976
|
}
|
|
3977
|
+
if (!retired && /^schema:\s*tradejs-research\/v2\s*$/m.test(frontmatter[1])) {
|
|
3978
|
+
if ((await import_promises3.default.stat(file)).size > 8 * 1024 * 1024)
|
|
3979
|
+
throw new Error("Compact permanent note exceeds 8 MiB");
|
|
3980
|
+
const content = await import_promises3.default.readFile(file, "utf8");
|
|
3981
|
+
const section = content.split("## Metrics snapshot (machine-readable)")[1]?.split("## Reported metrics")[0] ?? "";
|
|
3982
|
+
const blocks = [
|
|
3983
|
+
...section.matchAll(/```json\r?\n([\s\S]*?)\r?\n```/g)
|
|
3984
|
+
];
|
|
3985
|
+
if (blocks.length !== 1)
|
|
3986
|
+
throw new Error(
|
|
3987
|
+
"Complete v2 note needs one verified metric snapshot"
|
|
3988
|
+
);
|
|
3989
|
+
decodeResearchMetricSnapshot(JSON.parse(blocks[0][1]));
|
|
3990
|
+
}
|
|
3898
3991
|
} finally {
|
|
3899
3992
|
await handle.close();
|
|
3900
3993
|
}
|
|
@@ -4008,11 +4101,11 @@ var createResearchRetentionInventory = async (projectRoot, directory, spec, stat
|
|
|
4008
4101
|
}
|
|
4009
4102
|
const files = /* @__PURE__ */ new Map();
|
|
4010
4103
|
for (const stage of Object.values(state.stages)) {
|
|
4011
|
-
for (const [relative,
|
|
4104
|
+
for (const [relative, hash2] of Object.entries(stage.artifacts)) {
|
|
4012
4105
|
const file = await boundResearchPath(directory, relative);
|
|
4013
4106
|
if (relative.endsWith("/result.json")) {
|
|
4014
4107
|
const result = await readJson(file);
|
|
4015
|
-
if (result?.dataset) files.set(file,
|
|
4108
|
+
if (result?.dataset) files.set(file, hash2);
|
|
4016
4109
|
}
|
|
4017
4110
|
if (relative.endsWith("/sources.json") || relative.endsWith("/payloads.json")) {
|
|
4018
4111
|
const sources = await readJson(file);
|
|
@@ -4029,13 +4122,13 @@ var createResearchRetentionInventory = async (projectRoot, directory, spec, stat
|
|
|
4029
4122
|
}
|
|
4030
4123
|
}
|
|
4031
4124
|
const entries = [];
|
|
4032
|
-
for (const [file,
|
|
4125
|
+
for (const [file, hash2] of files) {
|
|
4033
4126
|
const stat = await import_promises4.default.stat(file);
|
|
4034
4127
|
entries.push({
|
|
4035
4128
|
path: file,
|
|
4036
4129
|
kind: "research_payload",
|
|
4037
4130
|
researchId: spec.core.researchId,
|
|
4038
|
-
sha256:
|
|
4131
|
+
sha256: hash2,
|
|
4039
4132
|
bytes: stat.size,
|
|
4040
4133
|
createdAt: stat.birthtimeMs,
|
|
4041
4134
|
verified: true,
|
|
@@ -4779,7 +4872,7 @@ var runStrategyResearch = async (parameters) => {
|
|
|
4779
4872
|
)
|
|
4780
4873
|
};
|
|
4781
4874
|
const note = `---
|
|
4782
|
-
schema: tradejs-research/
|
|
4875
|
+
schema: tradejs-research/v2
|
|
4783
4876
|
strategy: '${spec.core.strategy}'
|
|
4784
4877
|
date: '${spec.core.createdAt.slice(0, 10)}'
|
|
4785
4878
|
kind: 'backtest'
|
|
@@ -4812,7 +4905,7 @@ ${JSON.stringify(spec, null, 2)}
|
|
|
4812
4905
|
## Metrics snapshot (machine-readable)
|
|
4813
4906
|
|
|
4814
4907
|
\`\`\`json
|
|
4815
|
-
${JSON.stringify(compact
|
|
4908
|
+
${JSON.stringify(encodeResearchMetricSnapshot(compact))}
|
|
4816
4909
|
\`\`\`
|
|
4817
4910
|
|
|
4818
4911
|
## Reported metrics
|
|
@@ -4831,6 +4924,10 @@ ${directory}/report.html
|
|
|
4831
4924
|
|
|
4832
4925
|
${conclusion.nextAction} Current-snapshot universe; no deployment authorization. Temporary payloads are deleted only after the permanent record is verified; new trade-level questions require a frozen rerun.
|
|
4833
4926
|
`;
|
|
4927
|
+
if (Buffer.byteLength(note) > 8 * 1024 * 1024)
|
|
4928
|
+
throw new Error(
|
|
4929
|
+
"Compact permanent note exceeds 8 MiB; archive source separately, never truncate metrics"
|
|
4930
|
+
);
|
|
4834
4931
|
await import_promises5.default.writeFile(
|
|
4835
4932
|
import_node_path6.default.join(
|
|
4836
4933
|
noteDirectory,
|
|
@@ -4938,7 +5035,7 @@ var import_registry = require("@tradejs/node/registry");
|
|
|
4938
5035
|
var import_connectors = require("@tradejs/node/connectors");
|
|
4939
5036
|
|
|
4940
5037
|
// src/lib/coreResearch/dataset.ts
|
|
4941
|
-
var
|
|
5038
|
+
var import_node_crypto5 = require("crypto");
|
|
4942
5039
|
var import_node_fs2 = require("fs");
|
|
4943
5040
|
var import_node_path7 = __toESM(require("path"));
|
|
4944
5041
|
var import_node_readline = __toESM(require("readline"));
|
|
@@ -5153,8 +5250,8 @@ var readCoreResearchVariant = async (variant) => {
|
|
|
5153
5250
|
for (const inputPath of variant.files) {
|
|
5154
5251
|
const filePath = import_node_path7.default.resolve(inputPath);
|
|
5155
5252
|
const input = (0, import_node_fs2.createReadStream)(filePath);
|
|
5156
|
-
const
|
|
5157
|
-
input.on("data", (chunk) =>
|
|
5253
|
+
const hash2 = (0, import_node_crypto5.createHash)("sha256");
|
|
5254
|
+
input.on("data", (chunk) => hash2.update(chunk));
|
|
5158
5255
|
const lines = import_node_readline.default.createInterface({ input, crlfDelay: Infinity });
|
|
5159
5256
|
const fileTrades = [];
|
|
5160
5257
|
let lineNumber = 0;
|
|
@@ -5204,7 +5301,7 @@ var readCoreResearchVariant = async (variant) => {
|
|
|
5204
5301
|
trades.push(trade);
|
|
5205
5302
|
fileTrades.push(trade);
|
|
5206
5303
|
}
|
|
5207
|
-
const fileSha2562 =
|
|
5304
|
+
const fileSha2562 = hash2.digest("hex");
|
|
5208
5305
|
for (const trade of fileTrades) trade.sourceSha256 = fileSha2562;
|
|
5209
5306
|
sources.push({
|
|
5210
5307
|
path: filePath,
|
|
@@ -5224,7 +5321,7 @@ var readCoreResearchVariant = async (variant) => {
|
|
|
5224
5321
|
};
|
|
5225
5322
|
|
|
5226
5323
|
// src/lib/backtest/checkpoint.ts
|
|
5227
|
-
var
|
|
5324
|
+
var import_node_crypto6 = require("crypto");
|
|
5228
5325
|
var import_constants = require("@tradejs/core/constants");
|
|
5229
5326
|
var import_backtest2 = require("@tradejs/core/backtest");
|
|
5230
5327
|
var import_redis = require("@tradejs/infra/redis");
|
|
@@ -5424,6 +5521,7 @@ var extractSignalFromAiDatasetRow = (row) => {
|
|
|
5424
5521
|
const { payload } = row;
|
|
5425
5522
|
return {
|
|
5426
5523
|
...payload.signal,
|
|
5524
|
+
aiFeatureReplay: { snapshot: payload.featureSnapshot ?? null },
|
|
5427
5525
|
strategy: payload.signal.strategy,
|
|
5428
5526
|
figures: payload.figures ?? {},
|
|
5429
5527
|
indicators: payload.indicators ?? {},
|
|
@@ -5437,7 +5535,7 @@ init_io2();
|
|
|
5437
5535
|
|
|
5438
5536
|
// src/lib/aiTrainResearch.ts
|
|
5439
5537
|
var import_node_child_process2 = require("child_process");
|
|
5440
|
-
var
|
|
5538
|
+
var import_node_crypto8 = require("crypto");
|
|
5441
5539
|
var import_promises7 = __toESM(require("fs/promises"));
|
|
5442
5540
|
var import_node_path9 = __toESM(require("path"));
|
|
5443
5541
|
|
|
@@ -5449,7 +5547,7 @@ var import_strategies = require("@tradejs/node/strategies");
|
|
|
5449
5547
|
var import_types2 = require("@tradejs/types");
|
|
5450
5548
|
|
|
5451
5549
|
// src/lib/strategyGateFingerprint.ts
|
|
5452
|
-
var
|
|
5550
|
+
var import_node_crypto7 = require("crypto");
|
|
5453
5551
|
var import_node_module = require("module");
|
|
5454
5552
|
var import_promises6 = __toESM(require("fs/promises"));
|
|
5455
5553
|
var import_node_path8 = __toESM(require("path"));
|
|
@@ -5462,6 +5560,8 @@ var RESEARCH_CONTEXT_ENV_KEYS = [
|
|
|
5462
5560
|
"INTERVAL",
|
|
5463
5561
|
"DERIVATIVES_CONTEXT_ENABLED",
|
|
5464
5562
|
"DERIVATIVES_CONTEXT_TARGET_ENABLED",
|
|
5563
|
+
"TICKER_PROFILES_PROVIDER",
|
|
5564
|
+
"TICKER_PROFILES_UNIVERSE",
|
|
5465
5565
|
"DERIVATIVES_CONTEXT_LOOKBACK_HOURS",
|
|
5466
5566
|
"DERIVATIVES_CONTEXT_EXTRA_REFERENCE_SYMBOLS",
|
|
5467
5567
|
"DERIVATIVES_CONTEXT_EXCHANGE_PRIORITY",
|
|
@@ -5491,7 +5591,7 @@ var normalizeForStableJson = (value) => {
|
|
|
5491
5591
|
}
|
|
5492
5592
|
return value;
|
|
5493
5593
|
};
|
|
5494
|
-
var fingerprintResearchValue = (value) => (0,
|
|
5594
|
+
var fingerprintResearchValue = (value) => (0, import_node_crypto8.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
|
|
5495
5595
|
var fingerprintResearchContextEnvironment = (env = process.env) => fingerprintResearchValue(
|
|
5496
5596
|
Object.fromEntries(
|
|
5497
5597
|
RESEARCH_CONTEXT_ENV_KEYS.map((key) => [key, env[key] ?? null])
|
|
@@ -6532,7 +6632,7 @@ init_io();
|
|
|
6532
6632
|
var import_promises11 = __toESM(require("fs/promises"));
|
|
6533
6633
|
var import_node_path15 = __toESM(require("path"));
|
|
6534
6634
|
var import_node_child_process4 = require("child_process");
|
|
6535
|
-
var
|
|
6635
|
+
var import_node_crypto10 = require("crypto");
|
|
6536
6636
|
var import_coreResearch2 = require("@tradejs/infra/coreResearch");
|
|
6537
6637
|
|
|
6538
6638
|
// src/lib/coreResearch/artifacts.ts
|
|
@@ -6546,7 +6646,7 @@ init_io();
|
|
|
6546
6646
|
init_io();
|
|
6547
6647
|
|
|
6548
6648
|
// src/lib/coreResearch/statistics.ts
|
|
6549
|
-
var
|
|
6649
|
+
var import_node_crypto9 = require("crypto");
|
|
6550
6650
|
|
|
6551
6651
|
// src/lib/coreResearch/orchestrator.ts
|
|
6552
6652
|
init_types();
|
|
@@ -6584,7 +6684,7 @@ var createCoreResearchSpecTemplate = (params) => {
|
|
|
6584
6684
|
gitSha,
|
|
6585
6685
|
...sourceRepository ? { sourceRepository } : {},
|
|
6586
6686
|
...dirtyDiff ? {
|
|
6587
|
-
dirtyDiffSha256: (0,
|
|
6687
|
+
dirtyDiffSha256: (0, import_node_crypto10.createHash)("sha256").update(dirtyDiff).digest("hex")
|
|
6588
6688
|
} : {}
|
|
6589
6689
|
};
|
|
6590
6690
|
} catch {
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
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
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/scripts/tickerProfiles.ts
|
|
31
|
+
var tickerProfiles_exports = {};
|
|
32
|
+
__export(tickerProfiles_exports, {
|
|
33
|
+
main: () => main
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(tickerProfiles_exports);
|
|
36
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
37
|
+
|
|
38
|
+
// src/lib/tickerProfiles.ts
|
|
39
|
+
var import_tickerProfiles = require("@tradejs/core/tickerProfiles");
|
|
40
|
+
var import_candles = require("@tradejs/infra/timescale/candles");
|
|
41
|
+
var import_tickerProfiles2 = require("@tradejs/infra/tickerProfiles");
|
|
42
|
+
var prepareTickerProfiles = async ({
|
|
43
|
+
projectRoot,
|
|
44
|
+
provider,
|
|
45
|
+
universeId,
|
|
46
|
+
symbols,
|
|
47
|
+
start,
|
|
48
|
+
end
|
|
49
|
+
}) => {
|
|
50
|
+
if (!Number.isSafeInteger(end) || end <= start)
|
|
51
|
+
throw new Error("Invalid profile time window");
|
|
52
|
+
if (!symbols.length || new Set(symbols).size !== symbols.length || symbols.some((s) => !/^[A-Z0-9]+USDT$/.test(s)))
|
|
53
|
+
throw new Error("Supply a unique explicit USDT universe");
|
|
54
|
+
if (!symbols.includes("BTCUSDT") || !symbols.includes("ETHUSDT"))
|
|
55
|
+
throw new Error("The universe must include BTCUSDT and ETHUSDT references");
|
|
56
|
+
const receipts = [];
|
|
57
|
+
for (let asOf = (0, import_tickerProfiles.tickerProfileMonth)(start); asOf < end; asOf = (0, import_tickerProfiles.tickerProfileNextMonth)(asOf)) {
|
|
58
|
+
const candlesBySymbol = {};
|
|
59
|
+
for (const symbol of [...symbols].sort())
|
|
60
|
+
candlesBySymbol[symbol] = await (0, import_candles.getKlineCandlesRange)(
|
|
61
|
+
provider,
|
|
62
|
+
symbol,
|
|
63
|
+
60,
|
|
64
|
+
asOf - 721 * 36e5,
|
|
65
|
+
asOf - 36e5
|
|
66
|
+
);
|
|
67
|
+
const snapshot = (0, import_tickerProfiles.buildTickerProfileSnapshot)({
|
|
68
|
+
asOf,
|
|
69
|
+
provider,
|
|
70
|
+
universeId,
|
|
71
|
+
membership: "frozen-list",
|
|
72
|
+
candlesBySymbol
|
|
73
|
+
});
|
|
74
|
+
const snapshotId = await (0, import_tickerProfiles2.writeTickerProfiles)(projectRoot, snapshot);
|
|
75
|
+
receipts.push({
|
|
76
|
+
asOf,
|
|
77
|
+
snapshotId,
|
|
78
|
+
symbols: snapshot.profiles.length,
|
|
79
|
+
unknown: snapshot.profiles.filter(
|
|
80
|
+
(p) => p.moneyGroup === "unknown" || p.volatilityGroup === "unknown"
|
|
81
|
+
).length
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return receipts;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/scripts/tickerProfiles.ts
|
|
88
|
+
var main = async () => {
|
|
89
|
+
const argv = process.argv.slice(2);
|
|
90
|
+
const option = (name) => {
|
|
91
|
+
const i = argv.indexOf(`--${name}`);
|
|
92
|
+
if (i < 0 || !argv[i + 1] || argv[i + 1].startsWith("--"))
|
|
93
|
+
throw new Error(`--${name} is required`);
|
|
94
|
+
return argv[i + 1];
|
|
95
|
+
};
|
|
96
|
+
const symbols = JSON.parse(
|
|
97
|
+
await import_promises.default.readFile(option("symbolsFile"), "utf8")
|
|
98
|
+
);
|
|
99
|
+
if (!Array.isArray(symbols) || !symbols.every((s) => typeof s === "string"))
|
|
100
|
+
throw new Error("symbolsFile must be a JSON string array");
|
|
101
|
+
const receipts = await prepareTickerProfiles({
|
|
102
|
+
projectRoot: process.env.PROJECT_CWD || process.cwd(),
|
|
103
|
+
provider: option("provider"),
|
|
104
|
+
universeId: option("universeId"),
|
|
105
|
+
symbols,
|
|
106
|
+
start: Number(option("startTime")),
|
|
107
|
+
end: Number(option("endTime"))
|
|
108
|
+
});
|
|
109
|
+
console.log(JSON.stringify({ command: "ticker-profiles", receipts }));
|
|
110
|
+
};
|
|
111
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
112
|
+
0 && (module.exports = {
|
|
113
|
+
main
|
|
114
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/cli",
|
|
3
|
-
"version": "3.1.29-beta.
|
|
3
|
+
"version": "3.1.29-beta.291",
|
|
4
4
|
"description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
"tradejs": "dist/cli.js"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@tradejs/connectors": "^3.1.29-beta.
|
|
41
|
-
"@tradejs/core": "^3.1.29-beta.
|
|
42
|
-
"@tradejs/indicators": "^3.1.29-beta.
|
|
43
|
-
"@tradejs/infra": "^3.1.29-beta.
|
|
44
|
-
"@tradejs/node": "^3.1.29-beta.
|
|
40
|
+
"@tradejs/connectors": "^3.1.29-beta.291",
|
|
41
|
+
"@tradejs/core": "^3.1.29-beta.291",
|
|
42
|
+
"@tradejs/indicators": "^3.1.29-beta.291",
|
|
43
|
+
"@tradejs/infra": "^3.1.29-beta.291",
|
|
44
|
+
"@tradejs/node": "^3.1.29-beta.291",
|
|
45
45
|
"@tradejs/strategy-kit": "3.0.6",
|
|
46
|
-
"@tradejs/types": "^3.1.29-beta.
|
|
46
|
+
"@tradejs/types": "^3.1.29-beta.291",
|
|
47
47
|
"args": "^5.0.3",
|
|
48
48
|
"bcryptjs": "^2.4.3",
|
|
49
49
|
"chalk": "4.1.2",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"lodash": "^4.18.1",
|
|
55
55
|
"pg": "8.22.0",
|
|
56
56
|
"progress": "^2.0.3",
|
|
57
|
+
"sharp": "^0.35.3",
|
|
57
58
|
"ws": "^8.21.1"
|
|
58
59
|
},
|
|
59
60
|
"devDependencies": {
|