@tradejs/cli 3.1.29-beta.292 → 3.1.29-beta.297

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.
@@ -380,13 +380,12 @@ var getReferenceSymbols = () => {
380
380
  };
381
381
  var intervalToMarketFeatureInterval = (interval) => {
382
382
  const normalized = String(interval).trim().toLowerCase();
383
- if (normalized === "1" || normalized === "1m") return "1m";
383
+ if (normalized === "1" || normalized === "1m") return null;
384
384
  if (normalized === "5" || normalized === "5m") return "5m";
385
385
  if (normalized === "60" || normalized === "1h") return "1h";
386
386
  return "15m";
387
387
  };
388
388
  var marketIntervalToConnectorInterval = (interval) => {
389
- if (interval === "1m") return "1";
390
389
  if (interval === "5m") return "5";
391
390
  if (interval === "1h") return "60";
392
391
  return "15";
@@ -551,6 +550,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
551
550
  return skippedBackfillResult();
552
551
  }
553
552
  const interval = intervalToMarketFeatureInterval(params.interval);
553
+ if (interval === null) return skippedBackfillResult();
554
554
  const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
555
555
  const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
556
556
  if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
@@ -362,7 +362,7 @@ var coinMarketCapFetch = async (params) => {
362
362
  };
363
363
  var fetchCoinMarketCapIndexRows = async (params) => {
364
364
  const rows = [];
365
- const maxChunkDays = 9;
365
+ const maxChunkDays = 4;
366
366
  const totalChunks = Math.max(
367
367
  1,
368
368
  Math.ceil(
@@ -799,11 +799,27 @@ var backfillCoinMarketCapContext = async (params) => {
799
799
  toMs
800
800
  })
801
801
  );
802
- const globalDailyReady = globalDailyCached || globalDailyBackfillCovered;
803
- const referencesDailyReady = referencesDailyCached || referencesDailyBackfillCovered;
804
- const exchangeLiquidityReady = exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered;
805
- const fearGreedReady = fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered;
806
- const indexesReady = indexesCached || indexesBackfillCovered;
802
+ const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
803
+ const globalDailyReady = ready(
804
+ "cmc-global-1d",
805
+ globalDailyCached || globalDailyBackfillCovered
806
+ );
807
+ const referencesDailyReady = ready(
808
+ "cmc-reference_asset-1d",
809
+ referencesDailyCached || referencesDailyBackfillCovered
810
+ );
811
+ const exchangeLiquidityReady = ready(
812
+ "cmc-exchange_liquidity-1d",
813
+ exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
814
+ );
815
+ const fearGreedReady = ready(
816
+ "cmc-fear_greed-1d",
817
+ fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
818
+ );
819
+ const indexesReady = ready(
820
+ "cmc-index-1d",
821
+ indexesCached || indexesBackfillCovered
822
+ );
807
823
  let globalStatus = resolveBackfillStatus({
808
824
  cached: globalDailyCached,
809
825
  covered: globalDailyBackfillCovered
@@ -39,6 +39,7 @@ __export(derivativesContextBackfill_exports, {
39
39
  isBacktestDerivativesContextEnabled: () => isBacktestDerivativesContextEnabled,
40
40
  isDerivativesTargetContextEnabled: () => isDerivativesTargetContextEnabled,
41
41
  isSignalsDerivativesContextEnabled: () => isSignalsDerivativesContextEnabled,
42
+ resolveCoinalyzeBackfillMarket: () => resolveCoinalyzeBackfillMarket,
42
43
  resolveDerivativesContextBackfillSymbols: () => resolveDerivativesContextBackfillSymbols,
43
44
  resolveDerivativesContextBackfillWindow: () => resolveDerivativesContextBackfillWindow,
44
45
  resolveDerivativesContextFetchFromMs: () => resolveDerivativesContextFetchFromMs,
@@ -481,6 +482,18 @@ var buildMatches = (tickers, markets, exchangePriority) => {
481
482
  }
482
483
  return { matches, unmatched };
483
484
  };
485
+ async function resolveCoinalyzeBackfillMarket(userName, symbol) {
486
+ const apiKey = await getCoinalyzeApiKey(userName);
487
+ if (!apiKey) throw new Error("Missing Coinalyze API key.");
488
+ const markets = (await fetchCoinalyzeMarkets(apiKey)).filter(
489
+ (market) => market.quote_asset?.toUpperCase() === "USDT" && market.is_perpetual
490
+ );
491
+ const priority = parseList(
492
+ process.env.COINALYZE_EXCHANGE_PRIORITY || process.env.DERIVATIVES_CONTEXT_EXCHANGE_PRIORITY || "A,6,0"
493
+ );
494
+ const { matches } = buildMatches([symbol], markets, priority);
495
+ return { apiKey, marketSymbol: matches[0]?.marketSymbol };
496
+ }
484
497
  var normalizeMetricPoint = (metric, point) => {
485
498
  if (metric === "oi") {
486
499
  return {
@@ -1042,6 +1055,7 @@ var backfillDerivativesContextForSignals = async (params) => backfillDerivatives
1042
1055
  isBacktestDerivativesContextEnabled,
1043
1056
  isDerivativesTargetContextEnabled,
1044
1057
  isSignalsDerivativesContextEnabled,
1058
+ resolveCoinalyzeBackfillMarket,
1045
1059
  resolveDerivativesContextBackfillSymbols,
1046
1060
  resolveDerivativesContextBackfillWindow,
1047
1061
  resolveDerivativesContextFetchFromMs,
@@ -381,13 +381,12 @@ var getReferenceSymbols = () => {
381
381
  };
382
382
  var intervalToMarketFeatureInterval = (interval) => {
383
383
  const normalized = String(interval).trim().toLowerCase();
384
- if (normalized === "1" || normalized === "1m") return "1m";
384
+ if (normalized === "1" || normalized === "1m") return null;
385
385
  if (normalized === "5" || normalized === "5m") return "5m";
386
386
  if (normalized === "60" || normalized === "1h") return "1h";
387
387
  return "15m";
388
388
  };
389
389
  var marketIntervalToConnectorInterval = (interval) => {
390
- if (interval === "1m") return "1";
391
390
  if (interval === "5m") return "5";
392
391
  if (interval === "1h") return "60";
393
392
  return "15";
@@ -552,6 +551,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
552
551
  return skippedBackfillResult();
553
552
  }
554
553
  const interval = intervalToMarketFeatureInterval(params.interval);
554
+ if (interval === null) return skippedBackfillResult();
555
555
  const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
556
556
  const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
557
557
  if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
@@ -2132,7 +2132,7 @@ var coinMarketCapFetch = async (params) => {
2132
2132
  };
2133
2133
  var fetchCoinMarketCapIndexRows = async (params) => {
2134
2134
  const rows = [];
2135
- const maxChunkDays = 9;
2135
+ const maxChunkDays = 4;
2136
2136
  const totalChunks = Math.max(
2137
2137
  1,
2138
2138
  Math.ceil(
@@ -2569,11 +2569,27 @@ var backfillCoinMarketCapContext = async (params) => {
2569
2569
  toMs
2570
2570
  })
2571
2571
  );
2572
- const globalDailyReady = globalDailyCached || globalDailyBackfillCovered;
2573
- const referencesDailyReady = referencesDailyCached || referencesDailyBackfillCovered;
2574
- const exchangeLiquidityReady = exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered;
2575
- const fearGreedReady = fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered;
2576
- const indexesReady = indexesCached || indexesBackfillCovered;
2572
+ const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
2573
+ const globalDailyReady = ready(
2574
+ "cmc-global-1d",
2575
+ globalDailyCached || globalDailyBackfillCovered
2576
+ );
2577
+ const referencesDailyReady = ready(
2578
+ "cmc-reference_asset-1d",
2579
+ referencesDailyCached || referencesDailyBackfillCovered
2580
+ );
2581
+ const exchangeLiquidityReady = ready(
2582
+ "cmc-exchange_liquidity-1d",
2583
+ exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
2584
+ );
2585
+ const fearGreedReady = ready(
2586
+ "cmc-fear_greed-1d",
2587
+ fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
2588
+ );
2589
+ const indexesReady = ready(
2590
+ "cmc-index-1d",
2591
+ indexesCached || indexesBackfillCovered
2592
+ );
2577
2593
  let globalStatus = resolveBackfillStatus({
2578
2594
  cached: globalDailyCached,
2579
2595
  covered: globalDailyBackfillCovered
@@ -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 hash2 = (0, import_node_crypto.createHash)("sha256");
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) hash2.update(chunk);
174
- return hash2.digest("hex");
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);
@@ -445,14 +445,14 @@ __export(io_exports, {
445
445
  verifyResearchState: () => verifyResearchState,
446
446
  withResearchLock: () => withResearchLock
447
447
  });
448
- var import_promises2, import_node_path3, import_node_os, import_node_crypto3, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
448
+ var import_promises2, import_node_path3, import_node_os, import_node_crypto2, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
449
449
  var init_io2 = __esm({
450
450
  "src/lib/strategyResearch/io.ts"() {
451
451
  "use strict";
452
452
  import_promises2 = __toESM(require("fs/promises"));
453
453
  import_node_path3 = __toESM(require("path"));
454
454
  import_node_os = __toESM(require("os"));
455
- import_node_crypto3 = require("crypto");
455
+ import_node_crypto2 = require("crypto");
456
456
  init_io();
457
457
  researchDirectory = (projectRoot, spec) => import_node_path3.default.join(projectRoot, "data/research/strategy", spec.core.researchId);
458
458
  readJson = async (file) => JSON.parse(await import_promises2.default.readFile(file, "utf8"));
@@ -481,7 +481,7 @@ var init_io2 = __esm({
481
481
  "data/research/strategy/.lock"
482
482
  );
483
483
  await import_promises2.default.mkdir(import_node_path3.default.dirname(file), { recursive: true });
484
- const token = (0, import_node_crypto3.randomUUID)();
484
+ const token = (0, import_node_crypto2.randomUUID)();
485
485
  const acquire = () => import_promises2.default.writeFile(
486
486
  file,
487
487
  JSON.stringify({ pid: process.pid, host: import_node_os.default.hostname(), token }),
@@ -577,15 +577,15 @@ var init_io2 = __esm({
577
577
  await writeJsonAtomic(file, state);
578
578
  return state;
579
579
  };
580
- isRetainedDeletion = async (directory, file, hash2) => {
580
+ isRetainedDeletion = async (directory, file, hash) => {
581
581
  try {
582
582
  const inventory = await readJson(import_node_path3.default.join(directory, "retention.json"));
583
583
  const index = inventory.entries.findIndex(
584
- (entry) => entry.path === file && entry.sha256 === hash2
584
+ (entry) => entry.path === file && entry.sha256 === hash
585
585
  );
586
586
  if (index < 0) return false;
587
587
  const receipt = await readJson(import_node_path3.default.join(directory, "retention", `${index}.json`));
588
- return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 === hash2;
588
+ return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 === hash;
589
589
  } catch (error) {
590
590
  if (error.code === "ENOENT") return false;
591
591
  throw error;
@@ -1922,15 +1922,15 @@ var createPocketResult = (rows, predicates, mask, validationRows, testRows, obje
1922
1922
  };
1923
1923
  };
1924
1924
  var hashMask = (mask) => {
1925
- let hash2 = 2166136261;
1925
+ let hash = 2166136261;
1926
1926
  for (let index = 0; index < mask.length; index += 1) {
1927
1927
  if (mask[index] !== 1) {
1928
1928
  continue;
1929
1929
  }
1930
- hash2 ^= index + 1;
1931
- hash2 = Math.imul(hash2, 16777619);
1930
+ hash ^= index + 1;
1931
+ hash = Math.imul(hash, 16777619);
1932
1932
  }
1933
- return (hash2 >>> 0).toString(36);
1933
+ return (hash >>> 0).toString(36);
1934
1934
  };
1935
1935
  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;
1936
1936
  var estimateCombinationCount = (poolSize, maxDepth, maxCombinations) => {
@@ -2627,51 +2627,7 @@ var policyVariant = (spec, coreId, policy, id, jev) => {
2627
2627
 
2628
2628
  // src/lib/strategyResearch/orchestrator.ts
2629
2629
  var import_promises5 = __toESM(require("fs/promises"));
2630
-
2631
- // src/lib/researchMetricSnapshot.ts
2632
- var import_node_crypto2 = require("crypto");
2633
- var import_node_zlib = require("zlib");
2634
- var MAX_BYTES = 256 * 1024 * 1024;
2635
- var hash = (bytes) => (0, import_node_crypto2.createHash)("sha256").update(bytes).digest("hex");
2636
- var validatePermanentResearchMetrics = (value) => {
2637
- if (!value || typeof value !== "object") return;
2638
- for (const [key, child] of Object.entries(value)) {
2639
- if (["matchedPairs", "tradeRows", "allProjectedLeaves"].includes(key) && Array.isArray(child) && child.length)
2640
- throw new Error(`Temporary payload ${key} is not a permanent metric`);
2641
- if (key === "trades" && Array.isArray(child) && child.some(
2642
- (row) => row && typeof row === "object" && ("signalId" in row || "entryTimestamp" in row)
2643
- ))
2644
- throw new Error("Temporary trade records are not permanent metrics");
2645
- validatePermanentResearchMetrics(child);
2646
- }
2647
- };
2648
- var encodeResearchMetricSnapshot = (metrics) => {
2649
- validatePermanentResearchMetrics(metrics);
2650
- const bytes = Buffer.from(JSON.stringify(metrics));
2651
- if (bytes.length > MAX_BYTES)
2652
- throw new Error("Metric snapshot exceeds decoded size limit");
2653
- return {
2654
- schema: "tradejs-metric-snapshot/v1",
2655
- encoding: "gzip+base64",
2656
- decodedBytes: bytes.length,
2657
- sha256: hash(bytes),
2658
- payload: (0, import_node_zlib.gzipSync)(bytes, { level: 9 }).toString("base64")
2659
- };
2660
- };
2661
- var decodeResearchMetricSnapshot = (snapshot) => {
2662
- 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")
2663
- throw new Error("Invalid metric snapshot envelope");
2664
- const bytes = (0, import_node_zlib.gunzipSync)(Buffer.from(snapshot.payload, "base64"), {
2665
- maxOutputLength: snapshot.decodedBytes
2666
- });
2667
- if (bytes.length !== snapshot.decodedBytes || hash(bytes) !== snapshot.sha256)
2668
- throw new Error("Metric snapshot checksum or size mismatch");
2669
- const metrics = JSON.parse(bytes.toString("utf8"));
2670
- validatePermanentResearchMetrics(metrics);
2671
- return metrics;
2672
- };
2673
-
2674
- // src/lib/strategyResearch/orchestrator.ts
2630
+ var import_researchMetricSnapshot2 = require("@tradejs/infra/researchMetricSnapshot");
2675
2631
  var import_node_path7 = __toESM(require("path"));
2676
2632
 
2677
2633
  // src/lib/coreResearch/metrics.ts
@@ -3877,8 +3833,9 @@ var import_node_path6 = __toESM(require("path"));
3877
3833
 
3878
3834
  // src/lib/strategyRelease/researchRetention.ts
3879
3835
  var import_promises3 = __toESM(require("fs/promises"));
3836
+ var import_researchMetricSnapshot = require("@tradejs/infra/researchMetricSnapshot");
3880
3837
  var import_node_path5 = __toESM(require("path"));
3881
- var import_node_crypto4 = require("crypto");
3838
+ var import_node_crypto3 = require("crypto");
3882
3839
  var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
3883
3840
 
3884
3841
  // src/lib/strategyRelease/researchFileConsumers.ts
@@ -4027,7 +3984,7 @@ var mapFiles = async (entries, visit) => {
4027
3984
  if (worker.status === "rejected") throw worker.reason;
4028
3985
  return results;
4029
3986
  };
4030
- 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);
3987
+ 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);
4031
3988
  var inside = (root, file) => {
4032
3989
  const relative = import_node_path5.default.relative(root, file);
4033
3990
  return relative !== "" && !relative.startsWith(`..${import_node_path5.default.sep}`) && relative !== ".." && !import_node_path5.default.isAbsolute(relative);
@@ -4090,7 +4047,7 @@ var applyResearchRetention = async (options) => {
4090
4047
  throw new Error(
4091
4048
  "Complete v2 note needs one verified metric snapshot"
4092
4049
  );
4093
- decodeResearchMetricSnapshot(JSON.parse(blocks[0][1]));
4050
+ (0, import_researchMetricSnapshot.decodeResearchMetricSnapshot)(JSON.parse(blocks[0][1]));
4094
4051
  }
4095
4052
  } finally {
4096
4053
  await handle.close();
@@ -4205,11 +4162,11 @@ var createResearchRetentionInventory = async (projectRoot, directory, spec, stat
4205
4162
  }
4206
4163
  const files = /* @__PURE__ */ new Map();
4207
4164
  for (const stage of Object.values(state.stages)) {
4208
- for (const [relative, hash2] of Object.entries(stage.artifacts)) {
4165
+ for (const [relative, hash] of Object.entries(stage.artifacts)) {
4209
4166
  const file = await boundResearchPath(directory, relative);
4210
4167
  if (relative.endsWith("/result.json")) {
4211
4168
  const result = await readJson(file);
4212
- if (result?.dataset) files.set(file, hash2);
4169
+ if (result?.dataset) files.set(file, hash);
4213
4170
  }
4214
4171
  if (relative.endsWith("/sources.json") || relative.endsWith("/payloads.json")) {
4215
4172
  const sources = await readJson(file);
@@ -4226,13 +4183,13 @@ var createResearchRetentionInventory = async (projectRoot, directory, spec, stat
4226
4183
  }
4227
4184
  }
4228
4185
  const entries = [];
4229
- for (const [file, hash2] of files) {
4186
+ for (const [file, hash] of files) {
4230
4187
  const stat = await import_promises4.default.stat(file);
4231
4188
  entries.push({
4232
4189
  path: file,
4233
4190
  kind: "research_payload",
4234
4191
  researchId: spec.core.researchId,
4235
- sha256: hash2,
4192
+ sha256: hash,
4236
4193
  bytes: stat.size,
4237
4194
  createdAt: stat.birthtimeMs,
4238
4195
  verified: true,
@@ -4492,7 +4449,7 @@ var runStrategyResearch = async (parameters) => {
4492
4449
  });
4493
4450
  let partitionControl;
4494
4451
  if (spec.testSince === 0) {
4495
- const control2 = spec.core.variants.find(
4452
+ const control = spec.core.variants.find(
4496
4453
  (variant) => variant.role === "control"
4497
4454
  );
4498
4455
  partitionControl = await stage(
@@ -4509,7 +4466,7 @@ var runStrategyResearch = async (parameters) => {
4509
4466
  }
4510
4467
  return backend.runVariant(
4511
4468
  spec,
4512
- control2,
4469
+ control,
4513
4470
  folder,
4514
4471
  async (runId) => writeJsonAtomic(import_node_path7.default.join(folder, "native-run.json"), {
4515
4472
  runId
@@ -4531,9 +4488,6 @@ var runStrategyResearch = async (parameters) => {
4531
4488
  let frozenSelection;
4532
4489
  const raw = {};
4533
4490
  const discovered = [];
4534
- const control = spec.core.variants.find(
4535
- (variant) => variant.role === "control"
4536
- );
4537
4491
  const currentPolicy = {
4538
4492
  schema: "tradejs-research-entry-policy/v1",
4539
4493
  strategy: spec.core.strategy,
@@ -5009,7 +4963,7 @@ ${JSON.stringify(spec, null, 2)}
5009
4963
  ## Metrics snapshot (machine-readable)
5010
4964
 
5011
4965
  \`\`\`json
5012
- ${JSON.stringify(encodeResearchMetricSnapshot(compact))}
4966
+ ${JSON.stringify((0, import_researchMetricSnapshot2.encodeResearchMetricSnapshot)(compact))}
5013
4967
  \`\`\`
5014
4968
 
5015
4969
  ## Reported metrics
@@ -5139,7 +5093,7 @@ var import_registry = require("@tradejs/node/registry");
5139
5093
  var import_connectors = require("@tradejs/node/connectors");
5140
5094
 
5141
5095
  // src/lib/coreResearch/dataset.ts
5142
- var import_node_crypto5 = require("crypto");
5096
+ var import_node_crypto4 = require("crypto");
5143
5097
  var import_node_fs3 = require("fs");
5144
5098
  var import_node_path8 = __toESM(require("path"));
5145
5099
  var import_node_readline2 = __toESM(require("readline"));
@@ -5354,8 +5308,8 @@ var readCoreResearchVariant = async (variant) => {
5354
5308
  for (const inputPath of variant.files) {
5355
5309
  const filePath = import_node_path8.default.resolve(inputPath);
5356
5310
  const input = (0, import_node_fs3.createReadStream)(filePath);
5357
- const hash2 = (0, import_node_crypto5.createHash)("sha256");
5358
- input.on("data", (chunk) => hash2.update(chunk));
5311
+ const hash = (0, import_node_crypto4.createHash)("sha256");
5312
+ input.on("data", (chunk) => hash.update(chunk));
5359
5313
  const lines = import_node_readline2.default.createInterface({ input, crlfDelay: Infinity });
5360
5314
  const fileTrades = [];
5361
5315
  let lineNumber = 0;
@@ -5405,7 +5359,7 @@ var readCoreResearchVariant = async (variant) => {
5405
5359
  trades.push(trade);
5406
5360
  fileTrades.push(trade);
5407
5361
  }
5408
- const fileSha2562 = hash2.digest("hex");
5362
+ const fileSha2562 = hash.digest("hex");
5409
5363
  for (const trade of fileTrades) trade.sourceSha256 = fileSha2562;
5410
5364
  sources.push({
5411
5365
  path: filePath,
@@ -5425,7 +5379,7 @@ var readCoreResearchVariant = async (variant) => {
5425
5379
  };
5426
5380
 
5427
5381
  // src/lib/backtest/checkpoint.ts
5428
- var import_node_crypto6 = require("crypto");
5382
+ var import_node_crypto5 = require("crypto");
5429
5383
  var import_constants = require("@tradejs/core/constants");
5430
5384
  var import_backtest2 = require("@tradejs/core/backtest");
5431
5385
  var import_redis = require("@tradejs/infra/redis");
@@ -5639,7 +5593,7 @@ init_io2();
5639
5593
 
5640
5594
  // src/lib/aiTrainResearch.ts
5641
5595
  var import_node_child_process2 = require("child_process");
5642
- var import_node_crypto8 = require("crypto");
5596
+ var import_node_crypto7 = require("crypto");
5643
5597
  var import_promises7 = __toESM(require("fs/promises"));
5644
5598
  var import_node_path10 = __toESM(require("path"));
5645
5599
 
@@ -5651,7 +5605,7 @@ var import_strategies = require("@tradejs/node/strategies");
5651
5605
  var import_types2 = require("@tradejs/types");
5652
5606
 
5653
5607
  // src/lib/strategyGateFingerprint.ts
5654
- var import_node_crypto7 = require("crypto");
5608
+ var import_node_crypto6 = require("crypto");
5655
5609
  var import_node_module = require("module");
5656
5610
  var import_promises6 = __toESM(require("fs/promises"));
5657
5611
  var import_node_path9 = __toESM(require("path"));
@@ -5695,7 +5649,7 @@ var normalizeForStableJson = (value) => {
5695
5649
  }
5696
5650
  return value;
5697
5651
  };
5698
- var fingerprintResearchValue = (value) => (0, import_node_crypto8.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
5652
+ var fingerprintResearchValue = (value) => (0, import_node_crypto7.createHash)("sha256").update(JSON.stringify(normalizeForStableJson(value))).digest("hex").slice(0, 16);
5699
5653
  var fingerprintResearchContextEnvironment = (env = process.env) => fingerprintResearchValue(
5700
5654
  Object.fromEntries(
5701
5655
  RESEARCH_CONTEXT_ENV_KEYS.map((key) => [key, env[key] ?? null])