@tradejs/cli 2.0.15 → 2.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,7 +34,8 @@ __export(aiTrainResearch_exports, {
34
34
  fingerprintResearchValue: () => fingerprintResearchValue,
35
35
  summarizeAiTrainCoverage: () => summarizeAiTrainCoverage,
36
36
  summarizeAiTrainRejectReasons: () => summarizeAiTrainRejectReasons,
37
- summarizeAiTrainTerminalWindows: () => summarizeAiTrainTerminalWindows
37
+ summarizeAiTrainTerminalWindows: () => summarizeAiTrainTerminalWindows,
38
+ writeAiTrainResearchSnapshot: () => writeAiTrainResearchSnapshot
38
39
  });
39
40
  module.exports = __toCommonJS(aiTrainResearch_exports);
40
41
  var import_node_child_process = require("child_process");
@@ -350,6 +351,20 @@ var DERIVATIVES_CONTEXT_DATA_MODEL = {
350
351
  hyperliquidWhaleMinCoveragePct: 0.8,
351
352
  hyperliquidWhaleDataModelVersion: import_types.HYPERLIQUID_WHALE_DATA_MODEL_VERSION
352
353
  };
354
+ var writeAiTrainResearchSnapshot = async ({
355
+ outputPath,
356
+ result
357
+ }) => {
358
+ const resolvedPath = import_node_path.default.resolve(outputPath);
359
+ await import_promises.default.mkdir(import_node_path.default.dirname(resolvedPath), { recursive: true });
360
+ await import_promises.default.writeFile(
361
+ resolvedPath,
362
+ `${JSON.stringify(result, null, 2)}
363
+ `,
364
+ "utf8"
365
+ );
366
+ return resolvedPath;
367
+ };
353
368
  var normalizeForStableJson = (value) => {
354
369
  if (Array.isArray(value)) {
355
370
  return value.map(normalizeForStableJson);
@@ -464,6 +479,7 @@ var resolveGateFingerprint = async (projectRoot, strategyName, gitSha) => {
464
479
  `packages/strategies/src/${strategyName}/guardrails.ts`,
465
480
  `packages/strategies/src/${strategyName}/pockets.ts`,
466
481
  `packages/strategies/src/${strategyName}/config.ts`,
482
+ "packages/strategies/src/shared/localAiGate.ts",
467
483
  "packages/node/src/ai.ts"
468
484
  ];
469
485
  const optionalSourceEntries = await Promise.all(
@@ -532,5 +548,6 @@ var buildAiTrainLineage = async ({
532
548
  fingerprintResearchValue,
533
549
  summarizeAiTrainCoverage,
534
550
  summarizeAiTrainRejectReasons,
535
- summarizeAiTrainTerminalWindows
551
+ summarizeAiTrainTerminalWindows,
552
+ writeAiTrainResearchSnapshot
536
553
  });
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
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
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/lib/hyperliquidWhaleBackfill.ts
@@ -24,6 +34,7 @@ __export(hyperliquidWhaleBackfill_exports, {
24
34
  fetchHyperliquidUserFillsByTime: () => fetchHyperliquidUserFillsByTime
25
35
  });
26
36
  module.exports = __toCommonJS(hyperliquidWhaleBackfill_exports);
37
+ var import_progress = __toESM(require("progress"));
27
38
  var import_timescale = require("@tradejs/infra/timescale");
28
39
  var import_strategies = require("@tradejs/node/strategies");
29
40
 
@@ -398,11 +409,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
398
409
  toMs,
399
410
  ...identity
400
411
  });
412
+ const totalCoverageBuckets = Math.ceil(
413
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
414
+ );
415
+ const coverageBar = new import_progress.default(
416
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
417
+ {
418
+ total: Math.max(1, totalCoverageBuckets),
419
+ width: 24
420
+ }
421
+ );
422
+ let displayedCoverageBuckets = 0;
401
423
  const coverageBuckets = await (0, import_timescale.rebuildHyperliquidWhaleCoverageRows)({
402
424
  fromMs,
403
425
  toMs,
404
426
  expectedWhales: whales.addresses.length,
405
- ...identity
427
+ ...identity,
428
+ onProgress: (progress) => {
429
+ const next = Math.max(
430
+ displayedCoverageBuckets,
431
+ Math.min(progress.completedBuckets, coverageBar.total)
432
+ );
433
+ const delta = next - displayedCoverageBuckets;
434
+ if (delta > 0) {
435
+ coverageBar.tick(delta, {
436
+ rows: progress.rows,
437
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
438
+ });
439
+ displayedCoverageBuckets = next;
440
+ }
441
+ }
406
442
  });
407
443
  const result = {
408
444
  cached: false,
@@ -1637,6 +1637,7 @@ var require_list_it = __commonJS({
1637
1637
  var marketContextPrepare_exports = {};
1638
1638
  __export(marketContextPrepare_exports, {
1639
1639
  prepareMarketContextForRun: () => prepareMarketContextForRun,
1640
+ resolveMarketContextRunRequirements: () => resolveMarketContextRunRequirements,
1640
1641
  shouldPrepareBinanceMarketContextForRun: () => shouldPrepareBinanceMarketContextForRun,
1641
1642
  shouldPrepareCoinMarketCapContextForRun: () => shouldPrepareCoinMarketCapContextForRun,
1642
1643
  shouldPrepareDerivativesContextForRun: () => shouldPrepareDerivativesContextForRun,
@@ -1644,6 +1645,8 @@ __export(marketContextPrepare_exports, {
1644
1645
  });
1645
1646
  module.exports = __toCommonJS(marketContextPrepare_exports);
1646
1647
  var import_chalk4 = __toESM(require("chalk"));
1648
+ var import_timescale5 = require("@tradejs/infra/timescale");
1649
+ var import_registry = require("@tradejs/node/registry");
1647
1650
 
1648
1651
  // src/lib/binanceMarketContextBackfill.ts
1649
1652
  var import_progress = __toESM(require("progress"));
@@ -4498,6 +4501,7 @@ var timeOperation = async (label, operation, log = console.log) => {
4498
4501
  };
4499
4502
 
4500
4503
  // src/lib/hyperliquidWhaleBackfill.ts
4504
+ var import_progress3 = __toESM(require("progress"));
4501
4505
  var import_timescale4 = require("@tradejs/infra/timescale");
4502
4506
  var import_strategies2 = require("@tradejs/node/strategies");
4503
4507
 
@@ -4872,11 +4876,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
4872
4876
  toMs,
4873
4877
  ...identity
4874
4878
  });
4879
+ const totalCoverageBuckets = Math.ceil(
4880
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
4881
+ );
4882
+ const coverageBar = new import_progress3.default(
4883
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
4884
+ {
4885
+ total: Math.max(1, totalCoverageBuckets),
4886
+ width: 24
4887
+ }
4888
+ );
4889
+ let displayedCoverageBuckets = 0;
4875
4890
  const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
4876
4891
  fromMs,
4877
4892
  toMs,
4878
4893
  expectedWhales: whales.addresses.length,
4879
- ...identity
4894
+ ...identity,
4895
+ onProgress: (progress) => {
4896
+ const next = Math.max(
4897
+ displayedCoverageBuckets,
4898
+ Math.min(progress.completedBuckets, coverageBar.total)
4899
+ );
4900
+ const delta = next - displayedCoverageBuckets;
4901
+ if (delta > 0) {
4902
+ coverageBar.tick(delta, {
4903
+ rows: progress.rows,
4904
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
4905
+ });
4906
+ displayedCoverageBuckets = next;
4907
+ }
4908
+ }
4880
4909
  });
4881
4910
  const result = {
4882
4911
  cached: false,
@@ -4904,6 +4933,9 @@ var backfillHyperliquidWhaleContext = async (params) => {
4904
4933
  };
4905
4934
 
4906
4935
  // src/lib/marketContextPrepare.ts
4936
+ var uniqueReasons = (reasons) => [
4937
+ ...new Set(reasons)
4938
+ ];
4907
4939
  var shouldPrepareDerivativesContextForRun = (params) => {
4908
4940
  if (params.universe === "tradfi") return false;
4909
4941
  if (params.mode === "signals") {
@@ -4911,6 +4943,9 @@ var shouldPrepareDerivativesContextForRun = (params) => {
4911
4943
  cacheOnly: params.cacheOnly
4912
4944
  });
4913
4945
  }
4946
+ if (params.mode === "backtest" && !params.aiEnabled && !params.mlEnabled) {
4947
+ return false;
4948
+ }
4914
4949
  return shouldBackfillDerivativesContextForBacktest({
4915
4950
  aiEnabled: Boolean(params.aiEnabled),
4916
4951
  cacheOnly: params.cacheOnly,
@@ -4920,6 +4955,7 @@ var shouldPrepareDerivativesContextForRun = (params) => {
4920
4955
  var shouldPrepareBinanceMarketContextForRun = (params) => {
4921
4956
  if (params.universe === "tradfi") return false;
4922
4957
  if (params.mode === "backtest") {
4958
+ if (!params.aiEnabled && !params.mlEnabled) return false;
4923
4959
  return shouldBackfillBinanceMarketContextForBacktest({
4924
4960
  aiEnabled: Boolean(params.aiEnabled),
4925
4961
  cacheOnly: params.cacheOnly,
@@ -4938,6 +4974,7 @@ var shouldPrepareBinanceMarketContextForRun = (params) => {
4938
4974
  var shouldPrepareCoinMarketCapContextForRun = (params) => {
4939
4975
  if (params.universe === "tradfi") return false;
4940
4976
  if (params.mode === "backtest") {
4977
+ if (!params.aiEnabled && !params.mlEnabled) return false;
4941
4978
  return shouldBackfillCoinMarketCapContextForBacktest({
4942
4979
  aiEnabled: Boolean(params.aiEnabled),
4943
4980
  cacheOnly: params.cacheOnly,
@@ -4953,10 +4990,8 @@ var shouldPrepareCoinMarketCapContextForRun = (params) => {
4953
4990
  cacheOnly: params.cacheOnly
4954
4991
  });
4955
4992
  };
4956
- var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
4957
- const strategyRequiresContext = params.strategyNames?.includes(
4958
- "HyperliquidConsensus"
4959
- );
4993
+ var shouldPrepareHyperliquidWhaleContextForRun = (params, coreContextSources = []) => {
4994
+ const strategyRequiresContext = coreContextSources.includes("hyperliquidWhales");
4960
4995
  if (params.universe === "tradfi" || params.mode === "signals" || params.cacheOnly || !params.aiEnabled && !params.mlEnabled && !strategyRequiresContext) {
4961
4996
  return false;
4962
4997
  }
@@ -4967,6 +5002,64 @@ var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
4967
5002
  if (strategyRequiresContext) return true;
4968
5003
  return ["1", "true", "yes", "on"].includes(configured);
4969
5004
  };
5005
+ var resolveCoreContextSources = async (params) => {
5006
+ const strategyNames = [...new Set(params.strategyNames ?? [])];
5007
+ if (!strategyNames.length) return [];
5008
+ await (0, import_registry.ensureStrategyPluginsLoaded)(params.projectRoot);
5009
+ return [
5010
+ ...new Set(
5011
+ strategyNames.flatMap(
5012
+ (strategyName) => (0, import_registry.getStrategyManifest)(strategyName, params.projectRoot)?.contextRequirements?.core ?? []
5013
+ )
5014
+ )
5015
+ ];
5016
+ };
5017
+ var resolveMarketContextRunRequirements = async (params) => {
5018
+ const coreContextSources = await resolveCoreContextSources(params);
5019
+ const paramsWithCoreDemand = (source) => coreContextSources.includes(source) ? { ...params, aiEnabled: true } : params;
5020
+ const isCrypto = params.universe !== "tradfi";
5021
+ const capturesPayload = Boolean(params.aiEnabled || params.mlEnabled);
5022
+ const runtimeReadsContext = params.mode !== "backtest";
5023
+ const reasonsFor = (source) => uniqueReasons([
5024
+ ...coreContextSources.includes(source) ? ["core"] : [],
5025
+ ...params.aiEnabled ? ["ai"] : [],
5026
+ ...params.mlEnabled ? ["ml"] : [],
5027
+ ...runtimeReadsContext ? ["runtime"] : []
5028
+ ]);
5029
+ const readsStandardContext = isCrypto && (capturesPayload || runtimeReadsContext);
5030
+ const readsHyperliquid = isCrypto && (readsStandardContext || coreContextSources.includes("hyperliquidWhales"));
5031
+ return {
5032
+ binance: {
5033
+ read: readsStandardContext || coreContextSources.includes("binance"),
5034
+ backfill: shouldPrepareBinanceMarketContextForRun(
5035
+ paramsWithCoreDemand("binance")
5036
+ ),
5037
+ requiredBy: reasonsFor("binance")
5038
+ },
5039
+ coinmarketcap: {
5040
+ read: readsStandardContext || coreContextSources.includes("coinmarketcap"),
5041
+ backfill: shouldPrepareCoinMarketCapContextForRun(
5042
+ paramsWithCoreDemand("coinmarketcap")
5043
+ ),
5044
+ requiredBy: reasonsFor("coinmarketcap")
5045
+ },
5046
+ derivatives: {
5047
+ read: readsStandardContext || coreContextSources.includes("derivatives"),
5048
+ backfill: shouldPrepareDerivativesContextForRun(
5049
+ paramsWithCoreDemand("derivatives")
5050
+ ),
5051
+ requiredBy: reasonsFor("derivatives")
5052
+ },
5053
+ hyperliquidWhales: {
5054
+ read: readsHyperliquid,
5055
+ backfill: shouldPrepareHyperliquidWhaleContextForRun(
5056
+ params,
5057
+ coreContextSources
5058
+ ),
5059
+ requiredBy: reasonsFor("hyperliquidWhales")
5060
+ }
5061
+ };
5062
+ };
4970
5063
  var resolveCoinMarketCapBackfillForMode = (mode) => mode === "backtest" ? backfillCoinMarketCapContextForBacktest : mode === "signals" ? backfillCoinMarketCapContextForSignals : backfillCoinMarketCapContextForReplay;
4971
5064
  var buildCoinMarketCapBackfillParams = (params) => ({
4972
5065
  userName: params.userName,
@@ -4995,7 +5088,15 @@ var prepareMarketContextForRun = async (params) => {
4995
5088
  console.log(import_chalk4.default.gray(message));
4996
5089
  });
4997
5090
  const timeOperation2 = (label, operation) => timeOperation(label, operation, log);
4998
- if (shouldPrepareDerivativesContextForRun(params)) {
5091
+ const requirements = await resolveMarketContextRunRequirements(params);
5092
+ const readableSources = Object.entries(requirements).filter(([, requirement]) => requirement.read).map(([source]) => source);
5093
+ if (readableSources.length) {
5094
+ await timeOperation2(
5095
+ "market context schema ensure",
5096
+ () => (0, import_timescale5.ensureMarketContextSchemas)(readableSources)
5097
+ );
5098
+ }
5099
+ if (requirements.derivatives.backfill) {
4999
5100
  await timeOperation2(
5000
5101
  "derivatives context backfill",
5001
5102
  () => (params.mode === "signals" ? backfillDerivativesContextForSignals : backfillDerivativesContextForBacktest)(
@@ -5003,7 +5104,7 @@ var prepareMarketContextForRun = async (params) => {
5003
5104
  )
5004
5105
  );
5005
5106
  }
5006
- if (shouldPrepareHyperliquidWhaleContextForRun(params)) {
5107
+ if (requirements.hyperliquidWhales.backfill) {
5007
5108
  await timeOperation2(
5008
5109
  "hyperliquid whale context backfill",
5009
5110
  () => backfillHyperliquidWhaleContext({
@@ -5015,13 +5116,13 @@ var prepareMarketContextForRun = async (params) => {
5015
5116
  })
5016
5117
  );
5017
5118
  }
5018
- if (shouldPrepareBinanceMarketContextForRun(params)) {
5119
+ if (requirements.binance.backfill) {
5019
5120
  await timeOperation2("binance market context backfill", () => {
5020
5121
  const backfill = params.mode === "backtest" ? backfillBinanceMarketContextForBacktest : params.mode === "signals" ? backfillBinanceMarketContextForSignals : backfillBinanceMarketContextForReplay;
5021
5122
  return backfill(buildBinanceMarketBackfillParams(params));
5022
5123
  });
5023
5124
  }
5024
- if (shouldPrepareCoinMarketCapContextForRun(params)) {
5125
+ if (requirements.coinmarketcap.backfill) {
5025
5126
  await timeOperation2(
5026
5127
  "coinmarketcap historical context backfill",
5027
5128
  () => resolveCoinMarketCapBackfillForMode(params.mode)(
@@ -5029,10 +5130,12 @@ var prepareMarketContextForRun = async (params) => {
5029
5130
  )
5030
5131
  );
5031
5132
  }
5133
+ return requirements;
5032
5134
  };
5033
5135
  // Annotate the CommonJS export names for ESM import in node:
5034
5136
  0 && (module.exports = {
5035
5137
  prepareMarketContextForRun,
5138
+ resolveMarketContextRunRequirements,
5036
5139
  shouldPrepareBinanceMarketContextForRun,
5037
5140
  shouldPrepareCoinMarketCapContextForRun,
5038
5141
  shouldPrepareDerivativesContextForRun,
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/lib/researchAgent.ts
@@ -39,24 +29,14 @@ __export(researchAgent_exports, {
39
29
  buildResearchAgentPrBody: () => buildResearchAgentPrBody,
40
30
  buildResearchAgentPrTitle: () => buildResearchAgentPrTitle,
41
31
  getResearchAgentAllowedPathPrefixes: () => getResearchAgentAllowedPathPrefixes,
42
- getResearchAgentNotePath: () => getResearchAgentNotePath,
43
32
  normalizeDiffOutput: () => normalizeDiffOutput,
44
33
  parseChangedFilesFromDiff: () => parseChangedFilesFromDiff,
45
- parseGithubRepositoryFromRemote: () => parseGithubRepositoryFromRemote,
46
- toUpperSnakeCase: () => toUpperSnakeCase
34
+ parseGithubRepositoryFromRemote: () => parseGithubRepositoryFromRemote
47
35
  });
48
36
  module.exports = __toCommonJS(researchAgent_exports);
49
- var import_node_path = __toESM(require("path"));
50
37
  var RESEARCH_AGENT_MODEL = "openai/gpt-5.4";
51
38
  var RESEARCH_AGENT_REASONING_EFFORT = "medium";
52
39
  var RESEARCH_AGENT_BRANCH_PREFIX = "codex/research";
53
- var toUpperSnakeCase = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
54
- var RESEARCH_NOTE_FILE_OVERRIDES = {
55
- TrendLine: "AI_TRENDLINE_REPLAY_NOTES.md",
56
- ReverseTrendLine: "AI_REVERSE_TRENDLINE_REPLAY_NOTES.md",
57
- AdaptiveMomentumRibbon: "AI_ADAPTIVE_MOMENTUM_RIBBON_REPLAY_NOTES.md",
58
- VolumeDivergence: "AI_VOLUME_DIVERGENCE_REPLAY_NOTES.md"
59
- };
60
40
  var buildResearchAgentBranchName = (strategy, runId) => {
61
41
  const normalizedStrategy = strategy.trim().replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
62
42
  const normalizedRunId = runId.trim().replace(/[^a-zA-Z0-9-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
@@ -64,13 +44,8 @@ var buildResearchAgentBranchName = (strategy, runId) => {
64
44
  };
65
45
  var buildResearchAgentCommitMessage = (strategy, runId) => `Research agent: ${strategy} follow-up for ${runId}`;
66
46
  var buildResearchAgentPrTitle = (strategy, runId) => `Research agent: ${strategy} follow-up for ${runId}`;
67
- var getResearchAgentNotePath = (strategy) => import_node_path.default.join(
68
- "notes",
69
- RESEARCH_NOTE_FILE_OVERRIDES[strategy] || `AI_${toUpperSnakeCase(strategy)}_REPLAY_NOTES.md`
70
- );
71
47
  var getResearchAgentAllowedPathPrefixes = (strategy) => [
72
- `packages/strategies/src/${strategy}/`,
73
- getResearchAgentNotePath(strategy)
48
+ `packages/strategies/src/${strategy}/`
74
49
  ];
75
50
  var parseGithubRepositoryFromRemote = (value) => {
76
51
  const trimmed = value.trim();
@@ -187,9 +162,7 @@ ${diffText}`)) {
187
162
  buildResearchAgentPrBody,
188
163
  buildResearchAgentPrTitle,
189
164
  getResearchAgentAllowedPathPrefixes,
190
- getResearchAgentNotePath,
191
165
  normalizeDiffOutput,
192
166
  parseChangedFilesFromDiff,
193
- parseGithubRepositoryFromRemote,
194
- toUpperSnakeCase
167
+ parseGithubRepositoryFromRemote
195
168
  });
@@ -25,6 +25,7 @@ __export(runtimeDebugEvidence_exports, {
25
25
  buildRuntimeDebugEvaluationId: () => buildRuntimeDebugEvaluationId,
26
26
  buildRuntimeDebugReportAttachment: () => buildRuntimeDebugReportAttachment,
27
27
  buildRuntimeDebugReportPayload: () => buildRuntimeDebugReportPayload,
28
+ buildRuntimeEvidenceReportPayload: () => buildRuntimeEvidenceReportPayload,
28
29
  collectRuntimeDebugEvidence: () => collectRuntimeDebugEvidence
29
30
  });
30
31
  module.exports = __toCommonJS(runtimeDebugEvidence_exports);
@@ -122,6 +123,29 @@ var loadRuntimeTrades = async (userName, {
122
123
  const trades = await Promise.all(keys.map((key) => (0, import_redis.getData)(key, null)));
123
124
  return trades.filter(isRuntimeTradeRecord).filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
124
125
  };
126
+ var loadRuntimeClosedTrades = async (userName, {
127
+ startTime,
128
+ endTime
129
+ }) => {
130
+ const dayKeys = (0, import_time.getRuntimeStorageDayKeys)(startTime, endTime);
131
+ const trades = (await Promise.all(
132
+ dayKeys.map(
133
+ (dayKey) => (0, import_redis.getHashJsonValues)(
134
+ import_redis.redisKeys.runtimeClosedTradeBucket(userName, dayKey)
135
+ )
136
+ )
137
+ )).flat();
138
+ const deduped = /* @__PURE__ */ new Map();
139
+ for (const trade of trades) {
140
+ if (!isRuntimeTradeRecord(trade) || trade.status !== "closed" || !Number.isFinite(trade.exitTimestamp) || trade.exitTimestamp < startTime || trade.exitTimestamp >= endTime) {
141
+ continue;
142
+ }
143
+ deduped.set(trade.orderId, trade);
144
+ }
145
+ return [...deduped.values()].sort(
146
+ (left, right) => left.exitTimestamp - right.exitTimestamp
147
+ );
148
+ };
125
149
 
126
150
  // src/lib/runtimeSignalsLoader.ts
127
151
  var import_redis2 = require("@tradejs/infra/redis");
@@ -319,13 +343,30 @@ var collectRuntimeDebugEvidence = async ({
319
343
  }) => {
320
344
  const dayKeys = (0, import_time2.getRuntimeStorageDayKeys)(startTime, endTime);
321
345
  const dayKeySet = new Set(dayKeys);
322
- const [trades, signals, evaluations, evaluationStatsBuckets, configs] = await Promise.all([
346
+ const [
347
+ entryTrades,
348
+ closedTrades,
349
+ signals,
350
+ evaluations,
351
+ evaluationStatsBuckets,
352
+ configs
353
+ ] = await Promise.all([
323
354
  loadRuntimeTrades(userName, { startTime, endTime }),
355
+ loadRuntimeClosedTrades(userName, { startTime, endTime }),
324
356
  loadRuntimeSignals(userName, { startTime, endTime }),
325
357
  loadRuntimeSignalEvaluations(userName, { startTime, endTime }),
326
358
  loadRuntimeSignalEvaluationStatsBuckets(userName),
327
359
  loadRuntimeStrategyConfigs(userName)
328
360
  ]);
361
+ const tradesByOrderId = new Map(
362
+ entryTrades.map((trade) => [trade.orderId, trade])
363
+ );
364
+ for (const trade of closedTrades) {
365
+ tradesByOrderId.set(trade.orderId, trade);
366
+ }
367
+ const trades = [...tradesByOrderId.values()].sort(
368
+ (left, right) => left.entryTimestamp - right.entryTimestamp
369
+ );
329
370
  const filteredStats = evaluationStatsBuckets.filter(
330
371
  (entry) => dayKeySet.has(entry.dayKey) && (!strategies?.length || strategies.includes(entry.strategy))
331
372
  );
@@ -502,6 +543,39 @@ var buildRuntimeDebugReportPayload = async ({
502
543
  strategyConfigs: strategyConfigs ?? []
503
544
  };
504
545
  };
546
+ var buildRuntimeEvidenceReportPayload = ({
547
+ userName,
548
+ startTime,
549
+ endTime,
550
+ signals,
551
+ evaluations,
552
+ trades,
553
+ strategyConfigs,
554
+ evaluationStatsBuckets
555
+ }) => ({
556
+ reportType: "runtime-daily-evidence",
557
+ generatedAt: Date.now(),
558
+ userName,
559
+ window: {
560
+ startTime,
561
+ endTime,
562
+ startMsk: formatRuntimeDebugDateTime(startTime),
563
+ endMsk: formatRuntimeDebugDateTime(endTime),
564
+ dayKeys: (0, import_time2.getRuntimeStorageDayKeys)(startTime, endTime)
565
+ },
566
+ counts: {
567
+ trades: trades.length,
568
+ signals: signals.length,
569
+ evaluations: evaluations.length,
570
+ evaluationStatsBuckets: evaluationStatsBuckets?.length ?? 0,
571
+ strategyConfigs: strategyConfigs?.length ?? 0
572
+ },
573
+ trades: trades.map((trade) => ({ trade })),
574
+ signals: signals.map((signal) => ({ signal })),
575
+ evaluations: evaluations.map((evaluation) => ({ evaluation })),
576
+ evaluationStatsBuckets: evaluationStatsBuckets ?? [],
577
+ strategyConfigs: strategyConfigs ?? []
578
+ });
505
579
  var buildRuntimeDebugReportAttachment = async (params) => {
506
580
  const payload = await buildRuntimeDebugReportPayload(params);
507
581
  const dayKey = formatRuntimeDebugIsoDayKey(params.endTime);
@@ -523,5 +597,6 @@ var buildRuntimeDebugReportAttachment = async (params) => {
523
597
  buildRuntimeDebugEvaluationId,
524
598
  buildRuntimeDebugReportAttachment,
525
599
  buildRuntimeDebugReportPayload,
600
+ buildRuntimeEvidenceReportPayload,
526
601
  collectRuntimeDebugEvidence
527
602
  });