@tradejs/cli 3.1.29-beta.283 → 3.1.29-beta.284

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.
@@ -597,6 +597,7 @@ var DAYS_PER_WEEK = 7;
597
597
  var DAYS_PER_MONTH = 30.4375;
598
598
  var PRODUCTION_CANDIDATE_MIN_EVENTS = 25;
599
599
  var OUTCOME_SEGMENTS = /* @__PURE__ */ new Set([
600
+ "researchentrydecision",
600
601
  "actual",
601
602
  "aiapproved",
602
603
  "approvalallowednow",
@@ -881,6 +882,8 @@ var classifyAiPocketFeaturePath = (path3) => {
881
882
  if (METADATA_LEAVES.has(leaf) || leaf.endsWith("fingerprint") || normalized.some((segment) => segment === "metadata")) {
882
883
  return "metadata";
883
884
  }
885
+ if (normalized.some((segment) => OUTCOME_SEGMENTS.has(segment)))
886
+ return "derived-policy";
884
887
  if (DERIVED_POLICY_FRAGMENTS.some(
885
888
  (fragment) => !(fragment === "gatefeature" && isStrategySetupEvidence) && normalizedPath.includes(fragment)
886
889
  )) {
@@ -33,7 +33,7 @@ __export(coreResearch_exports, {
33
33
  main: () => main
34
34
  });
35
35
  module.exports = __toCommonJS(coreResearch_exports);
36
- var import_promises5 = __toESM(require("fs/promises"));
36
+ var import_promises4 = __toESM(require("fs/promises"));
37
37
  var import_node_path7 = __toESM(require("path"));
38
38
  var import_chalk = __toESM(require("chalk"));
39
39
 
@@ -644,7 +644,7 @@ var writeCoreResearchStageIndex = async (rootDir) => {
644
644
  };
645
645
 
646
646
  // src/lib/coreResearch/orchestrator.ts
647
- var import_promises4 = __toESM(require("fs/promises"));
647
+ var import_promises3 = __toESM(require("fs/promises"));
648
648
  var import_node_path6 = __toESM(require("path"));
649
649
  var import_node_child_process = require("child_process");
650
650
  var import_node_crypto5 = require("crypto");
@@ -1010,6 +1010,8 @@ var calendarClusterBootstrap = (params) => {
1010
1010
  const alpha = 1 - params.confidenceLevel;
1011
1011
  const positive = samples.filter((value) => value > 0).length;
1012
1012
  const probabilityPositive = positive / samples.length;
1013
+ const observed = deltas.reduce((sum, value) => sum + value, 0) / deltas.length;
1014
+ const oneSidedPValue = (1 + samples.filter((value) => value - observed >= observed - 1e-12).length) / (samples.length + 1);
1013
1015
  return {
1014
1016
  method: "calendar-cluster-bootstrap",
1015
1017
  clusterDays: params.clusterDays,
@@ -1021,7 +1023,7 @@ var calendarClusterBootstrap = (params) => {
1021
1023
  percentile(samples, 1 - alpha / 2)
1022
1024
  ],
1023
1025
  probabilityPositive,
1024
- oneSidedPValue: 1 - probabilityPositive,
1026
+ oneSidedPValue,
1025
1027
  holmAdjustedPValue: null
1026
1028
  };
1027
1029
  };
@@ -1088,7 +1090,7 @@ var erf = (value) => {
1088
1090
  return sign * y;
1089
1091
  };
1090
1092
  var normalCdf = (value) => 0.5 * (1 + erf(value / Math.SQRT2));
1091
- var deflatedSharpeDiagnostic = (returns, trials) => {
1093
+ var deflatedSharpeDiagnostic = (returns, trials, trialSharpes) => {
1092
1094
  const periods = returns.length;
1093
1095
  if (periods < 3) {
1094
1096
  return {
@@ -1113,9 +1115,18 @@ var deflatedSharpeDiagnostic = (returns, trials) => {
1113
1115
  const observedSharpe = mean / standardDeviation;
1114
1116
  const skew = centered.reduce((sum, value) => sum + (value / standardDeviation) ** 3, 0) / periods;
1115
1117
  const kurtosis = centered.reduce((sum, value) => sum + (value / standardDeviation) ** 4, 0) / periods;
1116
- const expectedMaximumSharpe = inverseNormalCdf(
1117
- (Math.max(1, trials) - 0.375) / (Math.max(1, trials) + 0.25)
1118
- );
1118
+ const available = trialSharpes?.filter(Number.isFinite) ?? [];
1119
+ if (trials > 1 && available.length < 2)
1120
+ return {
1121
+ periods,
1122
+ observedSharpe,
1123
+ expectedMaximumSharpe: null,
1124
+ probabilityAboveSelectionBias: null
1125
+ };
1126
+ const trialMean = available.length ? available.reduce((sum, value) => sum + value, 0) / available.length : 0;
1127
+ const trialVariance = available.length > 1 ? available.reduce((sum, value) => sum + (value - trialMean) ** 2, 0) / (available.length - 1) : 0;
1128
+ const gamma = 0.5772156649015329;
1129
+ const expectedMaximumSharpe = trials <= 1 ? 0 : Math.sqrt(trialVariance) * ((1 - gamma) * inverseNormalCdf(1 - 1 / trials) + gamma * inverseNormalCdf(1 - 1 / (trials * Math.E)));
1119
1130
  const standardError = Math.sqrt(
1120
1131
  Math.max(
1121
1132
  1e-12,
@@ -1133,6 +1144,27 @@ var deflatedSharpeDiagnostic = (returns, trials) => {
1133
1144
  };
1134
1145
  var combinations = (items, choose) => {
1135
1146
  const output = [];
1147
+ if (items.length > 10) {
1148
+ const random = createSeededRandom(`cscv-balanced-${items.length}`);
1149
+ const seen = /* @__PURE__ */ new Set();
1150
+ for (let attempt = 0; output.length < 512 && attempt < 1e5; attempt++) {
1151
+ const shuffled = [...items];
1152
+ for (let index = shuffled.length - 1; index > 0; index--) {
1153
+ const swap = Math.floor(random() * (index + 1));
1154
+ [shuffled[index], shuffled[swap]] = [shuffled[swap], shuffled[index]];
1155
+ }
1156
+ const selected = shuffled.slice(0, choose).sort((a, b) => a - b);
1157
+ const complement = items.filter((item) => !selected.includes(item));
1158
+ for (const half of [selected, complement]) {
1159
+ const key = half.join(",");
1160
+ if (!seen.has(key)) {
1161
+ seen.add(key);
1162
+ output.push(half);
1163
+ }
1164
+ }
1165
+ }
1166
+ return output;
1167
+ }
1136
1168
  const visit = (start, selected) => {
1137
1169
  if (output.length >= 512) return;
1138
1170
  if (selected.length === choose) {
@@ -1171,14 +1203,23 @@ var probabilityOfBacktestOverfitting = (performanceByVariant) => {
1171
1203
  const inScores = performanceByVariant.map(
1172
1204
  (performance) => inSample.reduce((sum, index) => sum + performance[index], 0)
1173
1205
  );
1174
- const selected = inScores.indexOf(Math.max(...inScores));
1206
+ const maximum = Math.max(...inScores);
1207
+ const selected = inScores.flatMap(
1208
+ (score, index) => score === maximum ? [index] : []
1209
+ );
1175
1210
  const outScores = performanceByVariant.map(
1176
1211
  (performance) => outSample.reduce((sum, index) => sum + performance[index], 0)
1177
1212
  );
1178
- const sorted = [...outScores].sort((left, right) => left - right);
1179
- const rankAscending = sorted.indexOf(outScores[selected]);
1180
- const omega = (rankAscending + 1) / (outScores.length + 1);
1181
- if (Math.log(omega / (1 - omega)) < 0) belowMedian += 1;
1213
+ for (const winner of selected) {
1214
+ const less = outScores.filter(
1215
+ (score) => score < outScores[winner]
1216
+ ).length;
1217
+ const equal = outScores.filter(
1218
+ (score) => score === outScores[winner]
1219
+ ).length;
1220
+ const omega = (less + (equal + 1) / 2) / (outScores.length + 1);
1221
+ if (omega < 0.5) belowMedian += 1 / selected.length;
1222
+ }
1182
1223
  }
1183
1224
  return {
1184
1225
  method: "CSCV",
@@ -2108,34 +2149,55 @@ var applyCoreResearchRobustnessGuardrails = (params) => {
2108
2149
  };
2109
2150
 
2110
2151
  // src/lib/coreResearch/trace.ts
2111
- var import_promises3 = __toESM(require("fs/promises"));
2152
+ var import_node_fs4 = require("fs");
2153
+ var import_node_readline2 = __toESM(require("readline"));
2112
2154
  var import_node_path4 = __toESM(require("path"));
2113
2155
  var summarizeCoreResearchTrace = async (filePaths = []) => {
2114
2156
  const events = /* @__PURE__ */ Object.create(null);
2115
2157
  const skipCounts = /* @__PURE__ */ Object.create(null);
2116
2158
  const exitCodes = /* @__PURE__ */ Object.create(null);
2159
+ const policyRejections = {};
2160
+ const policyExamples = [];
2117
2161
  for (const inputPath of filePaths) {
2118
2162
  const filePath = import_node_path4.default.resolve(inputPath);
2119
- const text = await import_promises3.default.readFile(filePath, "utf8");
2120
- for (const [index, line] of text.split("\n").entries()) {
2121
- if (!line.trim()) continue;
2122
- let event;
2123
- try {
2124
- event = JSON.parse(line);
2125
- } catch (error) {
2126
- throw new Error(
2127
- `${filePath}:${index + 1} contains invalid trace JSON: ${String(error)}`
2128
- );
2129
- }
2130
- events[event.event] = (events[event.event] ?? 0) + 1;
2131
- if (event.event === "skip_summary") {
2132
- for (const [reason, count] of Object.entries(event.skipCounts)) {
2133
- skipCounts[reason] = (skipCounts[reason] ?? 0) + count;
2163
+ const input = (0, import_node_fs4.createReadStream)(filePath);
2164
+ const lines = import_node_readline2.default.createInterface({ input, crlfDelay: Infinity });
2165
+ let index = -1;
2166
+ try {
2167
+ for await (const line of lines) {
2168
+ index++;
2169
+ if (!line.trim()) continue;
2170
+ let event;
2171
+ try {
2172
+ event = JSON.parse(line);
2173
+ } catch (error) {
2174
+ throw new Error(
2175
+ `${filePath}:${index + 1} contains invalid trace JSON: ${String(error)}`
2176
+ );
2177
+ }
2178
+ events[event.event] = (events[event.event] ?? 0) + 1;
2179
+ if (event.event === "skip_summary") {
2180
+ for (const [reason, count] of Object.entries(event.skipCounts)) {
2181
+ skipCounts[reason] = (skipCounts[reason] ?? 0) + count;
2182
+ }
2183
+ }
2184
+ if (event.event === "position_exited" && event.exitCode) {
2185
+ exitCodes[event.exitCode] = (exitCodes[event.exitCode] ?? 0) + 1;
2186
+ }
2187
+ if ("researchEntryDecision" in event && event.researchEntryDecision && !event.researchEntryDecision.allowed) {
2188
+ const reason = event.researchEntryDecision.reason;
2189
+ policyRejections[reason] = (policyRejections[reason] ?? 0) + 1;
2190
+ if (policyExamples.length < 20)
2191
+ policyExamples.push({
2192
+ timestamp: event.timestamp,
2193
+ symbol: event.symbol,
2194
+ decision: event.researchEntryDecision
2195
+ });
2134
2196
  }
2135
2197
  }
2136
- if (event.event === "position_exited" && event.exitCode) {
2137
- exitCodes[event.exitCode] = (exitCodes[event.exitCode] ?? 0) + 1;
2138
- }
2198
+ } finally {
2199
+ lines.close();
2200
+ input.destroy();
2139
2201
  }
2140
2202
  }
2141
2203
  return {
@@ -2149,7 +2211,13 @@ var summarizeCoreResearchTrace = async (filePaths = []) => {
2149
2211
  Object.entries(exitCodes).sort(
2150
2212
  ([leftKey, leftValue], [rightKey, rightValue]) => rightValue - leftValue || (leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0)
2151
2213
  )
2152
- )
2214
+ ),
2215
+ ...policyExamples.length ? {
2216
+ researchPolicy: {
2217
+ rejections: policyRejections,
2218
+ examples: policyExamples
2219
+ }
2220
+ } : {}
2153
2221
  };
2154
2222
  };
2155
2223
 
@@ -2436,7 +2504,14 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
2436
2504
  analysis.variant.id,
2437
2505
  deflatedSharpeDiagnostic(
2438
2506
  analysis.monthly.map((window) => window.cohorts.ALL.pnl),
2439
- Math.max(comparisons.length, familyHypotheses)
2507
+ Math.max(comparisons.length, familyHypotheses),
2508
+ analyses.flatMap((entry) => {
2509
+ const diagnostic = deflatedSharpeDiagnostic(
2510
+ entry.monthly.map((window) => window.cohorts.ALL.pnl),
2511
+ 1
2512
+ );
2513
+ return diagnostic.observedSharpe == null ? [] : [diagnostic.observedSharpe];
2514
+ })
2440
2515
  )
2441
2516
  ])
2442
2517
  ),
@@ -2461,7 +2536,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
2461
2536
  const tradesByVariant = new Map(
2462
2537
  windowed.map((entry) => [entry.variant.id, entry.trades])
2463
2538
  );
2464
- await import_promises4.default.writeFile(
2539
+ await import_promises3.default.writeFile(
2465
2540
  paths.reportPath,
2466
2541
  buildCoreResearchHtml({ spec, result, tradesByVariant }),
2467
2542
  "utf8"
@@ -2481,7 +2556,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
2481
2556
  if (error.code !== "ENOENT") throw error;
2482
2557
  }
2483
2558
  try {
2484
- for (const name of await import_promises4.default.readdir(paths.runLogDir)) {
2559
+ for (const name of await import_promises3.default.readdir(paths.runLogDir)) {
2485
2560
  if (!name.endsWith(".log")) continue;
2486
2561
  artifactHashes[`runs/${name}`] = await sha256File(
2487
2562
  import_node_path6.default.join(paths.runLogDir, name)
@@ -2681,7 +2756,7 @@ var createCoreResearchSpecTemplate = (params) => {
2681
2756
  };
2682
2757
  var runCommand = async (params) => {
2683
2758
  if (!params.command.length) throw new Error("Cannot run an empty command");
2684
- await import_promises4.default.mkdir(import_node_path6.default.dirname(params.logPath), { recursive: true });
2759
+ await import_promises3.default.mkdir(import_node_path6.default.dirname(params.logPath), { recursive: true });
2685
2760
  const chunks = [];
2686
2761
  const child = (0, import_node_child_process.spawn)(params.command[0], params.command.slice(1), {
2687
2762
  cwd: params.cwd,
@@ -2701,7 +2776,7 @@ var runCommand = async (params) => {
2701
2776
  child.once("close", (code) => resolve(code ?? 1));
2702
2777
  });
2703
2778
  const output = chunks.join("");
2704
- await import_promises4.default.writeFile(params.logPath, output, "utf8");
2779
+ await import_promises3.default.writeFile(params.logPath, output, "utf8");
2705
2780
  if (exitCode !== 0) {
2706
2781
  throw new Error(
2707
2782
  `Command failed with exit ${exitCode}: ${params.command.join(" ")}`
@@ -2919,7 +2994,7 @@ var readSymbols = async (argv, projectRoot) => {
2919
2994
  const symbolsFile = valueAfter(argv, "--symbolsFile");
2920
2995
  if (symbolsFile) {
2921
2996
  const parsed = JSON.parse(
2922
- await import_promises5.default.readFile(import_node_path7.default.resolve(projectRoot, symbolsFile), "utf8")
2997
+ await import_promises4.default.readFile(import_node_path7.default.resolve(projectRoot, symbolsFile), "utf8")
2923
2998
  );
2924
2999
  if (!Array.isArray(parsed) || parsed.some((symbol) => typeof symbol !== "string")) {
2925
3000
  throw new Error("--symbolsFile must contain a JSON string array");
@@ -137,14 +137,27 @@ var main = async (options = {}) => {
137
137
  let manifestHash = "";
138
138
  let replayReady = false;
139
139
  let replayReadiness = "unknown";
140
+ let replayResources;
140
141
  const updateReplayReady = async () => {
142
+ replayResources = void 0;
141
143
  try {
142
144
  const root = process.env.MCP_REPLAY_REQUEST_ROOT || `${process.env.PROJECT_CWD || process.cwd()}/data/mcp-replay-requests`;
143
145
  const heartbeat2 = JSON.parse(
144
146
  await (0, import_promises2.readFile)(`${root}/heartbeat.json`, "utf8")
145
147
  );
146
- replayReadiness = heartbeat2.readiness === "ready" || heartbeat2.readiness === "waiting_resources" ? heartbeat2.readiness : "unknown";
147
148
  replayReady = heartbeat2.protocolVersion === 2 && Number.isFinite(heartbeat2.observedAt) && Date.now() - heartbeat2.observedAt >= 0 && Date.now() - heartbeat2.observedAt < 12e4;
149
+ replayReadiness = replayReady && (heartbeat2.readiness === "ready" || heartbeat2.readiness === "waiting_resources") ? heartbeat2.readiness : "unknown";
150
+ if (replayReady && Number.isSafeInteger(heartbeat2.memoryAvailableKb) && heartbeat2.memoryAvailableKb >= 0 && Number.isSafeInteger(heartbeat2.minimumAvailableKb) && heartbeat2.minimumAvailableKb > 0) {
151
+ replayResources = {
152
+ observedAt: heartbeat2.observedAt,
153
+ memoryAvailableKb: heartbeat2.memoryAvailableKb,
154
+ minimumAvailableKb: heartbeat2.minimumAvailableKb,
155
+ memoryDeficitKb: Math.max(
156
+ 0,
157
+ heartbeat2.minimumAvailableKb - heartbeat2.memoryAvailableKb
158
+ )
159
+ };
160
+ }
148
161
  } catch {
149
162
  replayReadiness = "unknown";
150
163
  replayReady = false;
@@ -164,7 +177,8 @@ var main = async (options = {}) => {
164
177
  observedAt: Date.now(),
165
178
  packageManifestSha256: manifestHash,
166
179
  replayAvailable: replayReady,
167
- replayReadiness
180
+ replayReadiness,
181
+ replayResources
168
182
  });
169
183
  const stop = () => {
170
184
  stopping = true;