@tradejs/cli 3.1.29-beta.292 → 3.1.29-beta.296
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 +563 -485
- package/dist/lib/binanceMarketContextBackfill.js +2 -2
- package/dist/lib/coinMarketCapContextBackfill.js +1 -1
- package/dist/lib/marketContextPrepare.js +3 -3
- package/dist/lib/strategyResearch.js +33 -79
- package/dist/scripts/backtest.js +192 -69
- package/dist/scripts/binanceMarketIngest.js +3 -3
- package/dist/scripts/replay.js +3 -3
- package/dist/scripts/replayRunner.js +3 -3
- package/dist/scripts/runtimeParity.js +3 -3
- package/dist/scripts/signals.js +3 -3
- package/dist/scripts/signalsDaemon.js +3 -3
- package/dist/scripts/strategyRelease.js +6 -37
- package/dist/scripts/strategyResearch.js +36 -82
- package/package.json +7 -7
- package/dist/lib/researchMetricSnapshot.js +0 -74
|
@@ -42,40 +42,9 @@ var import_chalk = __toESM(require("chalk"));
|
|
|
42
42
|
|
|
43
43
|
// src/lib/strategyRelease/researchRetention.ts
|
|
44
44
|
var import_promises = __toESM(require("fs/promises"));
|
|
45
|
-
|
|
46
|
-
// src/lib/researchMetricSnapshot.ts
|
|
47
|
-
var import_node_crypto = require("crypto");
|
|
48
|
-
var import_node_zlib = require("zlib");
|
|
49
|
-
var MAX_BYTES = 256 * 1024 * 1024;
|
|
50
|
-
var hash = (bytes) => (0, import_node_crypto.createHash)("sha256").update(bytes).digest("hex");
|
|
51
|
-
var validatePermanentResearchMetrics = (value) => {
|
|
52
|
-
if (!value || typeof value !== "object") return;
|
|
53
|
-
for (const [key, child] of Object.entries(value)) {
|
|
54
|
-
if (["matchedPairs", "tradeRows", "allProjectedLeaves"].includes(key) && Array.isArray(child) && child.length)
|
|
55
|
-
throw new Error(`Temporary payload ${key} is not a permanent metric`);
|
|
56
|
-
if (key === "trades" && Array.isArray(child) && child.some(
|
|
57
|
-
(row) => row && typeof row === "object" && ("signalId" in row || "entryTimestamp" in row)
|
|
58
|
-
))
|
|
59
|
-
throw new Error("Temporary trade records are not permanent metrics");
|
|
60
|
-
validatePermanentResearchMetrics(child);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
var decodeResearchMetricSnapshot = (snapshot) => {
|
|
64
|
-
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")
|
|
65
|
-
throw new Error("Invalid metric snapshot envelope");
|
|
66
|
-
const bytes = (0, import_node_zlib.gunzipSync)(Buffer.from(snapshot.payload, "base64"), {
|
|
67
|
-
maxOutputLength: snapshot.decodedBytes
|
|
68
|
-
});
|
|
69
|
-
if (bytes.length !== snapshot.decodedBytes || hash(bytes) !== snapshot.sha256)
|
|
70
|
-
throw new Error("Metric snapshot checksum or size mismatch");
|
|
71
|
-
const metrics = JSON.parse(bytes.toString("utf8"));
|
|
72
|
-
validatePermanentResearchMetrics(metrics);
|
|
73
|
-
return metrics;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// src/lib/strategyRelease/researchRetention.ts
|
|
45
|
+
var import_researchMetricSnapshot = require("@tradejs/infra/researchMetricSnapshot");
|
|
77
46
|
var import_node_path2 = __toESM(require("path"));
|
|
78
|
-
var
|
|
47
|
+
var import_node_crypto = require("crypto");
|
|
79
48
|
var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
|
|
80
49
|
|
|
81
50
|
// src/lib/strategyRelease/researchFileConsumers.ts
|
|
@@ -267,7 +236,7 @@ var mapFiles = async (entries, visit) => {
|
|
|
267
236
|
if (worker.status === "rejected") throw worker.reason;
|
|
268
237
|
return results;
|
|
269
238
|
};
|
|
270
|
-
var fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0,
|
|
239
|
+
var fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto.createHash)("sha256").update(await import_promises.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence.strategyEvidenceFileSha256)(file);
|
|
271
240
|
var inside = (root, file) => {
|
|
272
241
|
const relative = import_node_path2.default.relative(root, file);
|
|
273
242
|
return relative !== "" && !relative.startsWith(`..${import_node_path2.default.sep}`) && relative !== ".." && !import_node_path2.default.isAbsolute(relative);
|
|
@@ -330,7 +299,7 @@ var applyResearchRetention = async (options) => {
|
|
|
330
299
|
throw new Error(
|
|
331
300
|
"Complete v2 note needs one verified metric snapshot"
|
|
332
301
|
);
|
|
333
|
-
decodeResearchMetricSnapshot(JSON.parse(blocks[0][1]));
|
|
302
|
+
(0, import_researchMetricSnapshot.decodeResearchMetricSnapshot)(JSON.parse(blocks[0][1]));
|
|
334
303
|
}
|
|
335
304
|
} finally {
|
|
336
305
|
await handle.close();
|
|
@@ -415,7 +384,7 @@ var applyResearchRetention = async (options) => {
|
|
|
415
384
|
};
|
|
416
385
|
|
|
417
386
|
// src/lib/strategyRelease.ts
|
|
418
|
-
var
|
|
387
|
+
var import_node_crypto2 = require("crypto");
|
|
419
388
|
var import_promises2 = __toESM(require("fs/promises"));
|
|
420
389
|
var import_node_path3 = __toESM(require("path"));
|
|
421
390
|
var import_types2 = require("@tradejs/types");
|
|
@@ -1585,7 +1554,7 @@ var verifyCompletedCoreResearchBundle = async ({
|
|
|
1585
1554
|
const artifactHashes = manifest.artifactHashes != null && typeof manifest.artifactHashes === "object" && !Array.isArray(manifest.artifactHashes) ? manifest.artifactHashes : null;
|
|
1586
1555
|
const parsedSpec = JSON.parse(specBytes.toString("utf8"));
|
|
1587
1556
|
assert2(
|
|
1588
|
-
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0,
|
|
1557
|
+
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto2.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
|
|
1589
1558
|
"core result is not bound by its completed core research manifest"
|
|
1590
1559
|
);
|
|
1591
1560
|
for (const [relativePath, expectedSha256] of Object.entries(
|
|
@@ -168,10 +168,10 @@ var init_io = __esm({
|
|
|
168
168
|
sha256Text = (value) => (0, import_node_crypto.createHash)("sha256").update(value).digest("hex");
|
|
169
169
|
sha256Json = (value) => sha256Text(canonicalJson(value));
|
|
170
170
|
sha256File = async (filePath) => {
|
|
171
|
-
const
|
|
171
|
+
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
172
172
|
const input = (0, import_node_fs2.createReadStream)(filePath);
|
|
173
|
-
for await (const chunk of input)
|
|
174
|
-
return
|
|
173
|
+
for await (const chunk of input) hash.update(chunk);
|
|
174
|
+
return hash.digest("hex");
|
|
175
175
|
};
|
|
176
176
|
assertFinite = (value, name) => {
|
|
177
177
|
assert(typeof value === "number" && Number.isFinite(value), name);
|
|
@@ -451,14 +451,14 @@ __export(io_exports, {
|
|
|
451
451
|
verifyResearchState: () => verifyResearchState,
|
|
452
452
|
withResearchLock: () => withResearchLock
|
|
453
453
|
});
|
|
454
|
-
var import_promises2, import_node_path3, import_node_os,
|
|
454
|
+
var import_promises2, import_node_path3, import_node_os, import_node_crypto2, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
|
|
455
455
|
var init_io2 = __esm({
|
|
456
456
|
"src/lib/strategyResearch/io.ts"() {
|
|
457
457
|
"use strict";
|
|
458
458
|
import_promises2 = __toESM(require("fs/promises"));
|
|
459
459
|
import_node_path3 = __toESM(require("path"));
|
|
460
460
|
import_node_os = __toESM(require("os"));
|
|
461
|
-
|
|
461
|
+
import_node_crypto2 = require("crypto");
|
|
462
462
|
init_io();
|
|
463
463
|
researchDirectory = (projectRoot, spec) => import_node_path3.default.join(projectRoot, "data/research/strategy", spec.core.researchId);
|
|
464
464
|
readJson = async (file) => JSON.parse(await import_promises2.default.readFile(file, "utf8"));
|
|
@@ -487,7 +487,7 @@ var init_io2 = __esm({
|
|
|
487
487
|
"data/research/strategy/.lock"
|
|
488
488
|
);
|
|
489
489
|
await import_promises2.default.mkdir(import_node_path3.default.dirname(file), { recursive: true });
|
|
490
|
-
const token = (0,
|
|
490
|
+
const token = (0, import_node_crypto2.randomUUID)();
|
|
491
491
|
const acquire = () => import_promises2.default.writeFile(
|
|
492
492
|
file,
|
|
493
493
|
JSON.stringify({ pid: process.pid, host: import_node_os.default.hostname(), token }),
|
|
@@ -583,15 +583,15 @@ var init_io2 = __esm({
|
|
|
583
583
|
await writeJsonAtomic(file, state);
|
|
584
584
|
return state;
|
|
585
585
|
};
|
|
586
|
-
isRetainedDeletion = async (directory, file,
|
|
586
|
+
isRetainedDeletion = async (directory, file, hash) => {
|
|
587
587
|
try {
|
|
588
588
|
const inventory = await readJson(import_node_path3.default.join(directory, "retention.json"));
|
|
589
589
|
const index = inventory.entries.findIndex(
|
|
590
|
-
(entry) => entry.path === file && entry.sha256 ===
|
|
590
|
+
(entry) => entry.path === file && entry.sha256 === hash
|
|
591
591
|
);
|
|
592
592
|
if (index < 0) return false;
|
|
593
593
|
const receipt = await readJson(import_node_path3.default.join(directory, "retention", `${index}.json`));
|
|
594
|
-
return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 ===
|
|
594
|
+
return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 === hash;
|
|
595
595
|
} catch (error) {
|
|
596
596
|
if (error.code === "ENOENT") return false;
|
|
597
597
|
throw error;
|
|
@@ -1927,15 +1927,15 @@ var createPocketResult = (rows, predicates, mask, validationRows, testRows, obje
|
|
|
1927
1927
|
};
|
|
1928
1928
|
};
|
|
1929
1929
|
var hashMask = (mask) => {
|
|
1930
|
-
let
|
|
1930
|
+
let hash = 2166136261;
|
|
1931
1931
|
for (let index = 0; index < mask.length; index += 1) {
|
|
1932
1932
|
if (mask[index] !== 1) {
|
|
1933
1933
|
continue;
|
|
1934
1934
|
}
|
|
1935
|
-
|
|
1936
|
-
|
|
1935
|
+
hash ^= index + 1;
|
|
1936
|
+
hash = Math.imul(hash, 16777619);
|
|
1937
1937
|
}
|
|
1938
|
-
return (
|
|
1938
|
+
return (hash >>> 0).toString(36);
|
|
1939
1939
|
};
|
|
1940
1940
|
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;
|
|
1941
1941
|
var estimateCombinationCount = (poolSize, maxDepth, maxCombinations) => {
|
|
@@ -2632,51 +2632,7 @@ var policyVariant = (spec, coreId, policy, id, jev) => {
|
|
|
2632
2632
|
|
|
2633
2633
|
// src/lib/strategyResearch/orchestrator.ts
|
|
2634
2634
|
var import_promises5 = __toESM(require("fs/promises"));
|
|
2635
|
-
|
|
2636
|
-
// src/lib/researchMetricSnapshot.ts
|
|
2637
|
-
var import_node_crypto2 = require("crypto");
|
|
2638
|
-
var import_node_zlib = require("zlib");
|
|
2639
|
-
var MAX_BYTES = 256 * 1024 * 1024;
|
|
2640
|
-
var hash = (bytes) => (0, import_node_crypto2.createHash)("sha256").update(bytes).digest("hex");
|
|
2641
|
-
var validatePermanentResearchMetrics = (value) => {
|
|
2642
|
-
if (!value || typeof value !== "object") return;
|
|
2643
|
-
for (const [key, child] of Object.entries(value)) {
|
|
2644
|
-
if (["matchedPairs", "tradeRows", "allProjectedLeaves"].includes(key) && Array.isArray(child) && child.length)
|
|
2645
|
-
throw new Error(`Temporary payload ${key} is not a permanent metric`);
|
|
2646
|
-
if (key === "trades" && Array.isArray(child) && child.some(
|
|
2647
|
-
(row) => row && typeof row === "object" && ("signalId" in row || "entryTimestamp" in row)
|
|
2648
|
-
))
|
|
2649
|
-
throw new Error("Temporary trade records are not permanent metrics");
|
|
2650
|
-
validatePermanentResearchMetrics(child);
|
|
2651
|
-
}
|
|
2652
|
-
};
|
|
2653
|
-
var encodeResearchMetricSnapshot = (metrics) => {
|
|
2654
|
-
validatePermanentResearchMetrics(metrics);
|
|
2655
|
-
const bytes = Buffer.from(JSON.stringify(metrics));
|
|
2656
|
-
if (bytes.length > MAX_BYTES)
|
|
2657
|
-
throw new Error("Metric snapshot exceeds decoded size limit");
|
|
2658
|
-
return {
|
|
2659
|
-
schema: "tradejs-metric-snapshot/v1",
|
|
2660
|
-
encoding: "gzip+base64",
|
|
2661
|
-
decodedBytes: bytes.length,
|
|
2662
|
-
sha256: hash(bytes),
|
|
2663
|
-
payload: (0, import_node_zlib.gzipSync)(bytes, { level: 9 }).toString("base64")
|
|
2664
|
-
};
|
|
2665
|
-
};
|
|
2666
|
-
var decodeResearchMetricSnapshot = (snapshot) => {
|
|
2667
|
-
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")
|
|
2668
|
-
throw new Error("Invalid metric snapshot envelope");
|
|
2669
|
-
const bytes = (0, import_node_zlib.gunzipSync)(Buffer.from(snapshot.payload, "base64"), {
|
|
2670
|
-
maxOutputLength: snapshot.decodedBytes
|
|
2671
|
-
});
|
|
2672
|
-
if (bytes.length !== snapshot.decodedBytes || hash(bytes) !== snapshot.sha256)
|
|
2673
|
-
throw new Error("Metric snapshot checksum or size mismatch");
|
|
2674
|
-
const metrics = JSON.parse(bytes.toString("utf8"));
|
|
2675
|
-
validatePermanentResearchMetrics(metrics);
|
|
2676
|
-
return metrics;
|
|
2677
|
-
};
|
|
2678
|
-
|
|
2679
|
-
// src/lib/strategyResearch/orchestrator.ts
|
|
2635
|
+
var import_researchMetricSnapshot2 = require("@tradejs/infra/researchMetricSnapshot");
|
|
2680
2636
|
var import_node_path7 = __toESM(require("path"));
|
|
2681
2637
|
|
|
2682
2638
|
// src/lib/coreResearch/metrics.ts
|
|
@@ -3882,8 +3838,9 @@ var import_node_path6 = __toESM(require("path"));
|
|
|
3882
3838
|
|
|
3883
3839
|
// src/lib/strategyRelease/researchRetention.ts
|
|
3884
3840
|
var import_promises3 = __toESM(require("fs/promises"));
|
|
3841
|
+
var import_researchMetricSnapshot = require("@tradejs/infra/researchMetricSnapshot");
|
|
3885
3842
|
var import_node_path5 = __toESM(require("path"));
|
|
3886
|
-
var
|
|
3843
|
+
var import_node_crypto3 = require("crypto");
|
|
3887
3844
|
var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
|
|
3888
3845
|
|
|
3889
3846
|
// src/lib/strategyRelease/researchFileConsumers.ts
|
|
@@ -4032,7 +3989,7 @@ var mapFiles = async (entries, visit) => {
|
|
|
4032
3989
|
if (worker.status === "rejected") throw worker.reason;
|
|
4033
3990
|
return results;
|
|
4034
3991
|
};
|
|
4035
|
-
var fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0,
|
|
3992
|
+
var fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto3.createHash)("sha256").update(await import_promises3.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence.strategyEvidenceFileSha256)(file);
|
|
4036
3993
|
var inside = (root, file) => {
|
|
4037
3994
|
const relative = import_node_path5.default.relative(root, file);
|
|
4038
3995
|
return relative !== "" && !relative.startsWith(`..${import_node_path5.default.sep}`) && relative !== ".." && !import_node_path5.default.isAbsolute(relative);
|
|
@@ -4095,7 +4052,7 @@ var applyResearchRetention = async (options) => {
|
|
|
4095
4052
|
throw new Error(
|
|
4096
4053
|
"Complete v2 note needs one verified metric snapshot"
|
|
4097
4054
|
);
|
|
4098
|
-
decodeResearchMetricSnapshot(JSON.parse(blocks[0][1]));
|
|
4055
|
+
(0, import_researchMetricSnapshot.decodeResearchMetricSnapshot)(JSON.parse(blocks[0][1]));
|
|
4099
4056
|
}
|
|
4100
4057
|
} finally {
|
|
4101
4058
|
await handle.close();
|
|
@@ -4210,11 +4167,11 @@ var createResearchRetentionInventory = async (projectRoot, directory, spec, stat
|
|
|
4210
4167
|
}
|
|
4211
4168
|
const files = /* @__PURE__ */ new Map();
|
|
4212
4169
|
for (const stage of Object.values(state.stages)) {
|
|
4213
|
-
for (const [relative,
|
|
4170
|
+
for (const [relative, hash] of Object.entries(stage.artifacts)) {
|
|
4214
4171
|
const file = await boundResearchPath(directory, relative);
|
|
4215
4172
|
if (relative.endsWith("/result.json")) {
|
|
4216
4173
|
const result = await readJson(file);
|
|
4217
|
-
if (result?.dataset) files.set(file,
|
|
4174
|
+
if (result?.dataset) files.set(file, hash);
|
|
4218
4175
|
}
|
|
4219
4176
|
if (relative.endsWith("/sources.json") || relative.endsWith("/payloads.json")) {
|
|
4220
4177
|
const sources = await readJson(file);
|
|
@@ -4231,13 +4188,13 @@ var createResearchRetentionInventory = async (projectRoot, directory, spec, stat
|
|
|
4231
4188
|
}
|
|
4232
4189
|
}
|
|
4233
4190
|
const entries = [];
|
|
4234
|
-
for (const [file,
|
|
4191
|
+
for (const [file, hash] of files) {
|
|
4235
4192
|
const stat = await import_promises4.default.stat(file);
|
|
4236
4193
|
entries.push({
|
|
4237
4194
|
path: file,
|
|
4238
4195
|
kind: "research_payload",
|
|
4239
4196
|
researchId: spec.core.researchId,
|
|
4240
|
-
sha256:
|
|
4197
|
+
sha256: hash,
|
|
4241
4198
|
bytes: stat.size,
|
|
4242
4199
|
createdAt: stat.birthtimeMs,
|
|
4243
4200
|
verified: true,
|
|
@@ -4497,7 +4454,7 @@ var runStrategyResearch = async (parameters) => {
|
|
|
4497
4454
|
});
|
|
4498
4455
|
let partitionControl;
|
|
4499
4456
|
if (spec.testSince === 0) {
|
|
4500
|
-
const
|
|
4457
|
+
const control = spec.core.variants.find(
|
|
4501
4458
|
(variant) => variant.role === "control"
|
|
4502
4459
|
);
|
|
4503
4460
|
partitionControl = await stage(
|
|
@@ -4514,7 +4471,7 @@ var runStrategyResearch = async (parameters) => {
|
|
|
4514
4471
|
}
|
|
4515
4472
|
return backend.runVariant(
|
|
4516
4473
|
spec,
|
|
4517
|
-
|
|
4474
|
+
control,
|
|
4518
4475
|
folder,
|
|
4519
4476
|
async (runId) => writeJsonAtomic(import_node_path7.default.join(folder, "native-run.json"), {
|
|
4520
4477
|
runId
|
|
@@ -4536,9 +4493,6 @@ var runStrategyResearch = async (parameters) => {
|
|
|
4536
4493
|
let frozenSelection;
|
|
4537
4494
|
const raw = {};
|
|
4538
4495
|
const discovered = [];
|
|
4539
|
-
const control = spec.core.variants.find(
|
|
4540
|
-
(variant) => variant.role === "control"
|
|
4541
|
-
);
|
|
4542
4496
|
const currentPolicy = {
|
|
4543
4497
|
schema: "tradejs-research-entry-policy/v1",
|
|
4544
4498
|
strategy: spec.core.strategy,
|
|
@@ -5014,7 +4968,7 @@ ${JSON.stringify(spec, null, 2)}
|
|
|
5014
4968
|
## Metrics snapshot (machine-readable)
|
|
5015
4969
|
|
|
5016
4970
|
\`\`\`json
|
|
5017
|
-
${JSON.stringify(encodeResearchMetricSnapshot(compact))}
|
|
4971
|
+
${JSON.stringify((0, import_researchMetricSnapshot2.encodeResearchMetricSnapshot)(compact))}
|
|
5018
4972
|
\`\`\`
|
|
5019
4973
|
|
|
5020
4974
|
## Reported metrics
|
|
@@ -5144,7 +5098,7 @@ var import_registry = require("@tradejs/node/registry");
|
|
|
5144
5098
|
var import_connectors = require("@tradejs/node/connectors");
|
|
5145
5099
|
|
|
5146
5100
|
// src/lib/coreResearch/dataset.ts
|
|
5147
|
-
var
|
|
5101
|
+
var import_node_crypto4 = require("crypto");
|
|
5148
5102
|
var import_node_fs3 = require("fs");
|
|
5149
5103
|
var import_node_path8 = __toESM(require("path"));
|
|
5150
5104
|
var import_node_readline2 = __toESM(require("readline"));
|
|
@@ -5359,8 +5313,8 @@ var readCoreResearchVariant = async (variant) => {
|
|
|
5359
5313
|
for (const inputPath of variant.files) {
|
|
5360
5314
|
const filePath = import_node_path8.default.resolve(inputPath);
|
|
5361
5315
|
const input = (0, import_node_fs3.createReadStream)(filePath);
|
|
5362
|
-
const
|
|
5363
|
-
input.on("data", (chunk) =>
|
|
5316
|
+
const hash = (0, import_node_crypto4.createHash)("sha256");
|
|
5317
|
+
input.on("data", (chunk) => hash.update(chunk));
|
|
5364
5318
|
const lines = import_node_readline2.default.createInterface({ input, crlfDelay: Infinity });
|
|
5365
5319
|
const fileTrades = [];
|
|
5366
5320
|
let lineNumber = 0;
|
|
@@ -5410,7 +5364,7 @@ var readCoreResearchVariant = async (variant) => {
|
|
|
5410
5364
|
trades.push(trade);
|
|
5411
5365
|
fileTrades.push(trade);
|
|
5412
5366
|
}
|
|
5413
|
-
const fileSha2562 =
|
|
5367
|
+
const fileSha2562 = hash.digest("hex");
|
|
5414
5368
|
for (const trade of fileTrades) trade.sourceSha256 = fileSha2562;
|
|
5415
5369
|
sources.push({
|
|
5416
5370
|
path: filePath,
|
|
@@ -5430,7 +5384,7 @@ var readCoreResearchVariant = async (variant) => {
|
|
|
5430
5384
|
};
|
|
5431
5385
|
|
|
5432
5386
|
// src/lib/backtest/checkpoint.ts
|
|
5433
|
-
var
|
|
5387
|
+
var import_node_crypto5 = require("crypto");
|
|
5434
5388
|
var import_constants = require("@tradejs/core/constants");
|
|
5435
5389
|
var import_backtest2 = require("@tradejs/core/backtest");
|
|
5436
5390
|
var import_redis = require("@tradejs/infra/redis");
|
|
@@ -5644,7 +5598,7 @@ init_io2();
|
|
|
5644
5598
|
|
|
5645
5599
|
// src/lib/aiTrainResearch.ts
|
|
5646
5600
|
var import_node_child_process2 = require("child_process");
|
|
5647
|
-
var
|
|
5601
|
+
var import_node_crypto7 = require("crypto");
|
|
5648
5602
|
var import_promises7 = __toESM(require("fs/promises"));
|
|
5649
5603
|
var import_node_path10 = __toESM(require("path"));
|
|
5650
5604
|
|
|
@@ -5656,7 +5610,7 @@ var import_strategies = require("@tradejs/node/strategies");
|
|
|
5656
5610
|
var import_types2 = require("@tradejs/types");
|
|
5657
5611
|
|
|
5658
5612
|
// src/lib/strategyGateFingerprint.ts
|
|
5659
|
-
var
|
|
5613
|
+
var import_node_crypto6 = require("crypto");
|
|
5660
5614
|
var import_node_module = require("module");
|
|
5661
5615
|
var import_promises6 = __toESM(require("fs/promises"));
|
|
5662
5616
|
var import_node_path9 = __toESM(require("path"));
|
|
@@ -5700,7 +5654,7 @@ var normalizeForStableJson = (value) => {
|
|
|
5700
5654
|
}
|
|
5701
5655
|
return value;
|
|
5702
5656
|
};
|
|
5703
|
-
var fingerprintResearchValue = (value) => (0,
|
|
5657
|
+
var fingerprintResearchValue = (value) => (0, import_node_crypto7.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
|
|
5704
5658
|
var fingerprintResearchContextEnvironment = (env = process.env) => fingerprintResearchValue(
|
|
5705
5659
|
Object.fromEntries(
|
|
5706
5660
|
RESEARCH_CONTEXT_ENV_KEYS.map((key) => [key, env[key] ?? null])
|
|
@@ -6667,7 +6621,7 @@ init_io();
|
|
|
6667
6621
|
var import_promises11 = __toESM(require("fs/promises"));
|
|
6668
6622
|
var import_node_path15 = __toESM(require("path"));
|
|
6669
6623
|
var import_node_child_process4 = require("child_process");
|
|
6670
|
-
var
|
|
6624
|
+
var import_node_crypto9 = require("crypto");
|
|
6671
6625
|
var import_coreResearch2 = require("@tradejs/infra/coreResearch");
|
|
6672
6626
|
|
|
6673
6627
|
// src/lib/coreResearch/artifacts.ts
|
|
@@ -6681,7 +6635,7 @@ init_io();
|
|
|
6681
6635
|
init_io();
|
|
6682
6636
|
|
|
6683
6637
|
// src/lib/coreResearch/statistics.ts
|
|
6684
|
-
var
|
|
6638
|
+
var import_node_crypto8 = require("crypto");
|
|
6685
6639
|
|
|
6686
6640
|
// src/lib/coreResearch/orchestrator.ts
|
|
6687
6641
|
init_trace();
|
|
@@ -6720,7 +6674,7 @@ var createCoreResearchSpecTemplate = (params) => {
|
|
|
6720
6674
|
gitSha,
|
|
6721
6675
|
...sourceRepository ? { sourceRepository } : {},
|
|
6722
6676
|
...dirtyDiff ? {
|
|
6723
|
-
dirtyDiffSha256: (0,
|
|
6677
|
+
dirtyDiffSha256: (0, import_node_crypto9.createHash)("sha256").update(dirtyDiff).digest("hex")
|
|
6724
6678
|
} : {}
|
|
6725
6679
|
};
|
|
6726
6680
|
} catch {
|
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.296",
|
|
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.296",
|
|
41
|
+
"@tradejs/core": "^3.1.29-beta.296",
|
|
42
|
+
"@tradejs/indicators": "^3.1.29-beta.296",
|
|
43
|
+
"@tradejs/infra": "^3.1.29-beta.296",
|
|
44
|
+
"@tradejs/node": "^3.1.29-beta.296",
|
|
45
45
|
"@tradejs/strategy-kit": "3.0.6",
|
|
46
|
-
"@tradejs/types": "^3.1.29-beta.
|
|
46
|
+
"@tradejs/types": "^3.1.29-beta.296",
|
|
47
47
|
"args": "^5.0.3",
|
|
48
48
|
"bcryptjs": "^2.4.3",
|
|
49
49
|
"chalk": "4.1.2",
|
|
@@ -1,74 +0,0 @@
|
|
|
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
|
-
});
|