@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 CHANGED
@@ -3086,10 +3086,10 @@ var init_io = __esm({
3086
3086
  sha256Text = (value) => (0, import_node_crypto4.createHash)("sha256").update(value).digest("hex");
3087
3087
  sha256Json = (value) => sha256Text(canonicalJson(value));
3088
3088
  sha256File = async (filePath) => {
3089
- const hash3 = (0, import_node_crypto4.createHash)("sha256");
3089
+ const hash2 = (0, import_node_crypto4.createHash)("sha256");
3090
3090
  const input = (0, import_node_fs2.createReadStream)(filePath);
3091
- for await (const chunk of input) hash3.update(chunk);
3092
- return hash3.digest("hex");
3091
+ for await (const chunk of input) hash2.update(chunk);
3092
+ return hash2.digest("hex");
3093
3093
  };
3094
3094
  assertFinite = (value, name) => {
3095
3095
  assert(typeof value === "number" && Number.isFinite(value), name);
@@ -5436,15 +5436,15 @@ var init_searchEngine = __esm({
5436
5436
  };
5437
5437
  };
5438
5438
  hashMask = (mask) => {
5439
- let hash3 = 2166136261;
5439
+ let hash2 = 2166136261;
5440
5440
  for (let index = 0; index < mask.length; index += 1) {
5441
5441
  if (mask[index] !== 1) {
5442
5442
  continue;
5443
5443
  }
5444
- hash3 ^= index + 1;
5445
- hash3 = Math.imul(hash3, 16777619);
5444
+ hash2 ^= index + 1;
5445
+ hash2 = Math.imul(hash2, 16777619);
5446
5446
  }
5447
- return (hash3 >>> 0).toString(36);
5447
+ return (hash2 >>> 0).toString(36);
5448
5448
  };
5449
5449
  isBetterRepresentativePocket = (candidate, existing, compare2) => candidate.depth < existing.depth || candidate.depth === existing.depth && candidate.condition.length < existing.condition.length || candidate.depth === existing.depth && candidate.condition.length === existing.condition.length && compare2(candidate, existing) < 0;
5450
5450
  estimateCombinationCount = (poolSize, maxDepth, maxCombinations) => {
@@ -9483,18 +9483,18 @@ var init_strategyGateFingerprint = __esm({
9483
9483
  const sourceEntries = candidates.filter(
9484
9484
  (entry) => entry != null
9485
9485
  );
9486
- const hash3 = (0, import_node_crypto5.createHash)("sha256");
9487
- hash3.update(strategyName);
9486
+ const hash2 = (0, import_node_crypto5.createHash)("sha256");
9487
+ hash2.update(strategyName);
9488
9488
  if (sourceEntries.length) {
9489
9489
  for (const entry of sourceEntries) {
9490
- hash3.update(entry.specifier);
9491
- hash3.update(entry.content);
9490
+ hash2.update(entry.specifier);
9491
+ hash2.update(entry.content);
9492
9492
  }
9493
9493
  } else {
9494
- hash3.update(gitSha ?? "unknown-git-sha");
9494
+ hash2.update(gitSha ?? "unknown-git-sha");
9495
9495
  }
9496
9496
  return {
9497
- gateFingerprint: hash3.digest("hex").slice(0, 16),
9497
+ gateFingerprint: hash2.digest("hex").slice(0, 16),
9498
9498
  gateFingerprintFiles: sourceEntries.map((entry) => entry.specifier)
9499
9499
  };
9500
9500
  };
@@ -11907,13 +11907,12 @@ var init_binanceMarketContextBackfill = __esm({
11907
11907
  };
11908
11908
  intervalToMarketFeatureInterval = (interval4) => {
11909
11909
  const normalized = String(interval4).trim().toLowerCase();
11910
- if (normalized === "1" || normalized === "1m") return "1m";
11910
+ if (normalized === "1" || normalized === "1m") return null;
11911
11911
  if (normalized === "5" || normalized === "5m") return "5m";
11912
11912
  if (normalized === "60" || normalized === "1h") return "1h";
11913
11913
  return "15m";
11914
11914
  };
11915
11915
  marketIntervalToConnectorInterval = (interval4) => {
11916
- if (interval4 === "1m") return "1";
11917
11916
  if (interval4 === "5m") return "5";
11918
11917
  if (interval4 === "1h") return "60";
11919
11918
  return "15";
@@ -12078,6 +12077,7 @@ var init_binanceMarketContextBackfill = __esm({
12078
12077
  return skippedBackfillResult();
12079
12078
  }
12080
12079
  const interval4 = intervalToMarketFeatureInterval(params.interval);
12080
+ if (interval4 === null) return skippedBackfillResult();
12081
12081
  const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval4];
12082
12082
  const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
12083
12083
  if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
@@ -13670,7 +13670,7 @@ var init_coinMarketCapContextBackfill = __esm({
13670
13670
  };
13671
13671
  fetchCoinMarketCapIndexRows = async (params) => {
13672
13672
  const rows = [];
13673
- const maxChunkDays = 9;
13673
+ const maxChunkDays = 4;
13674
13674
  const totalChunks = Math.max(
13675
13675
  1,
13676
13676
  Math.ceil(
@@ -16343,7 +16343,9 @@ var init_workerPool = __esm({
16343
16343
  chunkTestSuite,
16344
16344
  getProgressSnapshot,
16345
16345
  initialCompletedTests = 0,
16346
- totalTests
16346
+ totalTests,
16347
+ onProgress,
16348
+ onIncomplete
16347
16349
  }) => {
16348
16350
  const chunks = chunkTestSuite(testSuite);
16349
16351
  const fastAiWorkerPgPoolMax = resolveFastAiWorkerPgPoolMax(
@@ -16359,7 +16361,9 @@ var init_workerPool = __esm({
16359
16361
  );
16360
16362
  let completedTests = initialCompletedTests;
16361
16363
  let renderedTests = 0;
16364
+ let pendingResults = 0;
16362
16365
  let isFinishing = false;
16366
+ let isInterrupted = false;
16363
16367
  let signalHandlersRemoved = false;
16364
16368
  const workers = /* @__PURE__ */ new Set();
16365
16369
  const stopWorkers = () => {
@@ -16370,6 +16374,7 @@ var init_workerPool = __esm({
16370
16374
  }
16371
16375
  };
16372
16376
  const handleInterrupt = (signal, exitCode) => {
16377
+ isInterrupted = true;
16373
16378
  stopWorkers();
16374
16379
  void Promise.resolve(onInterrupt?.(signal)).catch((error) => {
16375
16380
  console.error(
@@ -16390,15 +16395,16 @@ var init_workerPool = __esm({
16390
16395
  process.removeListener("SIGTERM", handleSigterm);
16391
16396
  };
16392
16397
  const maybeFinish = async () => {
16393
- if (isFinishing) {
16394
- return;
16395
- }
16396
- if (completedTests !== totalExpectedTests || workers.size > 0) {
16398
+ if (isFinishing || isInterrupted || workers.size > 0 || pendingResults > 0) {
16397
16399
  return;
16398
16400
  }
16399
16401
  isFinishing = true;
16400
16402
  try {
16401
- await onFinish();
16403
+ if (completedTests === totalExpectedTests) {
16404
+ await onFinish();
16405
+ } else {
16406
+ await onIncomplete?.();
16407
+ }
16402
16408
  } finally {
16403
16409
  cleanupSignalHandlers();
16404
16410
  }
@@ -16457,14 +16463,22 @@ var init_workerPool = __esm({
16457
16463
  return;
16458
16464
  }
16459
16465
  completedTests++;
16460
- await onMessage(msg);
16461
- if (completedTests % progressStep2 === 0 || completedTests === totalExpectedTests) {
16462
- tickProgress();
16466
+ onProgress?.(completedTests);
16467
+ pendingResults++;
16468
+ try {
16469
+ await onMessage(msg);
16470
+ if (completedTests % progressStep2 === 0 || completedTests === totalExpectedTests) {
16471
+ tickProgress();
16472
+ }
16473
+ } finally {
16474
+ pendingResults--;
16463
16475
  }
16476
+ await maybeFinish();
16464
16477
  });
16465
16478
  tester.on("error", (err) => {
16466
16479
  workers.delete(tester);
16467
16480
  onWorkerError(err?.message ?? String(err));
16481
+ void maybeFinish();
16468
16482
  });
16469
16483
  tester.on("exit", (code) => {
16470
16484
  workers.delete(tester);
@@ -16876,7 +16890,9 @@ var init_runnerCore = __esm({
16876
16890
  onFinish,
16877
16891
  initialCompletedTests = 0,
16878
16892
  totalTests,
16879
- backtestRunId
16893
+ backtestRunId,
16894
+ onProgress,
16895
+ onIncomplete
16880
16896
  }) => {
16881
16897
  markTestsStarted();
16882
16898
  const { testerWorkerPath, testerNeedsTsRuntime } = resolveTesterWorker();
@@ -16900,6 +16916,8 @@ var init_runnerCore = __esm({
16900
16916
  chunkTestSuite: (suite) => chunkTestSuiteBySymbol(suite, effectiveParallel),
16901
16917
  initialCompletedTests,
16902
16918
  totalTests,
16919
+ onProgress,
16920
+ onIncomplete,
16903
16921
  onInterrupt,
16904
16922
  onMessage: async (msg) => {
16905
16923
  if (msg.error) {
@@ -16955,10 +16973,116 @@ var init_runnerCore = __esm({
16955
16973
  }
16956
16974
  });
16957
16975
 
16976
+ // src/lib/backtest/observeRun.ts
16977
+ var import_constants9, import_redis7, import_logger, HEARTBEAT_MS, ACTIVE_TTL_SECONDS, LINKED_RUN_TTL_SECONDS, RESEARCH_STUDY, MAX_VALUES_PER_PARAMETER, MAX_VALUE_LENGTH, summarizeBacktestParameters, observeBacktestRun;
16978
+ var init_observeRun = __esm({
16979
+ "src/lib/backtest/observeRun.ts"() {
16980
+ "use strict";
16981
+ import_constants9 = require("@tradejs/core/constants");
16982
+ import_redis7 = require("@tradejs/infra/redis");
16983
+ import_logger = require("@tradejs/infra/logger");
16984
+ HEARTBEAT_MS = 2e3;
16985
+ ACTIVE_TTL_SECONDS = 30;
16986
+ LINKED_RUN_TTL_SECONDS = 30 * 24 * import_constants9.TTL_1H;
16987
+ RESEARCH_STUDY = /^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}\/\d{4}-\d{2}-\d{2}-[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/;
16988
+ MAX_VALUES_PER_PARAMETER = 12;
16989
+ MAX_VALUE_LENGTH = 500;
16990
+ summarizeBacktestParameters = (tests) => {
16991
+ const parameters = /* @__PURE__ */ new Map();
16992
+ for (const test of tests) {
16993
+ for (const [name, value] of Object.entries(test.strategyConfig)) {
16994
+ const serialized = JSON.stringify(value);
16995
+ if (serialized === void 0) continue;
16996
+ const parameter = parameters.get(name) ?? {
16997
+ values: /* @__PURE__ */ new Set(),
16998
+ truncated: false
16999
+ };
17000
+ parameters.set(name, parameter);
17001
+ if (parameter.values.has(serialized)) continue;
17002
+ if (parameter.values.size === MAX_VALUES_PER_PARAMETER || serialized.length > MAX_VALUE_LENGTH) {
17003
+ parameter.truncated = true;
17004
+ } else {
17005
+ parameter.values.add(serialized);
17006
+ }
17007
+ }
17008
+ }
17009
+ return [...parameters].map(([name, { values, truncated }]) => ({
17010
+ name,
17011
+ values: [...values],
17012
+ truncated
17013
+ }));
17014
+ };
17015
+ observeBacktestRun = async (manifest, initialCompleted, parallel) => {
17016
+ if (process.env.TRADEJS_BACKTEST_WEB_JOB === "1") return;
17017
+ const researchStudy = process.env.TRADEJS_RESEARCH_STUDY?.trim();
17018
+ const linkedStudy = researchStudy && RESEARCH_STUDY.test(researchStudy) ? researchStudy : void 0;
17019
+ if (researchStudy && !linkedStudy) {
17020
+ import_logger.logger.warn(
17021
+ "invalid TRADEJS_RESEARCH_STUDY; expected Strategy/YYYY-MM-DD-slug"
17022
+ );
17023
+ }
17024
+ const { testSuite } = manifest;
17025
+ const firstTest = testSuite[0];
17026
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
17027
+ const run = {
17028
+ id: manifest.runId,
17029
+ ...linkedStudy && { researchStudy: linkedStudy },
17030
+ userName: manifest.userName,
17031
+ strategyName: firstTest.strategyName,
17032
+ configId: manifest.config,
17033
+ connector: manifest.connectorName,
17034
+ interval: manifest.interval,
17035
+ startTime: manifest.window.start,
17036
+ endTime: manifest.window.end,
17037
+ symbols: [...new Set(testSuite.map((test) => test.symbol))],
17038
+ settings: {
17039
+ ...manifest.flags,
17040
+ parallel,
17041
+ ...firstTest.executionCosts && {
17042
+ executionCosts: JSON.stringify(firstTest.executionCosts)
17043
+ }
17044
+ },
17045
+ parameters: summarizeBacktestParameters(testSuite),
17046
+ status: "running",
17047
+ completed: initialCompleted,
17048
+ total: testSuite.length,
17049
+ startedAt,
17050
+ updatedAt: startedAt
17051
+ };
17052
+ const save = async (expire) => {
17053
+ run.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
17054
+ try {
17055
+ await import_redis7.cliBacktestRunStorage.put(run, expire);
17056
+ } catch (error) {
17057
+ import_logger.logger.warn("failed to publish CLI backtest progress: %s", String(error));
17058
+ }
17059
+ };
17060
+ await save(ACTIVE_TTL_SECONDS);
17061
+ let pending;
17062
+ const timer = setInterval(() => {
17063
+ pending ??= save(ACTIVE_TTL_SECONDS).finally(() => {
17064
+ pending = void 0;
17065
+ });
17066
+ }, HEARTBEAT_MS).unref();
17067
+ return {
17068
+ progress: (completed) => {
17069
+ run.completed = completed;
17070
+ },
17071
+ finish: async (status) => {
17072
+ clearInterval(timer);
17073
+ await pending;
17074
+ run.status = status;
17075
+ await save(linkedStudy ? LINKED_RUN_TTL_SECONDS : import_constants9.TTL_1H);
17076
+ }
17077
+ };
17078
+ };
17079
+ }
17080
+ });
17081
+
16958
17082
  // src/scripts/backtest.ts
16959
17083
  var backtest_exports = {};
16960
17084
  __export(backtest_exports, {
16961
- BACKTEST_PRELOAD_DAYS: () => import_constants9.BACKTEST_PRELOAD_DAYS,
17085
+ BACKTEST_PRELOAD_DAYS: () => import_constants10.BACKTEST_PRELOAD_DAYS,
16962
17086
  backtest: () => backtest,
16963
17087
  chunkTestSuiteBySymbol: () => chunkTestSuiteBySymbol,
16964
17088
  interval: () => interval,
@@ -16983,7 +17107,7 @@ __export(backtest_exports, {
16983
17107
  toStrategyConfigGrid: () => toStrategyConfigGrid,
16984
17108
  userName: () => userName
16985
17109
  });
16986
- var import_fs2, import_path6, import_chalk15, import_backtest4, import_grid, import_data, import_redis7, import_constants9, toPersistedBacktestResultEntry, toPersistedBacktestResultEntries, resolveRenderableStat, toFiniteNumber2, toReportRow, collectReportRows, escapeMdCell, formatMoney, formatPercent2, formatRatio4, createMarkdownTable, renderReportRowsTable, safeFileToken, isStrategyConfigGrid, loadBacktestConfig, hasSingleSymbol, writeBacktestMarkdownReport, finishBacktest, restoreCompletedBacktestResults, loadBacktestRunForContinue, prepareContinuedBacktestMarketContext, backtest, main8;
17110
+ var import_fs2, import_path6, import_chalk15, import_backtest4, import_grid, import_data, import_redis8, import_constants10, toPersistedBacktestResultEntry, toPersistedBacktestResultEntries, resolveRenderableStat, toFiniteNumber2, toReportRow, collectReportRows, escapeMdCell, formatMoney, formatPercent2, formatRatio4, createMarkdownTable, renderReportRowsTable, safeFileToken, isStrategyConfigGrid, loadBacktestConfig, hasSingleSymbol, writeBacktestMarkdownReport, finishBacktest, restoreCompletedBacktestResults, loadBacktestRunForContinue, prepareContinuedBacktestMarketContext, runBacktestSuite, backtest, main8;
16987
17111
  var init_backtest = __esm({
16988
17112
  "src/scripts/backtest.ts"() {
16989
17113
  "use strict";
@@ -16993,12 +17117,13 @@ var init_backtest = __esm({
16993
17117
  import_backtest4 = require("@tradejs/core/backtest");
16994
17118
  import_grid = require("@tradejs/core/grid");
16995
17119
  import_data = require("@tradejs/core/data");
16996
- import_redis7 = require("@tradejs/infra/redis");
16997
- import_constants9 = require("@tradejs/core/constants");
17120
+ import_redis8 = require("@tradejs/infra/redis");
17121
+ import_constants10 = require("@tradejs/core/constants");
16998
17122
  init_runnerCore();
16999
17123
  init_cliConfig();
17000
17124
  init_runState();
17001
17125
  init_checkpoint();
17126
+ init_observeRun();
17002
17127
  init_marketContextPrepare();
17003
17128
  if (process.argv.some(
17004
17129
  (arg) => arg === "--live" || String(arg).startsWith("--live=")
@@ -17134,8 +17259,8 @@ var init_backtest = __esm({
17134
17259
  if (!strategyName) {
17135
17260
  throw new Error("Strategy name not found");
17136
17261
  }
17137
- const backtestConfig = await (0, import_redis7.getData)(
17138
- import_redis7.redisKeys.backtestConfig(userName, flags5.config),
17262
+ const backtestConfig = await (0, import_redis8.getData)(
17263
+ import_redis8.redisKeys.backtestConfig(userName, flags5.config),
17139
17264
  null
17140
17265
  );
17141
17266
  if (!backtestConfig) {
@@ -17282,8 +17407,8 @@ var init_backtest = __esm({
17282
17407
  console.log(import_chalk15.default.gray(`full report: ${markdownReportPath}`));
17283
17408
  console.log("");
17284
17409
  if (!isFastMode || flags5.persistResults) {
17285
- await (0, import_redis7.setData)(
17286
- import_redis7.redisKeys.backtestResults(userName, flags5.config, timestamp),
17410
+ await (0, import_redis8.setData)(
17411
+ import_redis8.redisKeys.backtestResults(userName, flags5.config, timestamp),
17287
17412
  {
17288
17413
  config: flags5.config,
17289
17414
  mode: "config",
@@ -17303,11 +17428,10 @@ var init_backtest = __esm({
17303
17428
  errorTests: errorTests2
17304
17429
  },
17305
17430
  {
17306
- expire: import_constants9.TTL_1M
17431
+ expire: import_constants10.TTL_1M
17307
17432
  }
17308
17433
  );
17309
17434
  }
17310
- process.exit();
17311
17435
  };
17312
17436
  restoreCompletedBacktestResults = (completed) => {
17313
17437
  for (const { result } of completed) {
@@ -17388,6 +17512,56 @@ var init_backtest = __esm({
17388
17512
  log: (message) => console.log(import_chalk15.default.gray(message))
17389
17513
  });
17390
17514
  };
17515
+ runBacktestSuite = async (manifest, testSuite, initialCompletedTests = 0) => {
17516
+ const observation = await observeBacktestRun(
17517
+ manifest,
17518
+ initialCompletedTests,
17519
+ effectiveParallel
17520
+ );
17521
+ try {
17522
+ await executeTestSuite({
17523
+ testSuite,
17524
+ window: manifest.window,
17525
+ preloadStart: manifest.preloadStart,
17526
+ backtestRunId: manifest.runId,
17527
+ initialCompletedTests,
17528
+ totalTests: manifest.testSuite.length,
17529
+ onProgress: observation?.progress,
17530
+ onIncomplete: async () => {
17531
+ await observation?.finish("failed");
17532
+ await markBacktestRunStatus({ run: manifest, status: "interrupted" });
17533
+ process.exit(1);
17534
+ },
17535
+ onResult: async (result) => {
17536
+ await saveBacktestCheckpointResult({
17537
+ result,
17538
+ runId: manifest.runId,
17539
+ userName
17540
+ });
17541
+ trackTopResult(result);
17542
+ updateBestTickerResult(result);
17543
+ },
17544
+ onInterrupt: async () => {
17545
+ await observation?.finish("cancelled");
17546
+ await markBacktestRunStatus({ run: manifest, status: "interrupted" });
17547
+ },
17548
+ onFinish: async () => {
17549
+ try {
17550
+ await markBacktestRunStatus({ run: manifest, status: "completed" });
17551
+ await finishBacktest(manifest.testSuite);
17552
+ await observation?.finish("completed");
17553
+ process.exit();
17554
+ } catch (error) {
17555
+ await observation?.finish("failed");
17556
+ throw error;
17557
+ }
17558
+ }
17559
+ });
17560
+ } catch (error) {
17561
+ await observation?.finish("failed");
17562
+ throw error;
17563
+ }
17564
+ };
17391
17565
  backtest = async () => {
17392
17566
  resetRunState();
17393
17567
  const config2 = await loadBacktestConfig();
@@ -17402,33 +17576,10 @@ var init_backtest = __esm({
17402
17576
  if (!remainingSuite.length) {
17403
17577
  await markBacktestRunStatus({ run: manifest2, status: "completed" });
17404
17578
  await finishBacktest(manifest2.testSuite);
17405
- return;
17579
+ process.exit();
17406
17580
  }
17407
17581
  await prepareContinuedBacktestMarketContext({ manifest: manifest2, remainingSuite });
17408
- await executeTestSuite({
17409
- testSuite: remainingSuite,
17410
- window: manifest2.window,
17411
- preloadStart: manifest2.preloadStart,
17412
- backtestRunId: manifest2.runId,
17413
- initialCompletedTests: completed.length,
17414
- totalTests: manifest2.testSuite.length,
17415
- onResult: async (result) => {
17416
- await saveBacktestCheckpointResult({
17417
- result,
17418
- runId: manifest2.runId,
17419
- userName
17420
- });
17421
- trackTopResult(result);
17422
- updateBestTickerResult(result);
17423
- },
17424
- onInterrupt: async () => {
17425
- await markBacktestRunStatus({ run: manifest2, status: "interrupted" });
17426
- },
17427
- onFinish: async () => {
17428
- await markBacktestRunStatus({ run: manifest2, status: "completed" });
17429
- await finishBacktest(manifest2.testSuite);
17430
- }
17431
- });
17582
+ await runBacktestSuite(manifest2, remainingSuite, completed.length);
17432
17583
  return;
17433
17584
  }
17434
17585
  const preparedRun = await prepareRunEnvironment2(config2.strategyName);
@@ -17489,28 +17640,7 @@ var init_backtest = __esm({
17489
17640
  testSuite
17490
17641
  });
17491
17642
  console.log(import_chalk15.default.gray(`backtest run id: ${manifest.runId}`));
17492
- await executeTestSuite({
17493
- testSuite,
17494
- window: preparedRun.window,
17495
- preloadStart: preparedRun.preloadStart,
17496
- backtestRunId: manifest.runId,
17497
- onResult: async (result) => {
17498
- await saveBacktestCheckpointResult({
17499
- result,
17500
- runId: manifest.runId,
17501
- userName
17502
- });
17503
- trackTopResult(result);
17504
- updateBestTickerResult(result);
17505
- },
17506
- onInterrupt: async () => {
17507
- await markBacktestRunStatus({ run: manifest, status: "interrupted" });
17508
- },
17509
- onFinish: async () => {
17510
- await markBacktestRunStatus({ run: manifest, status: "completed" });
17511
- await finishBacktest(testSuite);
17512
- }
17513
- });
17643
+ await runBacktestSuite(manifest, testSuite);
17514
17644
  };
17515
17645
  main8 = backtest;
17516
17646
  }
@@ -18461,11 +18591,11 @@ var init_memoryProfile = __esm({
18461
18591
  });
18462
18592
 
18463
18593
  // src/lib/replay/portfolioReplayConnector.ts
18464
- var import_constants10, import_math, import_trade, UNKNOWN_STRATEGY, getStrategyName, getPositionPnlSnapshot, createPortfolioReplayConnector;
18594
+ var import_constants11, import_math, import_trade, UNKNOWN_STRATEGY, getStrategyName, getPositionPnlSnapshot, createPortfolioReplayConnector;
18465
18595
  var init_portfolioReplayConnector = __esm({
18466
18596
  "src/lib/replay/portfolioReplayConnector.ts"() {
18467
18597
  "use strict";
18468
- import_constants10 = require("@tradejs/core/constants");
18598
+ import_constants11 = require("@tradejs/core/constants");
18469
18599
  import_math = require("@tradejs/core/math");
18470
18600
  import_trade = require("@tradejs/core/trade");
18471
18601
  init_support2();
@@ -18493,7 +18623,7 @@ var init_portfolioReplayConnector = __esm({
18493
18623
  };
18494
18624
  createPortfolioReplayConnector = (connector, observeEquity = false) => {
18495
18625
  let state = {};
18496
- let amount = import_constants10.INITIAL_BACKTEST_AMOUNT;
18626
+ let amount = import_constants11.INITIAL_BACKTEST_AMOUNT;
18497
18627
  let executionTimestamp = null;
18498
18628
  const positionsBySymbol = /* @__PURE__ */ new Map();
18499
18629
  const currentPriceBySymbol = /* @__PURE__ */ new Map();
@@ -18559,7 +18689,7 @@ var init_portfolioReplayConnector = __esm({
18559
18689
  price,
18560
18690
  qty
18561
18691
  }) => {
18562
- const fee = price * qty * import_constants10.FEE_PERCENT;
18692
+ const fee = price * qty * import_constants11.FEE_PERCENT;
18563
18693
  return {
18564
18694
  fee,
18565
18695
  profit: grossProfit - fee
@@ -18926,7 +19056,7 @@ var init_portfolioReplayConnector = __esm({
18926
19056
  },
18927
19057
  getMarkedEquity: () => {
18928
19058
  if (!equityMarks) return null;
18929
- let equity = amount - import_constants10.INITIAL_BACKTEST_AMOUNT;
19059
+ let equity = amount - import_constants11.INITIAL_BACKTEST_AMOUNT;
18930
19060
  for (const { position } of positionsBySymbol.values()) {
18931
19061
  const mark = equityMarks.get(position.symbol);
18932
19062
  if (mark == null || !Number.isFinite(mark)) return null;
@@ -19328,12 +19458,12 @@ var init_historicalSignalsReplayExecution = __esm({
19328
19458
  });
19329
19459
 
19330
19460
  // src/lib/replay/historicalSignalsReplayResults.ts
19331
- var import_backtest5, import_constants11, emptyStat, positionLogForStats, calculateReplayStat, byTimestamp, byPositionClose, collectHistoricalReplayResult, compactHistoricalReplayResultForPortfolio, mergeHistoricalReplayResults;
19461
+ var import_backtest5, import_constants12, emptyStat, positionLogForStats, calculateReplayStat, byTimestamp, byPositionClose, collectHistoricalReplayResult, compactHistoricalReplayResultForPortfolio, mergeHistoricalReplayResults;
19332
19462
  var init_historicalSignalsReplayResults = __esm({
19333
19463
  "src/lib/replay/historicalSignalsReplayResults.ts"() {
19334
19464
  "use strict";
19335
19465
  import_backtest5 = require("@tradejs/core/backtest");
19336
- import_constants11 = require("@tradejs/core/constants");
19466
+ import_constants12 = require("@tradejs/core/constants");
19337
19467
  emptyStat = () => ({
19338
19468
  orders: 0,
19339
19469
  wins: 0,
@@ -19342,7 +19472,7 @@ var init_historicalSignalsReplayResults = __esm({
19342
19472
  amount: 0
19343
19473
  });
19344
19474
  positionLogForStats = (positionLog) => {
19345
- let amount = import_constants11.INITIAL_BACKTEST_AMOUNT;
19475
+ let amount = import_constants12.INITIAL_BACKTEST_AMOUNT;
19346
19476
  return [...positionLog].sort(
19347
19477
  (left, right) => left.close.timestamp - right.close.timestamp || left.open.timestamp - right.open.timestamp
19348
19478
  ).map((position) => {
@@ -19436,7 +19566,7 @@ var init_historicalSignalsReplayResults = __esm({
19436
19566
  });
19437
19567
 
19438
19568
  // src/lib/replay/historicalSignalsReplay.ts
19439
- var import_chalk17, import_progress8, import_node_path12, import_node_module2, import_strategies5, import_time4, import_logger, import_redis8, import_connectors6, import_cli5, import_strategies6, import_runtimeStrategies3, projectReplayCacheReleasers, getProjectReplayCacheReleasers, releaseReplayCacheCopies, loadRuntimeStrategies, loadReferenceConnector, buildAfterSignalsContext, getConnectorName, loadHistoricalReplayReferences, runHistoricalSignalsReplay;
19569
+ var import_chalk17, import_progress8, import_node_path12, import_node_module2, import_strategies5, import_time4, import_logger2, import_redis9, import_connectors6, import_cli5, import_strategies6, import_runtimeStrategies3, projectReplayCacheReleasers, getProjectReplayCacheReleasers, releaseReplayCacheCopies, loadRuntimeStrategies, loadReferenceConnector, buildAfterSignalsContext, getConnectorName, loadHistoricalReplayReferences, runHistoricalSignalsReplay;
19440
19570
  var init_historicalSignalsReplay = __esm({
19441
19571
  "src/lib/replay/historicalSignalsReplay.ts"() {
19442
19572
  "use strict";
@@ -19447,8 +19577,8 @@ var init_historicalSignalsReplay = __esm({
19447
19577
  import_node_module2 = require("module");
19448
19578
  import_strategies5 = require("@tradejs/core/strategies");
19449
19579
  import_time4 = require("@tradejs/core/time");
19450
- import_logger = require("@tradejs/infra/logger");
19451
- import_redis8 = require("@tradejs/infra/redis");
19580
+ import_logger2 = require("@tradejs/infra/logger");
19581
+ import_redis9 = require("@tradejs/infra/redis");
19452
19582
  import_connectors6 = require("@tradejs/node/connectors");
19453
19583
  import_cli5 = require("@tradejs/node/cli");
19454
19584
  import_strategies6 = require("@tradejs/node/strategies");
@@ -19515,8 +19645,8 @@ var init_historicalSignalsReplay = __esm({
19515
19645
  `Runtime evidence package mismatch for ${strategyName}: expected=${strategyPackage}@${strategyPackageVersion}/@tradejs/node@${runtimePackageVersion}, installed=${installed.strategyPackage ?? "missing"}@${installed.strategyPackageVersion ?? "missing"}/@tradejs/node@${installed.runtimePackageVersion ?? "missing"}`
19516
19646
  );
19517
19647
  }
19518
- const strategyResults = await (0, import_redis8.getData)(
19519
- import_redis8.redisKeys.strategyResults(replayUserName, strategyName),
19648
+ const strategyResults = await (0, import_redis9.getData)(
19649
+ import_redis9.redisKeys.strategyResults(replayUserName, strategyName),
19520
19650
  {}
19521
19651
  );
19522
19652
  return {
@@ -19721,7 +19851,7 @@ var init_historicalSignalsReplay = __esm({
19721
19851
  releaseHistoricalReplayPlan(plan);
19722
19852
  memory?.("execution:released");
19723
19853
  const artifacts = replayConnector.getReplayArtifacts();
19724
- import_logger.logger.info(
19854
+ import_logger2.logger.info(
19725
19855
  import_chalk17.default.gray(
19726
19856
  `signals replay historical cycles: ${plan.orderedTimestamps.length} (aborted=${execution.abortedCycles}) done in ${((Date.now() - startedAt) / 1e3).toFixed(1)}s`
19727
19857
  )
@@ -20297,11 +20427,11 @@ var init_paritySummary = __esm({
20297
20427
  });
20298
20428
 
20299
20429
  // src/lib/runtimeSignalsStorage.ts
20300
- var import_constants12, import_data4, import_time5, appendRuntimeSignalEvaluationRun, SECONDS_PER_DAY, RUNTIME_SIGNAL_RETENTION_DAYS_ENV, DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS, RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS, parsePositiveNumber, getRuntimeSignalRetentionTtlSeconds, toRuntimeSignalBucketRef, shouldStoreRuntimeSignalDiagnostics, toStoredRuntimeSignal, isRuntimeSignalBucketRef, normalizeRuntimeSignalSkipReason, buildStatsReasonField, buildRuntimeSignalStatsIncrements, shouldStoreDetailedRuntimeSignalEvaluation, toCount, parseRuntimeSignalStatsBucket;
20430
+ var import_constants13, import_data4, import_time5, appendRuntimeSignalEvaluationRun, SECONDS_PER_DAY, RUNTIME_SIGNAL_RETENTION_DAYS_ENV, DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS, RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS, parsePositiveNumber, getRuntimeSignalRetentionTtlSeconds, toRuntimeSignalBucketRef, shouldStoreRuntimeSignalDiagnostics, toStoredRuntimeSignal, isRuntimeSignalBucketRef, normalizeRuntimeSignalSkipReason, buildStatsReasonField, buildRuntimeSignalStatsIncrements, shouldStoreDetailedRuntimeSignalEvaluation, toCount, parseRuntimeSignalStatsBucket;
20301
20431
  var init_runtimeSignalsStorage = __esm({
20302
20432
  "src/lib/runtimeSignalsStorage.ts"() {
20303
20433
  "use strict";
20304
- import_constants12 = require("@tradejs/core/constants");
20434
+ import_constants13 = require("@tradejs/core/constants");
20305
20435
  import_data4 = require("@tradejs/core/data");
20306
20436
  import_time5 = require("@tradejs/core/time");
20307
20437
  appendRuntimeSignalEvaluationRun = (runs = [], evaluation) => {
@@ -20336,8 +20466,8 @@ var init_runtimeSignalsStorage = __esm({
20336
20466
  };
20337
20467
  SECONDS_PER_DAY = 86400;
20338
20468
  RUNTIME_SIGNAL_RETENTION_DAYS_ENV = "RUNTIME_SIGNAL_RETENTION_DAYS";
20339
- DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS = import_constants12.TTL_3D;
20340
- RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS = import_constants12.TTL_1M;
20469
+ DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS = import_constants13.TTL_3D;
20470
+ RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS = import_constants13.TTL_1M;
20341
20471
  parsePositiveNumber = (value) => {
20342
20472
  if (value == null || value === "") {
20343
20473
  return null;
@@ -20470,11 +20600,11 @@ var init_runtimeSignalsStorage = __esm({
20470
20600
  });
20471
20601
 
20472
20602
  // src/lib/runtimeSignalsLoader.ts
20473
- var import_redis9, isSignalRecord, isRuntimeSignalEvaluationRecord, sortByTimestamp, filterBucketKeysByWindow, loadRuntimeSignals, loadRuntimeSignalEvaluations, loadRuntimeLineageScopes, parseBucketKey, loadRuntimeSignalEvaluationStatsBuckets;
20603
+ var import_redis10, isSignalRecord, isRuntimeSignalEvaluationRecord, sortByTimestamp, filterBucketKeysByWindow, loadRuntimeSignals, loadRuntimeSignalEvaluations, loadRuntimeLineageScopes, parseBucketKey, loadRuntimeSignalEvaluationStatsBuckets;
20474
20604
  var init_runtimeSignalsLoader = __esm({
20475
20605
  "src/lib/runtimeSignalsLoader.ts"() {
20476
20606
  "use strict";
20477
- import_redis9 = require("@tradejs/infra/redis");
20607
+ import_redis10 = require("@tradejs/infra/redis");
20478
20608
  init_runtimeSignalsStorage();
20479
20609
  isSignalRecord = (value) => {
20480
20610
  if (!value || typeof value !== "object") {
@@ -20512,14 +20642,14 @@ var init_runtimeSignalsLoader = __esm({
20512
20642
  startTime,
20513
20643
  endTime
20514
20644
  } = {}) => {
20515
- const bucketPrefix = import_redis9.redisKeys.runtimeSignalBuckets(userName3);
20645
+ const bucketPrefix = import_redis10.redisKeys.runtimeSignalBuckets(userName3);
20516
20646
  const bucketKeys = filterBucketKeysByWindow(
20517
- await (0, import_redis9.getKeys)(bucketPrefix),
20647
+ await (0, import_redis10.getKeys)(bucketPrefix),
20518
20648
  bucketPrefix,
20519
20649
  startTime,
20520
20650
  endTime
20521
20651
  );
20522
- const refs = (await Promise.all(bucketKeys.map((key2) => (0, import_redis9.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalBucketRef);
20652
+ const refs = (await Promise.all(bucketKeys.map((key2) => (0, import_redis10.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalBucketRef);
20523
20653
  const seen = /* @__PURE__ */ new Set();
20524
20654
  const payloads = await Promise.all(
20525
20655
  refs.map(async (ref) => {
@@ -20528,8 +20658,8 @@ var init_runtimeSignalsLoader = __esm({
20528
20658
  return null;
20529
20659
  }
20530
20660
  seen.add(dedupeKey);
20531
- const signal = await (0, import_redis9.getData)(
20532
- import_redis9.redisKeys.storeSignal(ref.symbol, ref.signalId),
20661
+ const signal = await (0, import_redis10.getData)(
20662
+ import_redis10.redisKeys.storeSignal(ref.symbol, ref.signalId),
20533
20663
  null
20534
20664
  );
20535
20665
  return isSignalRecord(signal) ? signal : null;
@@ -20541,14 +20671,14 @@ var init_runtimeSignalsLoader = __esm({
20541
20671
  startTime,
20542
20672
  endTime
20543
20673
  } = {}) => {
20544
- const bucketPrefix = import_redis9.redisKeys.runtimeSignalEvaluationBuckets(userName3);
20674
+ const bucketPrefix = import_redis10.redisKeys.runtimeSignalEvaluationBuckets(userName3);
20545
20675
  const bucketKeys = filterBucketKeysByWindow(
20546
- await (0, import_redis9.getKeys)(bucketPrefix),
20676
+ await (0, import_redis10.getKeys)(bucketPrefix),
20547
20677
  bucketPrefix,
20548
20678
  startTime,
20549
20679
  endTime
20550
20680
  );
20551
- const evaluations = (await Promise.all(bucketKeys.map((key2) => (0, import_redis9.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalEvaluationRecord);
20681
+ const evaluations = (await Promise.all(bucketKeys.map((key2) => (0, import_redis10.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalEvaluationRecord);
20552
20682
  const deduped = /* @__PURE__ */ new Map();
20553
20683
  for (const evaluation of evaluations) {
20554
20684
  deduped.set(evaluation.evaluationId, evaluation);
@@ -20561,8 +20691,8 @@ var init_runtimeSignalsLoader = __esm({
20561
20691
  }) => {
20562
20692
  const records = (await Promise.all(
20563
20693
  (0, import_time5.getRuntimeStorageDayKeys)(startTime, endTime).map(
20564
- (dayKey) => (0, import_redis9.getHashJsonValues)(
20565
- import_redis9.redisKeys.runtimeLineageScopeBucket(userName3, dayKey)
20694
+ (dayKey) => (0, import_redis10.getHashJsonValues)(
20695
+ import_redis10.redisKeys.runtimeLineageScopeBucket(userName3, dayKey)
20566
20696
  )
20567
20697
  )
20568
20698
  )).flat().filter(
@@ -20591,8 +20721,8 @@ var init_runtimeSignalsLoader = __esm({
20591
20721
  };
20592
20722
  };
20593
20723
  loadRuntimeSignalEvaluationStatsBuckets = async (userName3) => {
20594
- const prefix = import_redis9.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3);
20595
- const keys = await (0, import_redis9.getKeys)(prefix);
20724
+ const prefix = import_redis10.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3);
20725
+ const keys = await (0, import_redis10.getKeys)(prefix);
20596
20726
  const entries = await Promise.all(
20597
20727
  keys.map(async (key2) => {
20598
20728
  const parsedKey = parseBucketKey(prefix, key2);
@@ -20602,7 +20732,7 @@ var init_runtimeSignalsLoader = __esm({
20602
20732
  return {
20603
20733
  key: key2,
20604
20734
  ...parsedKey,
20605
- stats: parseRuntimeSignalStatsBucket(await (0, import_redis9.getHashData)(key2))
20735
+ stats: parseRuntimeSignalStatsBucket(await (0, import_redis10.getHashData)(key2))
20606
20736
  };
20607
20737
  })
20608
20738
  );
@@ -20612,13 +20742,13 @@ var init_runtimeSignalsLoader = __esm({
20612
20742
  });
20613
20743
 
20614
20744
  // src/lib/runtimeTradeSync.ts
20615
- var import_constants13, import_time6, import_redis10, CLOSED_PNL_LIMIT, CLOSED_PNL_RECONCILIATION_LOOKBACK_MS, EXCHANGE_HISTORY_MAX_RANGE_MS, isRuntimeTradeSyncFallbackClose, splitExchangeHistoryTimeRange, formatRuntimeTradeSyncError, loadClosedPnlRows, consumeClosedPnlMatch, isRuntimeTradeInConnectorScope, syncRuntimeTrades;
20745
+ var import_constants14, import_time6, import_redis11, CLOSED_PNL_LIMIT, CLOSED_PNL_RECONCILIATION_LOOKBACK_MS, EXCHANGE_HISTORY_MAX_RANGE_MS, isRuntimeTradeSyncFallbackClose, splitExchangeHistoryTimeRange, formatRuntimeTradeSyncError, loadClosedPnlRows, consumeClosedPnlMatch, isRuntimeTradeInConnectorScope, syncRuntimeTrades;
20616
20746
  var init_runtimeTradeSync = __esm({
20617
20747
  "src/lib/runtimeTradeSync.ts"() {
20618
20748
  "use strict";
20619
- import_constants13 = require("@tradejs/core/constants");
20749
+ import_constants14 = require("@tradejs/core/constants");
20620
20750
  import_time6 = require("@tradejs/core/time");
20621
- import_redis10 = require("@tradejs/infra/redis");
20751
+ import_redis11 = require("@tradejs/infra/redis");
20622
20752
  CLOSED_PNL_LIMIT = 100;
20623
20753
  CLOSED_PNL_RECONCILIATION_LOOKBACK_MS = 24 * 60 * 60 * 1e3;
20624
20754
  EXCHANGE_HISTORY_MAX_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
@@ -20751,7 +20881,7 @@ var init_runtimeTradeSync = __esm({
20751
20881
  const activeTradeKeys = [
20752
20882
  ...new Set(
20753
20883
  trades.filter((trade) => isRuntimeTradeInConnectorScope(trade, connector)).map(
20754
- (trade) => import_redis10.redisKeys.runtimeActiveTrade(
20884
+ (trade) => import_redis11.redisKeys.runtimeActiveTrade(
20755
20885
  userName3,
20756
20886
  trade.symbol,
20757
20887
  trade.deploymentId ?? trade.accountId
@@ -20761,7 +20891,7 @@ var init_runtimeTradeSync = __esm({
20761
20891
  ];
20762
20892
  await Promise.all(
20763
20893
  activeTradeKeys.map(async (key2) => {
20764
- const activeRef = await (0, import_redis10.getData)(key2, null);
20894
+ const activeRef = await (0, import_redis11.getData)(key2, null);
20765
20895
  activeOrderIdByKey.set(
20766
20896
  key2,
20767
20897
  typeof activeRef?.orderId === "string" ? activeRef.orderId : null
@@ -20790,7 +20920,7 @@ var init_runtimeTradeSync = __esm({
20790
20920
  syncedTrades.push(trade);
20791
20921
  continue;
20792
20922
  }
20793
- const activeTradeKey = import_redis10.redisKeys.runtimeActiveTrade(
20923
+ const activeTradeKey = import_redis11.redisKeys.runtimeActiveTrade(
20794
20924
  userName3,
20795
20925
  trade.symbol,
20796
20926
  trade.deploymentId ?? trade.accountId
@@ -20814,15 +20944,15 @@ var init_runtimeTradeSync = __esm({
20814
20944
  currentPnl: openPosition.unrealizedPnl,
20815
20945
  lastSyncedAt: endTime
20816
20946
  };
20817
- await (0, import_redis10.setData)(
20818
- import_redis10.redisKeys.runtimeTrade(userName3, trade.orderId),
20947
+ await (0, import_redis11.setData)(
20948
+ import_redis11.redisKeys.runtimeTrade(userName3, trade.orderId),
20819
20949
  nextTrade2,
20820
20950
  {
20821
20951
  expire: 0
20822
20952
  }
20823
20953
  );
20824
- await (0, import_redis10.setHashJsonField)(
20825
- import_redis10.redisKeys.runtimeTradeBucket(
20954
+ await (0, import_redis11.setHashJsonField)(
20955
+ import_redis11.redisKeys.runtimeTradeBucket(
20826
20956
  userName3,
20827
20957
  (0, import_time6.getRuntimeStorageDayKey)(trade.entryTimestamp)
20828
20958
  ),
@@ -20856,28 +20986,28 @@ var init_runtimeTradeSync = __esm({
20856
20986
  lastSyncedAt: endTime
20857
20987
  };
20858
20988
  await Promise.all([
20859
- (0, import_redis10.setData)(import_redis10.redisKeys.runtimeTrade(userName3, trade.orderId), nextTrade, {
20860
- expire: import_constants13.TTL_1M
20989
+ (0, import_redis11.setData)(import_redis11.redisKeys.runtimeTrade(userName3, trade.orderId), nextTrade, {
20990
+ expire: import_constants14.TTL_1M
20861
20991
  }),
20862
- (0, import_redis10.setHashJsonField)(
20863
- import_redis10.redisKeys.runtimeTradeBucket(
20992
+ (0, import_redis11.setHashJsonField)(
20993
+ import_redis11.redisKeys.runtimeTradeBucket(
20864
20994
  userName3,
20865
20995
  (0, import_time6.getRuntimeStorageDayKey)(trade.entryTimestamp)
20866
20996
  ),
20867
20997
  trade.orderId,
20868
20998
  nextTrade,
20869
- { expire: import_constants13.TTL_1M }
20999
+ { expire: import_constants14.TTL_1M }
20870
21000
  ),
20871
- (0, import_redis10.setHashJsonField)(
20872
- import_redis10.redisKeys.runtimeClosedTradeBucket(
21001
+ (0, import_redis11.setHashJsonField)(
21002
+ import_redis11.redisKeys.runtimeClosedTradeBucket(
20873
21003
  userName3,
20874
21004
  (0, import_time6.getRuntimeStorageDayKey)(nextTrade.exitTimestamp)
20875
21005
  ),
20876
21006
  trade.orderId,
20877
21007
  nextTrade,
20878
- { expire: import_constants13.TTL_1M }
21008
+ { expire: import_constants14.TTL_1M }
20879
21009
  ),
20880
- ...isCurrentActiveTrade ? [(0, import_redis10.delKey)(activeTradeKey)] : []
21010
+ ...isCurrentActiveTrade ? [(0, import_redis11.delKey)(activeTradeKey)] : []
20881
21011
  ]);
20882
21012
  syncedTrades.push(nextTrade);
20883
21013
  }
@@ -24412,16 +24542,16 @@ ${comparison.limitations.join(" ")}
24412
24542
  });
24413
24543
 
24414
24544
  // src/scripts/replayRunner.ts
24415
- var import_chalk21, import_constants14, import_data6, import_time8, import_redis11, import_candles2, import_runtimeStrategies4, import_strategies7, prepareReplayBinanceMarketContext, replayMarketContextInterval, cachedTickerSymbols, finishReplay, replayBacktest;
24545
+ var import_chalk21, import_constants15, import_data6, import_time8, import_redis12, import_candles2, import_runtimeStrategies4, import_strategies7, prepareReplayBinanceMarketContext, replayMarketContextInterval, cachedTickerSymbols, finishReplay, replayBacktest;
24416
24546
  var init_replayRunner = __esm({
24417
24547
  "src/scripts/replayRunner.ts"() {
24418
24548
  "use strict";
24419
24549
  init_historicalSignalsReplayPreparation();
24420
24550
  import_chalk21 = __toESM(require("chalk"));
24421
- import_constants14 = require("@tradejs/core/constants");
24551
+ import_constants15 = require("@tradejs/core/constants");
24422
24552
  import_data6 = require("@tradejs/core/data");
24423
24553
  import_time8 = require("@tradejs/core/time");
24424
- import_redis11 = require("@tradejs/infra/redis");
24554
+ import_redis12 = require("@tradejs/infra/redis");
24425
24555
  import_candles2 = require("@tradejs/infra/timescale/candles");
24426
24556
  import_runtimeStrategies4 = require("@tradejs/node/runtimeStrategies");
24427
24557
  import_strategies7 = require("@tradejs/node/strategies");
@@ -24475,12 +24605,12 @@ var init_replayRunner = __esm({
24475
24605
  ...connectorName.toLowerCase() === "bybit" ? ["ByBit"] : []
24476
24606
  ];
24477
24607
  const keys = connectorNames.flatMap((name) => [
24478
- import_redis11.redisKeys.tickerUniverse(replayUserName, name, universe, accountId),
24479
- import_redis11.redisKeys.tickerUniverse(replayUserName, name, universe, "default"),
24480
- import_redis11.redisKeys.tickerUniverse(replayUserName, name)
24608
+ import_redis12.redisKeys.tickerUniverse(replayUserName, name, universe, accountId),
24609
+ import_redis12.redisKeys.tickerUniverse(replayUserName, name, universe, "default"),
24610
+ import_redis12.redisKeys.tickerUniverse(replayUserName, name)
24481
24611
  ]);
24482
24612
  for (const key2 of [...new Set(keys)]) {
24483
- const cached = await (0, import_redis11.getData)(key2, null);
24613
+ const cached = await (0, import_redis12.getData)(key2, null);
24484
24614
  const symbols = (cached?.tickers ?? []).map(
24485
24615
  (ticker) => String(ticker.symbol ?? "").trim().toUpperCase()
24486
24616
  ).filter(Boolean);
@@ -24522,7 +24652,7 @@ var init_replayRunner = __esm({
24522
24652
  replayResult.orderLog[replayResult.orderLog.length - 1]?.timestamp ?? finishedAt.getTime()
24523
24653
  )}`
24524
24654
  }) : null;
24525
- const replayKey = import_redis11.redisKeys.backtestResults(
24655
+ const replayKey = import_redis12.redisKeys.backtestResults(
24526
24656
  replayUserName,
24527
24657
  REPLAY_RESULTS_CONFIG,
24528
24658
  timestamp
@@ -24556,7 +24686,7 @@ var init_replayRunner = __esm({
24556
24686
  console.log(import_chalk21.default.green(`Portfolio report: ${portfolioReport.html}`));
24557
24687
  console.log(import_chalk21.default.green(`Portfolio report JSON: ${portfolioReport.json}`));
24558
24688
  }
24559
- await (0, import_redis11.setData)(
24689
+ await (0, import_redis12.setData)(
24560
24690
  replayKey,
24561
24691
  {
24562
24692
  config: REPLAY_RESULTS_CONFIG,
@@ -24583,17 +24713,17 @@ var init_replayRunner = __esm({
24583
24713
  ...portfolioReport ? { portfolioReport } : {}
24584
24714
  },
24585
24715
  {
24586
- expire: import_constants14.TTL_1M
24716
+ expire: import_constants15.TTL_1M
24587
24717
  }
24588
24718
  );
24589
24719
  if (replayChartSnapshot) {
24590
24720
  await Promise.all(
24591
24721
  replayChartSnapshot.strategies.map(
24592
- (card) => (0, import_redis11.setData)(
24593
- import_redis11.redisKeys.strategyChartCard(replayUserName, "replay", card.cardId),
24722
+ (card) => (0, import_redis12.setData)(
24723
+ import_redis12.redisKeys.strategyChartCard(replayUserName, "replay", card.cardId),
24594
24724
  card,
24595
24725
  {
24596
- expire: import_constants14.TTL_1M
24726
+ expire: import_constants15.TTL_1M
24597
24727
  }
24598
24728
  )
24599
24729
  )
@@ -25045,7 +25175,7 @@ var init_binanceMarketIngest = __esm({
25045
25175
  import_client4 = require("@tradejs/infra/timescale/client");
25046
25176
  init_binanceMarketData();
25047
25177
  import_args9.default.example(
25048
- "yarn cli:node8g binance:market-ingest --all --symbols BTCUSDT,ETHUSDT --days 0.05 --interval 1m --write",
25178
+ "yarn cli:node8g binance:market-ingest --all --symbols BTCUSDT,ETHUSDT --days 0.05 --interval 15m --write",
25049
25179
  "Ingest Binance public market breadth and historical aggTrades buckets"
25050
25180
  );
25051
25181
  import_args9.default.option(
@@ -25053,7 +25183,7 @@ var init_binanceMarketIngest = __esm({
25053
25183
  "Comma-separated target symbols",
25054
25184
  "BTCUSDT,ETHUSDT"
25055
25185
  );
25056
- import_args9.default.option(["i", "interval"], "Aggregation interval: 1m,5m,15m,1h", "1m");
25186
+ import_args9.default.option(["i", "interval"], "Aggregation interval: 5m,15m,1h", "15m");
25057
25187
  import_args9.default.option(["d", "days"], "Lookback window in days", "1");
25058
25188
  import_args9.default.option(["h", "hours"], "Lookback window in hours; overrides --days");
25059
25189
  import_args9.default.option(["a", "aggTrades"], "Fetch and bucket Binance aggTrades");
@@ -25087,7 +25217,6 @@ var init_binanceMarketIngest = __esm({
25087
25217
  };
25088
25218
  sleep4 = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
25089
25219
  intervalToConnectorInterval = (interval4) => {
25090
- if (interval4 === "1m") return "1";
25091
25220
  if (interval4 === "5m") return "5";
25092
25221
  if (interval4 === "15m") return "15";
25093
25222
  return "60";
@@ -25143,6 +25272,7 @@ var init_binanceMarketIngest = __esm({
25143
25272
  main11 = async () => {
25144
25273
  const symbols = normalizeBinanceSymbols(flags7.symbols);
25145
25274
  const interval4 = normalizeMarketFeatureInterval(flags7.interval);
25275
+ if (interval4 === "1m") throw new Error("Use interval 5m, 15m, or 1h");
25146
25276
  const hours = flags7.hours == null ? null : asFloat2(flags7.hours, 0);
25147
25277
  const days = hours != null && hours > 0 ? hours / 24 : asFloat2(flags7.days, 1);
25148
25278
  const breadthUniverses = (0, import_strategies9.getBinanceBreadthUniverses)();
@@ -25256,7 +25386,7 @@ var init_binanceMarketIngest = __esm({
25256
25386
  });
25257
25387
 
25258
25388
  // src/lib/runBot.ts
25259
- var import_lodash, import_connectors10, import_data7, import_strategies10, import_async3, import_constants15, import_time9, import_logger2, import_redis12, projectRoot4, runBot;
25389
+ var import_lodash, import_connectors10, import_data7, import_strategies10, import_async3, import_constants16, import_time9, import_logger3, import_redis13, projectRoot4, runBot;
25260
25390
  var init_runBot = __esm({
25261
25391
  "src/lib/runBot.ts"() {
25262
25392
  "use strict";
@@ -25265,33 +25395,33 @@ var init_runBot = __esm({
25265
25395
  import_data7 = require("@tradejs/core/data");
25266
25396
  import_strategies10 = require("@tradejs/node/strategies");
25267
25397
  import_async3 = require("@tradejs/core/async");
25268
- import_constants15 = require("@tradejs/core/constants");
25398
+ import_constants16 = require("@tradejs/core/constants");
25269
25399
  import_time9 = require("@tradejs/core/time");
25270
- import_logger2 = require("@tradejs/infra/logger");
25271
- import_redis12 = require("@tradejs/infra/redis");
25400
+ import_logger3 = require("@tradejs/infra/logger");
25401
+ import_redis13 = require("@tradejs/infra/redis");
25272
25402
  projectRoot4 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
25273
25403
  runBot = async () => {
25274
25404
  const botResults = [];
25275
- const preloadStart = (0, import_time9.getTimestamp)(import_constants15.BOT_PRELOAD_DAYS);
25405
+ const preloadStart = (0, import_time9.getTimestamp)(import_constants16.BOT_PRELOAD_DAYS);
25276
25406
  const end = (0, import_time9.getTimestamp)();
25277
- const keys = await (0, import_redis12.getKeys)(import_redis12.redisKeys.botsPrefix());
25407
+ const keys = await (0, import_redis13.getKeys)(import_redis13.redisKeys.botsPrefix());
25278
25408
  const botKeys = keys.filter((key2) => key2.endsWith(":bots"));
25279
25409
  await (0, import_async3.delay)(5e3);
25280
- import_logger2.logger.log("info", "files count: %s", botKeys.length);
25410
+ import_logger3.logger.log("info", "files count: %s", botKeys.length);
25281
25411
  for await (const key2 of botKeys) {
25282
25412
  const userName3 = key2.split(":")[1];
25283
- import_logger2.logger.log("info", "user: %s", userName3);
25284
- const botConfig = await (0, import_redis12.getData)(import_redis12.redisKeys.bots(userName3));
25413
+ import_logger3.logger.log("info", "user: %s", userName3);
25414
+ const botConfig = await (0, import_redis13.getData)(import_redis13.redisKeys.bots(userName3));
25285
25415
  if (import_lodash.default.isEmpty(botConfig)) {
25286
- import_logger2.logger.log("error", "botConfig is empty: %s", userName3);
25416
+ import_logger3.logger.log("error", "botConfig is empty: %s", userName3);
25287
25417
  continue;
25288
25418
  }
25289
- import_logger2.logger.log("info", "bots count: %s", botConfig.length);
25419
+ import_logger3.logger.log("info", "bots count: %s", botConfig.length);
25290
25420
  for await (const bot of botConfig) {
25291
25421
  const { symbol, strategyName, strategyConfig, connectorName, disabled } = bot;
25292
- import_logger2.logger.log("info", "bot %s", symbol);
25422
+ import_logger3.logger.log("info", "bot %s", symbol);
25293
25423
  if (disabled) {
25294
- import_logger2.logger.log("error", "bot %s disabled", symbol);
25424
+ import_logger3.logger.log("error", "bot %s disabled", symbol);
25295
25425
  continue;
25296
25426
  }
25297
25427
  try {
@@ -25371,7 +25501,7 @@ var init_runBot = __esm({
25371
25501
  btcCoinbaseData,
25372
25502
  connector
25373
25503
  });
25374
- import_logger2.logger.log("info", "strategy created");
25504
+ import_logger3.logger.log("info", "strategy created");
25375
25505
  if (!candle || !btcCandle) {
25376
25506
  throw new Error("Candle is empty");
25377
25507
  }
@@ -25381,11 +25511,11 @@ var init_runBot = __esm({
25381
25511
  status: JSON.stringify(status)
25382
25512
  });
25383
25513
  } catch (err) {
25384
- import_logger2.logger.log("error", "bot %s error: %s", bot.symbol, (0, import_data7.toJson)(err, false));
25514
+ import_logger3.logger.log("error", "bot %s error: %s", bot.symbol, (0, import_data7.toJson)(err, false));
25385
25515
  }
25386
25516
  }
25387
25517
  }
25388
- import_logger2.logger.log("info", "botResults: %s", (0, import_data7.toJson)(botResults, true));
25518
+ import_logger3.logger.log("info", "botResults: %s", (0, import_data7.toJson)(botResults, true));
25389
25519
  return botResults;
25390
25520
  };
25391
25521
  }
@@ -25809,7 +25939,7 @@ var cleanTests_exports = {};
25809
25939
  __export(cleanTests_exports, {
25810
25940
  main: () => main16
25811
25941
  });
25812
- var import_args13, import_promises20, import_path7, import_chalk25, import_cli8, import_backtestArtifacts2, import_redis13, flags11, extractUsers, getUsersToClean, cleanUserTests, main16;
25942
+ var import_args13, import_promises20, import_path7, import_chalk25, import_cli8, import_backtestArtifacts2, import_redis14, flags11, extractUsers, getUsersToClean, cleanUserTests, main16;
25813
25943
  var init_cleanTests = __esm({
25814
25944
  "src/scripts/cleanTests.ts"() {
25815
25945
  "use strict";
@@ -25819,7 +25949,7 @@ var init_cleanTests = __esm({
25819
25949
  import_chalk25 = __toESM(require("chalk"));
25820
25950
  import_cli8 = require("@tradejs/node/cli");
25821
25951
  import_backtestArtifacts2 = require("@tradejs/infra/backtestArtifacts");
25822
- import_redis13 = require("@tradejs/infra/redis");
25952
+ import_redis14 = require("@tradejs/infra/redis");
25823
25953
  import_args13.default.option(["U", "user"], "Clean tests for user", "");
25824
25954
  import_args13.default.option(["C", "cache"], "Clean only cache keys", false);
25825
25955
  flags11 = import_args13.default.parse(process.argv);
@@ -25845,7 +25975,7 @@ var init_cleanTests = __esm({
25845
25975
  if (userName3) {
25846
25976
  return [userName3];
25847
25977
  }
25848
- const keys = await (0, import_redis13.getKeys)(import_redis13.redisKeys.users());
25978
+ const keys = await (0, import_redis14.getKeys)(import_redis14.redisKeys.users());
25849
25979
  return extractUsers(keys);
25850
25980
  };
25851
25981
  cleanUserTests = async (userName3) => {
@@ -25934,7 +26064,7 @@ var continuity_exports = {};
25934
26064
  __export(continuity_exports, {
25935
26065
  main: () => main17
25936
26066
  });
25937
- var import_args14, import_progress9, import_chalk26, import_connectors11, import_cli9, import_constants16, import_time10, import_logger3, import_candles3, import_client5, flags12, interval2, intervalKey, projectRoot5, parseProviders, runContinuity, main17;
26067
+ var import_args14, import_progress9, import_chalk26, import_connectors11, import_cli9, import_constants17, import_time10, import_logger4, import_candles3, import_client5, flags12, interval2, intervalKey, projectRoot5, parseProviders, runContinuity, main17;
25938
26068
  var init_continuity2 = __esm({
25939
26069
  "src/scripts/continuity.ts"() {
25940
26070
  "use strict";
@@ -25943,9 +26073,9 @@ var init_continuity2 = __esm({
25943
26073
  import_chalk26 = __toESM(require("chalk"));
25944
26074
  import_connectors11 = require("@tradejs/node/connectors");
25945
26075
  import_cli9 = require("@tradejs/node/cli");
25946
- import_constants16 = require("@tradejs/core/constants");
26076
+ import_constants17 = require("@tradejs/core/constants");
25947
26077
  import_time10 = require("@tradejs/core/time");
25948
- import_logger3 = require("@tradejs/infra/logger");
26078
+ import_logger4 = require("@tradejs/infra/logger");
25949
26079
  import_candles3 = require("@tradejs/infra/timescale/candles");
25950
26080
  import_client5 = require("@tradejs/infra/timescale/client");
25951
26081
  init_continuity();
@@ -25972,7 +26102,7 @@ var init_continuity2 = __esm({
25972
26102
  const uniqueSelected = [...new Set(selected)];
25973
26103
  const invalid = uniqueSelected.filter((item) => !allProviders.includes(item));
25974
26104
  if (invalid.length) {
25975
- import_logger3.logger.error(
26105
+ import_logger4.logger.error(
25976
26106
  "Unknown provider(s): %s. Supported: %s",
25977
26107
  invalid.join(", "),
25978
26108
  allProviders.join(", ")
@@ -26007,7 +26137,7 @@ var init_continuity2 = __esm({
26007
26137
  let broken = 0;
26008
26138
  let fixed = 0;
26009
26139
  const expectedMs = interval2 * 60 * 1e3;
26010
- import_logger3.logger.info(
26140
+ import_logger4.logger.info(
26011
26141
  import_chalk26.default.yellow(`continuity ${connectorName}:${universe}: ${tickers.length}`)
26012
26142
  );
26013
26143
  for await (const symbol of tickers) {
@@ -26021,7 +26151,7 @@ var init_continuity2 = __esm({
26021
26151
  let gap = findRepairableContinuityGap(data, expectedMs, universe);
26022
26152
  if (gap) {
26023
26153
  broken++;
26024
- import_logger3.logger.warn(
26154
+ import_logger4.logger.warn(
26025
26155
  "[%s:%s] gap %s %s: %s -> %s (%ss)",
26026
26156
  provider,
26027
26157
  universe,
@@ -26050,7 +26180,7 @@ var init_continuity2 = __esm({
26050
26180
  symbol: import_chalk26.default.gray(symbol)
26051
26181
  });
26052
26182
  }
26053
- import_logger3.logger.info(
26183
+ import_logger4.logger.info(
26054
26184
  import_chalk26.default.yellow(
26055
26185
  `[${provider}:${universe}] broken: ${broken}/${tickers.length}, fixed: ${fixed}`
26056
26186
  )
@@ -26058,17 +26188,17 @@ var init_continuity2 = __esm({
26058
26188
  };
26059
26189
  main17 = async () => {
26060
26190
  if (!Number.isFinite(interval2) || interval2 <= 0) {
26061
- import_logger3.logger.error("Invalid timeframe: %s", flags12.timeframe);
26191
+ import_logger4.logger.error("Invalid timeframe: %s", flags12.timeframe);
26062
26192
  process.exit(1);
26063
26193
  }
26064
26194
  await (0, import_client5.waitForDbReady)();
26065
- const reloadStart = (0, import_time10.getTimestamp)(import_constants16.PRELOAD_DAYS);
26195
+ const reloadStart = (0, import_time10.getTimestamp)(import_constants17.PRELOAD_DAYS);
26066
26196
  const reloadEnd = (0, import_time10.getTimestamp)();
26067
26197
  let requestedUniverse;
26068
26198
  try {
26069
26199
  requestedUniverse = parseContinuityUniverse(flags12.universe);
26070
26200
  } catch (error) {
26071
- import_logger3.logger.error(error.message);
26201
+ import_logger4.logger.error(error.message);
26072
26202
  process.exit(1);
26073
26203
  }
26074
26204
  const providerIds = await parseProviders(flags12.provider);
@@ -26079,7 +26209,7 @@ var init_continuity2 = __esm({
26079
26209
  projectRoot5
26080
26210
  );
26081
26211
  if (!connectorName) {
26082
- import_logger3.logger.warn(
26212
+ import_logger4.logger.warn(
26083
26213
  'Skip provider "%s": connector mapping is missing',
26084
26214
  providerId
26085
26215
  );
@@ -26090,7 +26220,7 @@ var init_continuity2 = __esm({
26090
26220
  projectRoot5
26091
26221
  );
26092
26222
  if (!creator) {
26093
- import_logger3.logger.warn(
26223
+ import_logger4.logger.warn(
26094
26224
  'Skip provider "%s": connector "%s" is not registered',
26095
26225
  providerId,
26096
26226
  connectorName
@@ -26106,7 +26236,7 @@ var init_continuity2 = __esm({
26106
26236
  );
26107
26237
  const activeProviders = providers.filter(Boolean);
26108
26238
  if (!activeProviders.length) {
26109
- import_logger3.logger.error("No connector providers available");
26239
+ import_logger4.logger.error("No connector providers available");
26110
26240
  process.exit(1);
26111
26241
  }
26112
26242
  for await (const provider of activeProviders) {
@@ -26118,7 +26248,7 @@ var init_continuity2 = __esm({
26118
26248
  defaultConnector.capabilities.supportedUniverses
26119
26249
  );
26120
26250
  if (!universes.length) {
26121
- import_logger3.logger.warn(
26251
+ import_logger4.logger.warn(
26122
26252
  'Skip provider "%s": universe "%s" is not supported',
26123
26253
  provider.id,
26124
26254
  requestedUniverse
@@ -26844,11 +26974,11 @@ var init_doctor = __esm({
26844
26974
  });
26845
26975
 
26846
26976
  // src/lib/executionCalibration.ts
26847
- var import_constants17, import_data8, import_trade3, roundMetric, asRecord3, asArray, finiteNumber2, finiteString, finiteDirection, metricValues, quantile2, summarizeNumbers, getIntervalMs, getSignalKey, addSignalToMap, getRuntimePayload, extractRuntimeTradeRows, normalizeReplayMatch, extractReplayMatches, buildReplayMatchMaps, getSignalCandles, adverseEntryBps, feeBps, latencyDelta, resolveTelemetryQuality, finiteTelemetryQuality, countBy, toLatencyBucket, toSpreadBucket, buildSample, buildReplayOnlySample, hasTelemetry, hasFullTelemetry, buildGroupSummary, groupSamples, positiveMetricValues, buildRecommendation, buildExecutionCalibrationReport;
26977
+ var import_constants18, import_data8, import_trade3, roundMetric, asRecord3, asArray, finiteNumber2, finiteString, finiteDirection, metricValues, quantile2, summarizeNumbers, getIntervalMs, getSignalKey, addSignalToMap, getRuntimePayload, extractRuntimeTradeRows, normalizeReplayMatch, extractReplayMatches, buildReplayMatchMaps, getSignalCandles, adverseEntryBps, feeBps, latencyDelta, resolveTelemetryQuality, finiteTelemetryQuality, countBy, toLatencyBucket, toSpreadBucket, buildSample, buildReplayOnlySample, hasTelemetry, hasFullTelemetry, buildGroupSummary, groupSamples, positiveMetricValues, buildRecommendation, buildExecutionCalibrationReport;
26848
26978
  var init_executionCalibration = __esm({
26849
26979
  "src/lib/executionCalibration.ts"() {
26850
26980
  "use strict";
26851
- import_constants17 = require("@tradejs/core/constants");
26981
+ import_constants18 = require("@tradejs/core/constants");
26852
26982
  import_data8 = require("@tradejs/core/data");
26853
26983
  import_trade3 = require("@tradejs/core/trade");
26854
26984
  roundMetric = (value, decimals = 6) => typeof value === "number" && Number.isFinite(value) ? Number(value.toFixed(decimals)) : null;
@@ -27233,7 +27363,7 @@ var init_executionCalibration = __esm({
27233
27363
  actualPrice: fillAvgPrice
27234
27364
  });
27235
27365
  const currentModelEntrySlippageBps = signalToFillAdverseBps != null ? roundMetric(
27236
- import_constants17.BACKTEST_BASE_SLIPPAGE_BPS + (spreadBps ?? 0) * import_constants17.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER + import_constants17.BACKTEST_MARKET_IMPACT_BPS + (currentDelayRiskBps ?? 0)
27366
+ import_constants18.BACKTEST_BASE_SLIPPAGE_BPS + (spreadBps ?? 0) * import_constants18.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER + import_constants18.BACKTEST_MARKET_IMPACT_BPS + (currentDelayRiskBps ?? 0)
27237
27367
  ) : null;
27238
27368
  const residualVsCurrentModelBps = signalToFillAdverseBps != null && currentModelEntrySlippageBps != null ? roundMetric(signalToFillAdverseBps - currentModelEntrySlippageBps) : null;
27239
27369
  return {
@@ -27428,7 +27558,7 @@ var init_executionCalibration = __esm({
27428
27558
  }
27429
27559
  return Math.max(
27430
27560
  0,
27431
- sample.arrivalToFillAdverseBps - (sample.spreadBps ?? 0) * (spreadMultiplier ?? import_constants17.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER)
27561
+ sample.arrivalToFillAdverseBps - (sample.spreadBps ?? 0) * (spreadMultiplier ?? import_constants18.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER)
27432
27562
  );
27433
27563
  }).filter(
27434
27564
  (value) => value != null && Number.isFinite(value)
@@ -27491,9 +27621,9 @@ var init_executionCalibration = __esm({
27491
27621
  generatedAt: nowMs,
27492
27622
  sources: sourcePaths,
27493
27623
  currentModel: {
27494
- baseSlippageBps: import_constants17.BACKTEST_BASE_SLIPPAGE_BPS,
27495
- spreadMultiplier: import_constants17.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER,
27496
- marketImpactBps: import_constants17.BACKTEST_MARKET_IMPACT_BPS
27624
+ baseSlippageBps: import_constants18.BACKTEST_BASE_SLIPPAGE_BPS,
27625
+ spreadMultiplier: import_constants18.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER,
27626
+ marketImpactBps: import_constants18.BACKTEST_MARKET_IMPACT_BPS
27497
27627
  },
27498
27628
  counts: {
27499
27629
  runtimeTrades: runtimeRows.length,
@@ -27840,13 +27970,13 @@ var migration_exports = {};
27840
27970
  __export(migration_exports, {
27841
27971
  main: () => main26
27842
27972
  });
27843
- var import_progress11, import_chalk36, import_logger4, import_files, import_candles4, DIR, re, BATCH, projectRoot7, migrateFile, main26;
27973
+ var import_progress11, import_chalk36, import_logger5, import_files, import_candles4, DIR, re, BATCH, projectRoot7, migrateFile, main26;
27844
27974
  var init_migration = __esm({
27845
27975
  "src/scripts/migration.ts"() {
27846
27976
  "use strict";
27847
27977
  import_progress11 = __toESM(require("progress"));
27848
27978
  import_chalk36 = __toESM(require("chalk"));
27849
- import_logger4 = require("@tradejs/infra/logger");
27979
+ import_logger5 = require("@tradejs/infra/logger");
27850
27980
  import_files = require("@tradejs/infra/files");
27851
27981
  import_candles4 = require("@tradejs/infra/timescale/candles");
27852
27982
  DIR = "data/history";
@@ -27882,7 +28012,7 @@ var init_migration = __esm({
27882
28012
  try {
27883
28013
  await migrateFile(file);
27884
28014
  } catch (e) {
27885
- import_logger4.logger.error("Failed: %s %s", file, e);
28015
+ import_logger5.logger.error("Failed: %s %s", file, e);
27886
28016
  } finally {
27887
28017
  bar.tick(1, {
27888
28018
  file: import_chalk36.default.gray(file)
@@ -27895,12 +28025,12 @@ var init_migration = __esm({
27895
28025
  });
27896
28026
 
27897
28027
  // src/lib/marketData/klineEvents.ts
27898
- var import_ioredis2, import_redis14, MARKET_KLINE_CHANNEL, positiveInt2, redisOptions, buildMarketKlineTopic, publishMarketKlineEvent, createMarketKlineSubscriber, parseMarketKlineEvent;
28028
+ var import_ioredis2, import_redis15, MARKET_KLINE_CHANNEL, positiveInt2, redisOptions, buildMarketKlineTopic, publishMarketKlineEvent, createMarketKlineSubscriber, parseMarketKlineEvent;
27899
28029
  var init_klineEvents = __esm({
27900
28030
  "src/lib/marketData/klineEvents.ts"() {
27901
28031
  "use strict";
27902
28032
  import_ioredis2 = __toESM(require("ioredis"));
27903
- import_redis14 = require("@tradejs/infra/redis");
28033
+ import_redis15 = require("@tradejs/infra/redis");
27904
28034
  MARKET_KLINE_CHANNEL = "tradejs:market:kline";
27905
28035
  positiveInt2 = (value, fallback) => {
27906
28036
  const parsed = Number(value);
@@ -27919,7 +28049,7 @@ var init_klineEvents = __esm({
27919
28049
  event.symbol.trim().toUpperCase(),
27920
28050
  event.interval
27921
28051
  ].join(":");
27922
- publishMarketKlineEvent = (event) => (0, import_redis14.publishData)(MARKET_KLINE_CHANNEL, event);
28052
+ publishMarketKlineEvent = (event) => (0, import_redis15.publishData)(MARKET_KLINE_CHANNEL, event);
27923
28053
  createMarketKlineSubscriber = () => new import_ioredis2.default(redisOptions());
27924
28054
  parseMarketKlineEvent = (payload) => {
27925
28055
  try {
@@ -27936,13 +28066,13 @@ var init_klineEvents = __esm({
27936
28066
  });
27937
28067
 
27938
28068
  // src/lib/marketData/marketWsGateway.ts
27939
- var import_http, import_ws, import_logger5, MAX_TOPICS_PER_CLIENT, TOPIC_PATTERN, parseSubscriptionCommand, applySubscriptionCommand, startMarketWsGateway;
28069
+ var import_http, import_ws, import_logger6, MAX_TOPICS_PER_CLIENT, TOPIC_PATTERN, parseSubscriptionCommand, applySubscriptionCommand, startMarketWsGateway;
27940
28070
  var init_marketWsGateway = __esm({
27941
28071
  "src/lib/marketData/marketWsGateway.ts"() {
27942
28072
  "use strict";
27943
28073
  import_http = __toESM(require("http"));
27944
28074
  import_ws = require("ws");
27945
- import_logger5 = require("@tradejs/infra/logger");
28075
+ import_logger6 = require("@tradejs/infra/logger");
27946
28076
  init_klineEvents();
27947
28077
  MAX_TOPICS_PER_CLIENT = 20;
27948
28078
  TOPIC_PATTERN = /^(bybit|binance|coinbase):(crypto|tradfi):[A-Z0-9._-]+:(1|3|5|15|30|60|120|240|360|720|D|W|M)$/;
@@ -28056,7 +28186,7 @@ var init_marketWsGateway = __esm({
28056
28186
  resolve();
28057
28187
  });
28058
28188
  });
28059
- import_logger5.logger.info("market websocket gateway listening on %s:%s", host, port);
28189
+ import_logger6.logger.info("market websocket gateway listening on %s:%s", host, port);
28060
28190
  return {
28061
28191
  close: async () => {
28062
28192
  clearInterval(heartbeat);
@@ -28198,14 +28328,14 @@ var mcpWorker_exports = {};
28198
28328
  __export(mcpWorker_exports, {
28199
28329
  main: () => main28
28200
28330
  });
28201
- var import_node_child_process4, import_node_crypto15, import_promises23, import_redis15, import_mcp, pause, leaseKey, LEASE_SECONDS, JOB_TIMEOUT_MS, main28;
28331
+ var import_node_child_process4, import_node_crypto15, import_promises23, import_redis16, import_mcp, pause, leaseKey, LEASE_SECONDS, JOB_TIMEOUT_MS, main28;
28202
28332
  var init_mcpWorker = __esm({
28203
28333
  "src/scripts/mcpWorker.ts"() {
28204
28334
  "use strict";
28205
28335
  import_node_child_process4 = require("child_process");
28206
28336
  import_node_crypto15 = require("crypto");
28207
28337
  import_promises23 = require("fs/promises");
28208
- import_redis15 = require("@tradejs/infra/redis");
28338
+ import_redis16 = require("@tradejs/infra/redis");
28209
28339
  import_mcp = require("@tradejs/node/mcp");
28210
28340
  init_mcpReplayProcess();
28211
28341
  pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
@@ -28214,7 +28344,7 @@ var init_mcpWorker = __esm({
28214
28344
  JOB_TIMEOUT_MS = 60 * 60 * 1e3;
28215
28345
  main28 = async (options = {}) => {
28216
28346
  const owner = (0, import_node_crypto15.randomUUID)();
28217
- if (!await import_redis15.mcpStorage.put(leaseKey, owner, LEASE_SECONDS, true))
28347
+ if (!await import_redis16.mcpStorage.put(leaseKey, owner, LEASE_SECONDS, true))
28218
28348
  throw new Error("Another MCP worker owns this storage");
28219
28349
  let stopping = false;
28220
28350
  let child;
@@ -28278,10 +28408,10 @@ var init_mcpWorker = __esm({
28278
28408
  if (renewing || leaseLost) return;
28279
28409
  renewing = true;
28280
28410
  try {
28281
- if (!await import_redis15.mcpStorage.compare(leaseKey, owner, owner, LEASE_SECONDS))
28411
+ if (!await import_redis16.mcpStorage.compare(leaseKey, owner, owner, LEASE_SECONDS))
28282
28412
  throw new Error("Worker lease lost");
28283
28413
  await updateReplayReady();
28284
- await import_redis15.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
28414
+ await import_redis16.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
28285
28415
  } catch {
28286
28416
  leaseLost = true;
28287
28417
  stop();
@@ -28292,15 +28422,15 @@ var init_mcpWorker = __esm({
28292
28422
  try {
28293
28423
  manifestHash = await (0, import_mcp.mcpPackageManifestHash)();
28294
28424
  await updateReplayReady();
28295
- await import_redis15.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
28425
+ await import_redis16.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
28296
28426
  let cursor = "0";
28297
28427
  do {
28298
- const page = await import_redis15.mcpStorage.scan("jobs:", cursor);
28428
+ const page = await import_redis16.mcpStorage.scan("jobs:", cursor);
28299
28429
  cursor = page.cursor;
28300
28430
  for (const key2 of page.ids) {
28301
- const job = await import_redis15.mcpStorage.get(key2);
28431
+ const job = await import_redis16.mcpStorage.get(key2);
28302
28432
  if (job?.status === "running")
28303
- await import_redis15.mcpStorage.compare(
28433
+ await import_redis16.mcpStorage.compare(
28304
28434
  key2,
28305
28435
  job,
28306
28436
  {
@@ -28321,10 +28451,10 @@ var init_mcpWorker = __esm({
28321
28451
  let queued;
28322
28452
  cursor = "0";
28323
28453
  do {
28324
- const page = await import_redis15.mcpStorage.scan("jobs:", cursor);
28454
+ const page = await import_redis16.mcpStorage.scan("jobs:", cursor);
28325
28455
  cursor = page.cursor;
28326
28456
  for (const key2 of page.ids) {
28327
- const job = await import_redis15.mcpStorage.get(key2);
28457
+ const job = await import_redis16.mcpStorage.get(key2);
28328
28458
  if (job && ["queued", "waiting_resources", "waiting_executor"].includes(
28329
28459
  job.status
28330
28460
  ) && (!queued || job.createdAt < queued.createdAt))
@@ -28342,10 +28472,10 @@ var init_mcpWorker = __esm({
28342
28472
  ...queued.kind === "runtime-feedback-replay" ? {} : { startedAt: Date.now() },
28343
28473
  updatedAt: Date.now()
28344
28474
  };
28345
- if (!await import_redis15.mcpStorage.compare(jobKey, queued, started, import_mcp.MCP_JOB_TTL))
28475
+ if (!await import_redis16.mcpStorage.compare(jobKey, queued, started, import_mcp.MCP_JOB_TTL))
28346
28476
  continue;
28347
28477
  if (started.kind !== "runtime-feedback-replay" && started.packageManifestSha256 !== manifestHash) {
28348
- await import_redis15.mcpStorage.compare(
28478
+ await import_redis16.mcpStorage.compare(
28349
28479
  jobKey,
28350
28480
  started,
28351
28481
  {
@@ -28360,8 +28490,8 @@ var init_mcpWorker = __esm({
28360
28490
  }
28361
28491
  await (0, import_promises23.mkdir)((0, import_mcp.mcpJobDirectory)(started), { recursive: true });
28362
28492
  if (started.kind === "backtest")
28363
- await (0, import_redis15.setDataStrict)(
28364
- import_redis15.redisKeys.backtestConfig(
28493
+ await (0, import_redis16.setDataStrict)(
28494
+ import_redis16.redisKeys.backtestConfig(
28365
28495
  started.userName,
28366
28496
  String(started.request.frozenConfigId)
28367
28497
  ),
@@ -28410,7 +28540,7 @@ var init_mcpWorker = __esm({
28410
28540
  env: process.env
28411
28541
  });
28412
28542
  } catch (error) {
28413
- await import_redis15.mcpStorage.compare(
28543
+ await import_redis16.mcpStorage.compare(
28414
28544
  jobKey,
28415
28545
  started,
28416
28546
  {
@@ -28448,7 +28578,7 @@ var init_mcpWorker = __esm({
28448
28578
  let killAt;
28449
28579
  const monitor = setInterval(async () => {
28450
28580
  try {
28451
- const latest = await import_redis15.mcpStorage.get(jobKey);
28581
+ const latest = await import_redis16.mcpStorage.get(jobKey);
28452
28582
  if (!latest || latest.cancelRequested || stopping || timedOut) {
28453
28583
  killAt ??= Date.now();
28454
28584
  signalChild(Date.now() - killAt > 8e3 ? "SIGKILL" : "SIGTERM");
@@ -28473,7 +28603,7 @@ var init_mcpWorker = __esm({
28473
28603
  }
28474
28604
  }
28475
28605
  if (latest && !leaseLost)
28476
- await import_redis15.mcpStorage.compare(
28606
+ await import_redis16.mcpStorage.compare(
28477
28607
  jobKey,
28478
28608
  latest,
28479
28609
  {
@@ -28504,7 +28634,7 @@ var init_mcpWorker = __esm({
28504
28634
  child = void 0;
28505
28635
  if (!leaseLost) {
28506
28636
  for (let attempt = 0; attempt < 4; attempt++) {
28507
- const latest = await import_redis15.mcpStorage.get(jobKey);
28637
+ const latest = await import_redis16.mcpStorage.get(jobKey);
28508
28638
  if (!latest) break;
28509
28639
  const cancelled = latest.cancelRequested;
28510
28640
  const next = {
@@ -28520,7 +28650,7 @@ var init_mcpWorker = __esm({
28520
28650
  ) || logs.at(-1) : void 0) || "Research process failed"
28521
28651
  } : {}
28522
28652
  };
28523
- if (await import_redis15.mcpStorage.compare(jobKey, latest, next, import_mcp.MCP_JOB_TTL))
28653
+ if (await import_redis16.mcpStorage.compare(jobKey, latest, next, import_mcp.MCP_JOB_TTL))
28524
28654
  break;
28525
28655
  }
28526
28656
  }
@@ -28530,8 +28660,8 @@ var init_mcpWorker = __esm({
28530
28660
  options.signal?.removeEventListener("abort", stop);
28531
28661
  process.removeListener("SIGINT", stop);
28532
28662
  process.removeListener("SIGTERM", stop);
28533
- if (await import_redis15.mcpStorage.release(leaseKey, owner))
28534
- await import_redis15.mcpStorage.remove("worker:heartbeat");
28663
+ if (await import_redis16.mcpStorage.release(leaseKey, owner))
28664
+ await import_redis16.mcpStorage.remove("worker:heartbeat");
28535
28665
  }
28536
28666
  if (leaseLost)
28537
28667
  throw new Error("Worker lease lost; active computation was stopped");
@@ -30677,7 +30807,7 @@ __export(researchAuto_exports, {
30677
30807
  toStrategyConfigGrid: () => toStrategyConfigGrid2,
30678
30808
  trimTextTail: () => trimTextTail2
30679
30809
  });
30680
- var import_args25, import_chalk40, import_node_child_process5, import_promises27, import_node_os2, import_node_path20, import_constants18, import_ai8, import_logger6, import_redis16, import_registry4, flags23, projectRoot8, dotenvPath, getResearchAutoLockPath, readResearchAutoLock, isProcessAlive, acquireResearchAutoLock, releaseResearchAutoLock, resolvePositiveInteger, resolveHeapMbFromEnv, buildNodeOptions, RESEARCH_AUTO_PARENT_HEAP_MB, RESEARCH_AUTO_BACKTEST_PARENT_HEAP_MB, RESEARCH_AUTO_AI_TRAIN_PARENT_HEAP_MB, RESEARCH_AUTO_AGENT_PARENT_HEAP_MB, trimTextTail2, escapeHtml3, createEmptySteps, saveRun, listMergedFiles3, getBacktestResultsPrefix, listRuntimeStrategyNames, toStrategyConfigGrid2, formatMskDateTime, buildTelegramReport, runCliCommand, resolveTarget, parseJsonOutput, logResearch, executeNonBlockingStep, main35;
30810
+ var import_args25, import_chalk40, import_node_child_process5, import_promises27, import_node_os2, import_node_path20, import_constants19, import_ai8, import_logger7, import_redis17, import_registry4, flags23, projectRoot8, dotenvPath, getResearchAutoLockPath, readResearchAutoLock, isProcessAlive, acquireResearchAutoLock, releaseResearchAutoLock, resolvePositiveInteger, resolveHeapMbFromEnv, buildNodeOptions, RESEARCH_AUTO_PARENT_HEAP_MB, RESEARCH_AUTO_BACKTEST_PARENT_HEAP_MB, RESEARCH_AUTO_AI_TRAIN_PARENT_HEAP_MB, RESEARCH_AUTO_AGENT_PARENT_HEAP_MB, trimTextTail2, escapeHtml3, createEmptySteps, saveRun, listMergedFiles3, getBacktestResultsPrefix, listRuntimeStrategyNames, toStrategyConfigGrid2, formatMskDateTime, buildTelegramReport, runCliCommand, resolveTarget, parseJsonOutput, logResearch, executeNonBlockingStep, main35;
30681
30811
  var init_researchAuto = __esm({
30682
30812
  "src/scripts/researchAuto.ts"() {
30683
30813
  "use strict";
@@ -30687,10 +30817,10 @@ var init_researchAuto = __esm({
30687
30817
  import_promises27 = __toESM(require("fs/promises"));
30688
30818
  import_node_os2 = __toESM(require("os"));
30689
30819
  import_node_path20 = __toESM(require("path"));
30690
- import_constants18 = require("@tradejs/core/constants");
30820
+ import_constants19 = require("@tradejs/core/constants");
30691
30821
  import_ai8 = require("@tradejs/infra/ai");
30692
- import_logger6 = require("@tradejs/infra/logger");
30693
- import_redis16 = require("@tradejs/infra/redis");
30822
+ import_logger7 = require("@tradejs/infra/logger");
30823
+ import_redis17 = require("@tradejs/infra/redis");
30694
30824
  import_registry4 = require("@tradejs/node/registry");
30695
30825
  init_runtimeRedis();
30696
30826
  init_runtimeStrategyBacktest();
@@ -30892,11 +31022,11 @@ var init_researchAuto = __esm({
30892
31022
  }
30893
31023
  });
30894
31024
  saveRun = async (run) => {
30895
- await (0, import_redis16.setData)(import_redis16.redisKeys.researchRun(run.userName, run.runId), run, {
30896
- expire: import_constants18.TTL_1M
31025
+ await (0, import_redis17.setData)(import_redis17.redisKeys.researchRun(run.userName, run.runId), run, {
31026
+ expire: import_constants19.TTL_1M
30897
31027
  });
30898
- await (0, import_redis16.setData)(import_redis16.redisKeys.researchLatestRun(run.userName, run.strategy), run, {
30899
- expire: import_constants18.TTL_1M
31028
+ await (0, import_redis17.setData)(import_redis17.redisKeys.researchLatestRun(run.userName, run.strategy), run, {
31029
+ expire: import_constants19.TTL_1M
30900
31030
  });
30901
31031
  };
30902
31032
  listMergedFiles3 = async (outDir, strategyName) => {
@@ -31057,13 +31187,13 @@ var init_researchAuto = __esm({
31057
31187
  const emitLines = (source, text3) => {
31058
31188
  const prefix = params.liveLogPrefix ? `[research:auto:${params.liveLogPrefix}:${source}] ` : `[research:auto:${source}] `;
31059
31189
  for (const line of text3.split(/\r?\n/).map((value) => value.trimEnd()).filter(Boolean)) {
31060
- import_logger6.logger.info(import_chalk40.default.gray(`${prefix}${line}`));
31190
+ import_logger7.logger.info(import_chalk40.default.gray(`${prefix}${line}`));
31061
31191
  }
31062
31192
  };
31063
31193
  if (params.heartbeatMs && params.heartbeatMs > 0) {
31064
31194
  heartbeatTimer = setInterval(() => {
31065
31195
  const elapsedMs = Date.now() - startedAt;
31066
- import_logger6.logger.info(
31196
+ import_logger7.logger.info(
31067
31197
  import_chalk40.default.gray(
31068
31198
  `[research:auto:${params.liveLogPrefix || params.command}] still running after ${Math.round(elapsedMs / 1e3)}s`
31069
31199
  )
@@ -31125,8 +31255,8 @@ var init_researchAuto = __esm({
31125
31255
  const candidates = [];
31126
31256
  for (const strategy of availableStrategies) {
31127
31257
  const config2 = `${strategy}:research`;
31128
- const latestRun = await (0, import_redis16.getData)(
31129
- import_redis16.redisKeys.researchLatestRun(userName3, strategy),
31258
+ const latestRun = await (0, import_redis17.getData)(
31259
+ import_redis17.redisKeys.researchLatestRun(userName3, strategy),
31130
31260
  null
31131
31261
  );
31132
31262
  const lastFinishedAt = latestRun?.finishedAt ? Date.parse(latestRun.finishedAt) : 0;
@@ -31163,7 +31293,7 @@ var init_researchAuto = __esm({
31163
31293
  return JSON.parse(trimmed);
31164
31294
  };
31165
31295
  logResearch = (message) => {
31166
- import_logger6.logger.info(import_chalk40.default.cyan(`[research:auto] ${message}`));
31296
+ import_logger7.logger.info(import_chalk40.default.cyan(`[research:auto] ${message}`));
31167
31297
  };
31168
31298
  executeNonBlockingStep = async (run, stepName, command, commandArgs, options = {}) => {
31169
31299
  logResearch(
@@ -31305,13 +31435,13 @@ var init_researchAuto = __esm({
31305
31435
  startedAt
31306
31436
  };
31307
31437
  await saveRun(run);
31308
- const strategyConfigKey = import_redis16.redisKeys.strategyConfig(
31438
+ const strategyConfigKey = import_redis17.redisKeys.strategyConfig(
31309
31439
  userName3,
31310
31440
  target.strategy
31311
31441
  );
31312
- const backtestConfigKey = import_redis16.redisKeys.backtestConfig(userName3, target.config);
31442
+ const backtestConfigKey = import_redis17.redisKeys.backtestConfig(userName3, target.config);
31313
31443
  const defaults = await (0, import_registry4.getStrategyDefaults)(target.strategy, projectRoot8) || {};
31314
- const userStrategyConfig = await (0, import_redis16.getData)(
31444
+ const userStrategyConfig = await (0, import_redis17.getData)(
31315
31445
  strategyConfigKey,
31316
31446
  {}
31317
31447
  );
@@ -31325,7 +31455,7 @@ var init_researchAuto = __esm({
31325
31455
  );
31326
31456
  }
31327
31457
  const backtestConfig = toStrategyConfigGrid2(strategyConfig);
31328
- await (0, import_redis16.setData)(backtestConfigKey, backtestConfig, { expire: 0 });
31458
+ await (0, import_redis17.setData)(backtestConfigKey, backtestConfig, { expire: 0 });
31329
31459
  logResearch(
31330
31460
  `stored backtest config at ${backtestConfigKey} with ${Object.keys(strategyConfig).length} top-level fields`
31331
31461
  );
@@ -31365,7 +31495,7 @@ var init_researchAuto = __esm({
31365
31495
  `resource knobs: researchAutoHeapMb=${RESEARCH_AUTO_PARENT_HEAP_MB}, backtestParentHeapMb=${RESEARCH_AUTO_BACKTEST_PARENT_HEAP_MB}, aiTrainParentHeapMb=${RESEARCH_AUTO_AI_TRAIN_PARENT_HEAP_MB}, agentParentHeapMb=${RESEARCH_AUTO_AGENT_PARENT_HEAP_MB}, backtestWorkerHeapMb=${process.env.BACKTEST_WORKER_HEAP_MB || "auto"}, backtestMaxParallel=${process.env.BACKTEST_MAX_PARALLEL || "auto"}, klineConcurrency=${process.env.KLINE_CONCURRENCY_LIMIT || "default"}`
31366
31496
  );
31367
31497
  const backtestKeysBefore = new Set(
31368
- await (0, import_redis16.getKeys)(getBacktestResultsPrefix(userName3, target.config))
31498
+ await (0, import_redis17.getKeys)(getBacktestResultsPrefix(userName3, target.config))
31369
31499
  );
31370
31500
  const aiFilesBefore = new Set(
31371
31501
  await listMergedFiles3(outDir, target.strategy)
@@ -31427,14 +31557,14 @@ var init_researchAuto = __esm({
31427
31557
  captureMode: "full"
31428
31558
  }
31429
31559
  );
31430
- const backtestKeysAfter = await (0, import_redis16.getKeys)(
31560
+ const backtestKeysAfter = await (0, import_redis17.getKeys)(
31431
31561
  getBacktestResultsPrefix(userName3, target.config)
31432
31562
  );
31433
31563
  const newBacktestKeys = backtestKeysAfter.filter((key2) => !backtestKeysBefore.has(key2)).sort();
31434
31564
  const backtestResultKey = newBacktestKeys[newBacktestKeys.length - 1] || backtestKeysAfter.sort().at(-1);
31435
31565
  if (backtestResultKey) {
31436
31566
  logResearch(`detected backtest result key ${backtestResultKey}`);
31437
- const backtestResult = await (0, import_redis16.getData)(backtestResultKey, null);
31567
+ const backtestResult = await (0, import_redis17.getData)(backtestResultKey, null);
31438
31568
  run.artifacts.backtestResultKey = backtestResultKey;
31439
31569
  run.artifacts.backtestResult = backtestResult ? {
31440
31570
  finishedAt: backtestResult.finishedAt,
@@ -32134,8 +32264,8 @@ var init_dataset2 = __esm({
32134
32264
  for (const inputPath of variant.files) {
32135
32265
  const filePath = import_node_path22.default.resolve(inputPath);
32136
32266
  const input = (0, import_node_fs8.createReadStream)(filePath);
32137
- const hash3 = (0, import_node_crypto17.createHash)("sha256");
32138
- input.on("data", (chunk) => hash3.update(chunk));
32267
+ const hash2 = (0, import_node_crypto17.createHash)("sha256");
32268
+ input.on("data", (chunk) => hash2.update(chunk));
32139
32269
  const lines = import_node_readline3.default.createInterface({ input, crlfDelay: Infinity });
32140
32270
  const fileTrades = [];
32141
32271
  let lineNumber = 0;
@@ -32185,7 +32315,7 @@ var init_dataset2 = __esm({
32185
32315
  trades.push(trade);
32186
32316
  fileTrades.push(trade);
32187
32317
  }
32188
- const fileSha2562 = hash3.digest("hex");
32318
+ const fileSha2562 = hash2.digest("hex");
32189
32319
  for (const trade of fileTrades) trade.sourceSha256 = fileSha2562;
32190
32320
  sources.push({
32191
32321
  path: filePath,
@@ -33744,55 +33874,6 @@ var init_specification = __esm({
33744
33874
  }
33745
33875
  });
33746
33876
 
33747
- // src/lib/researchMetricSnapshot.ts
33748
- var import_node_crypto19, import_node_zlib2, MAX_BYTES, hash2, validatePermanentResearchMetrics, encodeResearchMetricSnapshot, decodeResearchMetricSnapshot;
33749
- var init_researchMetricSnapshot = __esm({
33750
- "src/lib/researchMetricSnapshot.ts"() {
33751
- "use strict";
33752
- import_node_crypto19 = require("crypto");
33753
- import_node_zlib2 = require("zlib");
33754
- MAX_BYTES = 256 * 1024 * 1024;
33755
- hash2 = (bytes) => (0, import_node_crypto19.createHash)("sha256").update(bytes).digest("hex");
33756
- validatePermanentResearchMetrics = (value) => {
33757
- if (!value || typeof value !== "object") return;
33758
- for (const [key2, child] of Object.entries(value)) {
33759
- if (["matchedPairs", "tradeRows", "allProjectedLeaves"].includes(key2) && Array.isArray(child) && child.length)
33760
- throw new Error(`Temporary payload ${key2} is not a permanent metric`);
33761
- if (key2 === "trades" && Array.isArray(child) && child.some(
33762
- (row) => row && typeof row === "object" && ("signalId" in row || "entryTimestamp" in row)
33763
- ))
33764
- throw new Error("Temporary trade records are not permanent metrics");
33765
- validatePermanentResearchMetrics(child);
33766
- }
33767
- };
33768
- encodeResearchMetricSnapshot = (metrics) => {
33769
- validatePermanentResearchMetrics(metrics);
33770
- const bytes = Buffer.from(JSON.stringify(metrics));
33771
- if (bytes.length > MAX_BYTES)
33772
- throw new Error("Metric snapshot exceeds decoded size limit");
33773
- return {
33774
- schema: "tradejs-metric-snapshot/v1",
33775
- encoding: "gzip+base64",
33776
- decodedBytes: bytes.length,
33777
- sha256: hash2(bytes),
33778
- payload: (0, import_node_zlib2.gzipSync)(bytes, { level: 9 }).toString("base64")
33779
- };
33780
- };
33781
- decodeResearchMetricSnapshot = (snapshot) => {
33782
- 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")
33783
- throw new Error("Invalid metric snapshot envelope");
33784
- const bytes = (0, import_node_zlib2.gunzipSync)(Buffer.from(snapshot.payload, "base64"), {
33785
- maxOutputLength: snapshot.decodedBytes
33786
- });
33787
- if (bytes.length !== snapshot.decodedBytes || hash2(bytes) !== snapshot.sha256)
33788
- throw new Error("Metric snapshot checksum or size mismatch");
33789
- const metrics = JSON.parse(bytes.toString("utf8"));
33790
- validatePermanentResearchMetrics(metrics);
33791
- return metrics;
33792
- };
33793
- }
33794
- });
33795
-
33796
33877
  // src/lib/strategyResearch/io.ts
33797
33878
  var io_exports = {};
33798
33879
  __export(io_exports, {
@@ -33805,14 +33886,14 @@ __export(io_exports, {
33805
33886
  verifyResearchState: () => verifyResearchState,
33806
33887
  withResearchLock: () => withResearchLock
33807
33888
  });
33808
- var import_promises31, import_node_path25, import_node_os3, import_node_crypto20, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
33889
+ var import_promises31, import_node_path25, import_node_os3, import_node_crypto19, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
33809
33890
  var init_io2 = __esm({
33810
33891
  "src/lib/strategyResearch/io.ts"() {
33811
33892
  "use strict";
33812
33893
  import_promises31 = __toESM(require("fs/promises"));
33813
33894
  import_node_path25 = __toESM(require("path"));
33814
33895
  import_node_os3 = __toESM(require("os"));
33815
- import_node_crypto20 = require("crypto");
33896
+ import_node_crypto19 = require("crypto");
33816
33897
  init_io();
33817
33898
  researchDirectory = (projectRoot18, spec) => import_node_path25.default.join(projectRoot18, "data/research/strategy", spec.core.researchId);
33818
33899
  readJson = async (file) => JSON.parse(await import_promises31.default.readFile(file, "utf8"));
@@ -33841,7 +33922,7 @@ var init_io2 = __esm({
33841
33922
  "data/research/strategy/.lock"
33842
33923
  );
33843
33924
  await import_promises31.default.mkdir(import_node_path25.default.dirname(file), { recursive: true });
33844
- const token = (0, import_node_crypto20.randomUUID)();
33925
+ const token = (0, import_node_crypto19.randomUUID)();
33845
33926
  const acquire = () => import_promises31.default.writeFile(
33846
33927
  file,
33847
33928
  JSON.stringify({ pid: process.pid, host: import_node_os3.default.hostname(), token }),
@@ -33937,15 +34018,15 @@ var init_io2 = __esm({
33937
34018
  await writeJsonAtomic(file, state);
33938
34019
  return state;
33939
34020
  };
33940
- isRetainedDeletion = async (directory, file, hash3) => {
34021
+ isRetainedDeletion = async (directory, file, hash2) => {
33941
34022
  try {
33942
34023
  const inventory = await readJson(import_node_path25.default.join(directory, "retention.json"));
33943
34024
  const index = inventory.entries.findIndex(
33944
- (entry) => entry.path === file && entry.sha256 === hash3
34025
+ (entry) => entry.path === file && entry.sha256 === hash2
33945
34026
  );
33946
34027
  if (index < 0) return false;
33947
34028
  const receipt = await readJson(import_node_path25.default.join(directory, "retention", `${index}.json`));
33948
- return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 === hash3;
34029
+ return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 === hash2;
33949
34030
  } catch (error) {
33950
34031
  if (error.code === "ENOENT") return false;
33951
34032
  throw error;
@@ -35168,14 +35249,14 @@ var init_evidenceRetention = __esm({
35168
35249
  });
35169
35250
 
35170
35251
  // src/lib/strategyRelease/researchRetention.ts
35171
- var import_promises32, import_node_path27, import_node_crypto21, import_strategyReleaseEvidence2, SHA256_RE2, mapFiles, fileSha256, inside, applyResearchRetention;
35252
+ var import_promises32, import_researchMetricSnapshot, import_node_path27, import_node_crypto20, import_strategyReleaseEvidence2, SHA256_RE2, mapFiles, fileSha256, inside, applyResearchRetention;
35172
35253
  var init_researchRetention = __esm({
35173
35254
  "src/lib/strategyRelease/researchRetention.ts"() {
35174
35255
  "use strict";
35175
35256
  import_promises32 = __toESM(require("fs/promises"));
35176
- init_researchMetricSnapshot();
35257
+ import_researchMetricSnapshot = require("@tradejs/infra/researchMetricSnapshot");
35177
35258
  import_node_path27 = __toESM(require("path"));
35178
- import_node_crypto21 = require("crypto");
35259
+ import_node_crypto20 = require("crypto");
35179
35260
  import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
35180
35261
  init_researchFileConsumers();
35181
35262
  init_evidenceRetention();
@@ -35195,7 +35276,7 @@ var init_researchRetention = __esm({
35195
35276
  if (worker.status === "rejected") throw worker.reason;
35196
35277
  return results2;
35197
35278
  };
35198
- fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto21.createHash)("sha256").update(await import_promises32.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(file);
35279
+ fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto20.createHash)("sha256").update(await import_promises32.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(file);
35199
35280
  inside = (root, file) => {
35200
35281
  const relative = import_node_path27.default.relative(root, file);
35201
35282
  return relative !== "" && !relative.startsWith(`..${import_node_path27.default.sep}`) && relative !== ".." && !import_node_path27.default.isAbsolute(relative);
@@ -35258,7 +35339,7 @@ var init_researchRetention = __esm({
35258
35339
  throw new Error(
35259
35340
  "Complete v2 note needs one verified metric snapshot"
35260
35341
  );
35261
- decodeResearchMetricSnapshot(JSON.parse(blocks[0][1]));
35342
+ (0, import_researchMetricSnapshot.decodeResearchMetricSnapshot)(JSON.parse(blocks[0][1]));
35262
35343
  }
35263
35344
  } finally {
35264
35345
  await handle.close();
@@ -35382,11 +35463,11 @@ var init_retention = __esm({
35382
35463
  }
35383
35464
  const files = /* @__PURE__ */ new Map();
35384
35465
  for (const stage of Object.values(state.stages)) {
35385
- for (const [relative, hash3] of Object.entries(stage.artifacts)) {
35466
+ for (const [relative, hash2] of Object.entries(stage.artifacts)) {
35386
35467
  const file = await boundResearchPath(directory, relative);
35387
35468
  if (relative.endsWith("/result.json")) {
35388
35469
  const result = await readJson(file);
35389
- if (result?.dataset) files.set(file, hash3);
35470
+ if (result?.dataset) files.set(file, hash2);
35390
35471
  }
35391
35472
  if (relative.endsWith("/sources.json") || relative.endsWith("/payloads.json")) {
35392
35473
  const sources = await readJson(file);
@@ -35403,13 +35484,13 @@ var init_retention = __esm({
35403
35484
  }
35404
35485
  }
35405
35486
  const entries = [];
35406
- for (const [file, hash3] of files) {
35487
+ for (const [file, hash2] of files) {
35407
35488
  const stat = await import_promises33.default.stat(file);
35408
35489
  entries.push({
35409
35490
  path: file,
35410
35491
  kind: "research_payload",
35411
35492
  researchId: spec.core.researchId,
35412
- sha256: hash3,
35493
+ sha256: hash2,
35413
35494
  bytes: stat.size,
35414
35495
  createdAt: stat.birthtimeMs,
35415
35496
  verified: true,
@@ -35493,12 +35574,12 @@ var init_retention = __esm({
35493
35574
  });
35494
35575
 
35495
35576
  // src/lib/strategyResearch/orchestrator.ts
35496
- var import_promises34, import_node_path29, runStrategyResearch;
35577
+ var import_promises34, import_researchMetricSnapshot2, import_node_path29, runStrategyResearch;
35497
35578
  var init_orchestrator2 = __esm({
35498
35579
  "src/lib/strategyResearch/orchestrator.ts"() {
35499
35580
  "use strict";
35500
35581
  import_promises34 = __toESM(require("fs/promises"));
35501
- init_researchMetricSnapshot();
35582
+ import_researchMetricSnapshot2 = require("@tradejs/infra/researchMetricSnapshot");
35502
35583
  import_node_path29 = __toESM(require("path"));
35503
35584
  init_metrics();
35504
35585
  init_io();
@@ -35689,7 +35770,7 @@ var init_orchestrator2 = __esm({
35689
35770
  });
35690
35771
  let partitionControl;
35691
35772
  if (spec.testSince === 0) {
35692
- const control2 = spec.core.variants.find(
35773
+ const control = spec.core.variants.find(
35693
35774
  (variant) => variant.role === "control"
35694
35775
  );
35695
35776
  partitionControl = await stage(
@@ -35706,7 +35787,7 @@ var init_orchestrator2 = __esm({
35706
35787
  }
35707
35788
  return backend.runVariant(
35708
35789
  spec,
35709
- control2,
35790
+ control,
35710
35791
  folder,
35711
35792
  async (runId) => writeJsonAtomic(import_node_path29.default.join(folder, "native-run.json"), {
35712
35793
  runId
@@ -35728,9 +35809,6 @@ var init_orchestrator2 = __esm({
35728
35809
  let frozenSelection;
35729
35810
  const raw = {};
35730
35811
  const discovered = [];
35731
- const control = spec.core.variants.find(
35732
- (variant) => variant.role === "control"
35733
- );
35734
35812
  const currentPolicy = {
35735
35813
  schema: "tradejs-research-entry-policy/v1",
35736
35814
  strategy: spec.core.strategy,
@@ -36206,7 +36284,7 @@ ${JSON.stringify(spec, null, 2)}
36206
36284
  ## Metrics snapshot (machine-readable)
36207
36285
 
36208
36286
  \`\`\`json
36209
- ${JSON.stringify(encodeResearchMetricSnapshot(compact))}
36287
+ ${JSON.stringify((0, import_researchMetricSnapshot2.encodeResearchMetricSnapshot)(compact))}
36210
36288
  \`\`\`
36211
36289
 
36212
36290
  ## Reported metrics
@@ -36324,7 +36402,7 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
36324
36402
  });
36325
36403
 
36326
36404
  // src/lib/strategyResearch/native.ts
36327
- var import_promises35, import_node_fs9, import_node_path30, import_node_os4, import_node_readline4, import_node_child_process8, import_node_module3, import_redis17, import_ai9, import_backtest7, import_registry5, import_connectors14, import_data9, import_coreResearch2, import_jev6, validateResearchJevTraining, nativeConfig, runResearchCommand, createNativeStrategyResearchBackend;
36405
+ var import_promises35, import_node_fs9, import_node_path30, import_node_os4, import_node_readline4, import_node_child_process8, import_node_module3, import_redis18, import_ai9, import_backtest7, import_registry5, import_connectors14, import_data9, import_coreResearch2, import_jev6, validateResearchJevTraining, nativeConfig, runResearchCommand, createNativeStrategyResearchBackend;
36328
36406
  var init_native = __esm({
36329
36407
  "src/lib/strategyResearch/native.ts"() {
36330
36408
  "use strict";
@@ -36335,7 +36413,7 @@ var init_native = __esm({
36335
36413
  import_node_readline4 = __toESM(require("readline"));
36336
36414
  import_node_child_process8 = require("child_process");
36337
36415
  import_node_module3 = require("module");
36338
- import_redis17 = require("@tradejs/infra/redis");
36416
+ import_redis18 = require("@tradejs/infra/redis");
36339
36417
  import_ai9 = require("@tradejs/node/ai");
36340
36418
  import_backtest7 = require("@tradejs/node/backtest");
36341
36419
  import_registry5 = require("@tradejs/node/registry");
@@ -36799,11 +36877,11 @@ var init_native = __esm({
36799
36877
  const grid = Object.fromEntries(
36800
36878
  Object.entries(config2).map(([key3, value]) => [key3, [value]])
36801
36879
  );
36802
- const key2 = import_redis17.redisKeys.backtestConfig("root", configName);
36803
- const existing = await (0, import_redis17.getData)(key2, null);
36880
+ const key2 = import_redis18.redisKeys.backtestConfig("root", configName);
36881
+ const existing = await (0, import_redis18.getData)(key2, null);
36804
36882
  if (existing != null && sha256Json(existing) !== sha256Json(grid))
36805
36883
  throw new Error(`Frozen research config changed: ${configName}`);
36806
- if (existing == null) await (0, import_redis17.setData)(key2, grid, { expire: 0 });
36884
+ if (existing == null) await (0, import_redis18.setData)(key2, grid, { expire: 0 });
36807
36885
  let runId = previousRunId ?? "";
36808
36886
  const common = {
36809
36887
  executable: process.execPath,
@@ -37237,7 +37315,7 @@ var strategyResearch_exports = {};
37237
37315
  __export(strategyResearch_exports, {
37238
37316
  main: () => main37
37239
37317
  });
37240
- var import_promises36, import_node_path31, import_redis18, usage, main37;
37318
+ var import_promises36, import_node_path31, import_redis19, usage, main37;
37241
37319
  var init_strategyResearch2 = __esm({
37242
37320
  "src/scripts/strategyResearch.ts"() {
37243
37321
  "use strict";
@@ -37247,7 +37325,7 @@ var init_strategyResearch2 = __esm({
37247
37325
  init_researchRoots();
37248
37326
  init_io();
37249
37327
  init_orchestrator();
37250
- import_redis18 = require("@tradejs/infra/redis");
37328
+ import_redis19 = require("@tradejs/infra/redis");
37251
37329
  init_io2();
37252
37330
  usage = `Usage:
37253
37331
  tradejs research:strategy init --coreSpec <core-spec.json> --out <workflow.json>
@@ -37335,8 +37413,8 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
37335
37413
  throw new Error(
37336
37414
  "Every config must belong to the selected strategy"
37337
37415
  );
37338
- const grid = await (0, import_redis18.getData)(
37339
- import_redis18.redisKeys.backtestConfig("root", configName),
37416
+ const grid = await (0, import_redis19.getData)(
37417
+ import_redis19.redisKeys.backtestConfig("root", configName),
37340
37418
  null
37341
37419
  );
37342
37420
  if (!grid || typeof grid !== "object" || Array.isArray(grid) || !Object.keys(grid).length)
@@ -37476,7 +37554,7 @@ __export(results_exports, {
37476
37554
  main: () => main38,
37477
37555
  results: () => results
37478
37556
  });
37479
- var import_args26, import_chalk42, import_connectors15, import_cli11, import_redis19, ListIt4, flags24, MIN_PROFIT, MIN_WIN_RATE, MIN_ORDERS_PER_MONTH, createListIt4, formatPercent4, getMonthlyReturn, toStrategyResultEntry, toStrategyResults, getTestConfigs, buildBestResults, getSavedProfitsBySymbol, getCoverageRow, results, main38;
37557
+ var import_args26, import_chalk42, import_connectors15, import_cli11, import_redis20, ListIt4, flags24, MIN_PROFIT, MIN_WIN_RATE, MIN_ORDERS_PER_MONTH, createListIt4, formatPercent4, getMonthlyReturn, toStrategyResultEntry, toStrategyResults, getTestConfigs, buildBestResults, getSavedProfitsBySymbol, getCoverageRow, results, main38;
37480
37558
  var init_results = __esm({
37481
37559
  "src/scripts/results.ts"() {
37482
37560
  "use strict";
@@ -37484,7 +37562,7 @@ var init_results = __esm({
37484
37562
  import_chalk42 = __toESM(require("chalk"));
37485
37563
  import_connectors15 = require("@tradejs/connectors");
37486
37564
  import_cli11 = require("@tradejs/node/cli");
37487
- import_redis19 = require("@tradejs/infra/redis");
37565
+ import_redis20 = require("@tradejs/infra/redis");
37488
37566
  ListIt4 = require("list-it");
37489
37567
  import_args26.default.example(
37490
37568
  "yarn results --strategy TrendLine --coverage",
@@ -37524,8 +37602,8 @@ var init_results = __esm({
37524
37602
  [...rows].map((row) => [row.symbol, toStrategyResultEntry(row)])
37525
37603
  );
37526
37604
  getTestConfigs = async (userName3) => {
37527
- const testSummariesKey = typeof import_redis19.redisKeys.testSummaries === "function" ? import_redis19.redisKeys.testSummaries(userName3) : null;
37528
- const indexedItems = testSummariesKey ? await (0, import_redis19.getData)(testSummariesKey, null) : null;
37605
+ const testSummariesKey = typeof import_redis20.redisKeys.testSummaries === "function" ? import_redis20.redisKeys.testSummaries(userName3) : null;
37606
+ const indexedItems = testSummariesKey ? await (0, import_redis20.getData)(testSummariesKey, null) : null;
37529
37607
  if (Array.isArray(indexedItems) && indexedItems.length) {
37530
37608
  return indexedItems.map((item) => {
37531
37609
  const testName = typeof item?.value === "string" ? item.value : null;
@@ -37536,8 +37614,8 @@ var init_results = __esm({
37536
37614
  return { strategyName, testName };
37537
37615
  }).filter(Boolean);
37538
37616
  }
37539
- const testsPrefix = import_redis19.redisKeys.tests(userName3);
37540
- const keys = await (0, import_redis19.getKeys)(testsPrefix);
37617
+ const testsPrefix = import_redis20.redisKeys.tests(userName3);
37618
+ const keys = await (0, import_redis20.getKeys)(testsPrefix);
37541
37619
  const configKeys = keys.filter((key2) => key2.endsWith(":config"));
37542
37620
  return configKeys.map((key2) => {
37543
37621
  const parts = key2.split(":");
@@ -37556,15 +37634,15 @@ var init_results = __esm({
37556
37634
  testName,
37557
37635
  strategyName: strategyFromIndex
37558
37636
  } of testConfigs) {
37559
- const config2 = await (0, import_redis19.getData)(
37560
- import_redis19.redisKeys.testConfig(userName3, strategyFromIndex, testName),
37637
+ const config2 = await (0, import_redis20.getData)(
37638
+ import_redis20.redisKeys.testConfig(userName3, strategyFromIndex, testName),
37561
37639
  null
37562
37640
  );
37563
37641
  if (!config2 || config2.strategyName !== strategyName) {
37564
37642
  continue;
37565
37643
  }
37566
- const stat = await (0, import_redis19.getData)(
37567
- import_redis19.redisKeys.testStat(userName3, strategyFromIndex, testName),
37644
+ const stat = await (0, import_redis20.getData)(
37645
+ import_redis20.redisKeys.testStat(userName3, strategyFromIndex, testName),
37568
37646
  null
37569
37647
  );
37570
37648
  if (!stat) {
@@ -37609,8 +37687,8 @@ var init_results = __esm({
37609
37687
  return savedProfitBySymbol;
37610
37688
  };
37611
37689
  getCoverageRow = async (strategyName, userName3, goodSymbols) => {
37612
- const currentResults = await (0, import_redis19.getData)(
37613
- import_redis19.redisKeys.strategyResults(userName3, strategyName),
37690
+ const currentResults = await (0, import_redis20.getData)(
37691
+ import_redis20.redisKeys.strategyResults(userName3, strategyName),
37614
37692
  {}
37615
37693
  );
37616
37694
  const existingSymbols = new Set(Object.keys(currentResults));
@@ -37644,8 +37722,8 @@ var init_results = __esm({
37644
37722
  const strategyName = flags24.strategy;
37645
37723
  const userName3 = flags24.user;
37646
37724
  if (flags24.clear) {
37647
- const cleared = await (0, import_redis19.delKey)(
37648
- import_redis19.redisKeys.strategyResults(userName3, strategyName)
37725
+ const cleared = await (0, import_redis20.delKey)(
37726
+ import_redis20.redisKeys.strategyResults(userName3, strategyName)
37649
37727
  );
37650
37728
  console.log(
37651
37729
  cleared ? import_chalk42.default.green(`Cleared results:${strategyName}`) : import_chalk42.default.yellow(`No results to clear for ${strategyName}`)
@@ -37693,8 +37771,8 @@ var init_results = __esm({
37693
37771
  console.log(import_chalk42.default.yellow("No good results to merge."));
37694
37772
  process.exit(0);
37695
37773
  }
37696
- const current = await (0, import_redis19.getData)(
37697
- import_redis19.redisKeys.strategyResults(userName3, strategyName),
37774
+ const current = await (0, import_redis20.getData)(
37775
+ import_redis20.redisKeys.strategyResults(userName3, strategyName),
37698
37776
  {}
37699
37777
  );
37700
37778
  const savedProfitBySymbol = await getSavedProfitsBySymbol(current);
@@ -37716,7 +37794,7 @@ var init_results = __esm({
37716
37794
  ...current,
37717
37795
  ...toStrategyResults(updates)
37718
37796
  };
37719
- await (0, import_redis19.setData)(import_redis19.redisKeys.strategyResults(userName3, strategyName), merged, {
37797
+ await (0, import_redis20.setData)(import_redis20.redisKeys.strategyResults(userName3, strategyName), merged, {
37720
37798
  expire: 0
37721
37799
  });
37722
37800
  if (flags24.verbose) {
@@ -37757,8 +37835,8 @@ var init_results = __esm({
37757
37835
  );
37758
37836
  process.exit(0);
37759
37837
  }
37760
- await (0, import_redis19.setData)(
37761
- import_redis19.redisKeys.strategyResults(userName3, strategyName),
37838
+ await (0, import_redis20.setData)(
37839
+ import_redis20.redisKeys.strategyResults(userName3, strategyName),
37762
37840
  resultsConfig,
37763
37841
  {
37764
37842
  expire: 0
@@ -37777,11 +37855,11 @@ var init_results = __esm({
37777
37855
  });
37778
37856
 
37779
37857
  // src/lib/runtimeDebugEvidence.ts
37780
- var import_redis20, RUNTIME_DEBUG_TIMEZONE, RUNTIME_DEBUG_TIMEZONE_LABEL, formatRuntimeDebugDateTime, getRuntimeDebugDateParts, formatRuntimeDebugIsoDayKey, buildRuntimeDebugEvaluationId, filterByStrategies, collectRuntimeDebugEvidence, buildRuntimeDebugReportPayload, buildRuntimeEvidenceReportPayload, buildRuntimeDebugReportAttachment;
37858
+ var import_redis21, RUNTIME_DEBUG_TIMEZONE, RUNTIME_DEBUG_TIMEZONE_LABEL, formatRuntimeDebugDateTime, getRuntimeDebugDateParts, formatRuntimeDebugIsoDayKey, buildRuntimeDebugEvaluationId, filterByStrategies, collectRuntimeDebugEvidence, buildRuntimeDebugReportPayload, buildRuntimeEvidenceReportPayload, buildRuntimeDebugReportAttachment;
37781
37859
  var init_runtimeDebugEvidence = __esm({
37782
37860
  "src/lib/runtimeDebugEvidence.ts"() {
37783
37861
  "use strict";
37784
- import_redis20 = require("@tradejs/infra/redis");
37862
+ import_redis21 = require("@tradejs/infra/redis");
37785
37863
  init_runtimeRedis();
37786
37864
  init_runtimeSignalsLoader();
37787
37865
  init_runtimeSignalsStorage();
@@ -37888,24 +37966,24 @@ var init_runtimeDebugEvidence = __esm({
37888
37966
  const tradeDayKey = (0, import_time5.getRuntimeStorageDayKey)(trade.entryTimestamp);
37889
37967
  const signalDayKey = signal != null ? (0, import_time5.getRuntimeStorageDayKey)(signal.timestamp) : tradeDayKey;
37890
37968
  const evaluationDayKey = knownEvaluation != null ? (0, import_time5.getRuntimeStorageDayKey)(knownEvaluation.timestamp) : signalDayKey;
37891
- const tradeKey = import_redis20.redisKeys.runtimeTrade(userName3, trade.orderId);
37892
- const tradeBucketKey = import_redis20.redisKeys.runtimeTradeBucket(
37969
+ const tradeKey = import_redis21.redisKeys.runtimeTrade(userName3, trade.orderId);
37970
+ const tradeBucketKey = import_redis21.redisKeys.runtimeTradeBucket(
37893
37971
  userName3,
37894
37972
  tradeDayKey
37895
37973
  );
37896
- const activeTradeKey = import_redis20.redisKeys.runtimeActiveTrade(
37974
+ const activeTradeKey = import_redis21.redisKeys.runtimeActiveTrade(
37897
37975
  userName3,
37898
37976
  trade.symbol,
37899
37977
  trade.deploymentId ?? trade.accountId
37900
37978
  );
37901
- const signalKey = trade.signalId != null ? import_redis20.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
37902
- const evaluationBucketKey = import_redis20.redisKeys.runtimeSignalEvaluationBucket(
37979
+ const signalKey = trade.signalId != null ? import_redis21.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
37980
+ const evaluationBucketKey = import_redis21.redisKeys.runtimeSignalEvaluationBucket(
37903
37981
  userName3,
37904
37982
  evaluationDayKey,
37905
37983
  knownEvaluation?.strategy ?? trade.strategy
37906
37984
  );
37907
37985
  const evaluationField = knownEvaluation?.evaluationId ?? evaluationId;
37908
- const evaluationKey = import_redis20.redisKeys.runtimeSignalEvaluation(
37986
+ const evaluationKey = import_redis21.redisKeys.runtimeSignalEvaluation(
37909
37987
  userName3,
37910
37988
  evaluationField
37911
37989
  );
@@ -37916,11 +37994,11 @@ var init_runtimeDebugEvidence = __esm({
37916
37994
  directEvaluationValue,
37917
37995
  bucketEvaluationValue
37918
37996
  ] = await Promise.all([
37919
- (0, import_redis20.getData)(tradeKey, null),
37920
- (0, import_redis20.getData)(activeTradeKey, null),
37921
- signalKey ? (0, import_redis20.getData)(signalKey, null) : Promise.resolve(null),
37922
- (0, import_redis20.getData)(evaluationKey, null),
37923
- knownEvaluation ? Promise.resolve(knownEvaluation) : (0, import_redis20.getHashJsonField)(
37997
+ (0, import_redis21.getData)(tradeKey, null),
37998
+ (0, import_redis21.getData)(activeTradeKey, null),
37999
+ signalKey ? (0, import_redis21.getData)(signalKey, null) : Promise.resolve(null),
38000
+ (0, import_redis21.getData)(evaluationKey, null),
38001
+ knownEvaluation ? Promise.resolve(knownEvaluation) : (0, import_redis21.getHashJsonField)(
37924
38002
  evaluationBucketKey,
37925
38003
  evaluationField,
37926
38004
  null
@@ -37977,12 +38055,12 @@ var init_runtimeDebugEvidence = __esm({
37977
38055
  dayKeys
37978
38056
  },
37979
38057
  redisPrefixes: {
37980
- runtimeTrades: import_redis20.redisKeys.runtimeTrades(userName3),
37981
- runtimeTradeBuckets: import_redis20.redisKeys.runtimeTradeBuckets(userName3),
37982
- runtimeActiveTrades: import_redis20.redisKeys.runtimeActiveTrades(userName3),
37983
- runtimeSignals: import_redis20.redisKeys.runtimeSignalBuckets(userName3),
37984
- runtimeSignalEvaluations: import_redis20.redisKeys.runtimeSignalEvaluationBuckets(userName3),
37985
- runtimeSignalEvaluationStats: import_redis20.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3)
38058
+ runtimeTrades: import_redis21.redisKeys.runtimeTrades(userName3),
38059
+ runtimeTradeBuckets: import_redis21.redisKeys.runtimeTradeBuckets(userName3),
38060
+ runtimeActiveTrades: import_redis21.redisKeys.runtimeActiveTrades(userName3),
38061
+ runtimeSignals: import_redis21.redisKeys.runtimeSignalBuckets(userName3),
38062
+ runtimeSignalEvaluations: import_redis21.redisKeys.runtimeSignalEvaluationBuckets(userName3),
38063
+ runtimeSignalEvaluationStats: import_redis21.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3)
37986
38064
  },
37987
38065
  counts: {
37988
38066
  trades: trades.length,
@@ -37993,18 +38071,18 @@ var init_runtimeDebugEvidence = __esm({
37993
38071
  },
37994
38072
  trades: debugTrades,
37995
38073
  signals: signals2.map((signal) => ({
37996
- redisKey: import_redis20.redisKeys.storeSignal(signal.symbol, signal.signalId),
38074
+ redisKey: import_redis21.redisKeys.storeSignal(signal.symbol, signal.signalId),
37997
38075
  signal
37998
38076
  })),
37999
38077
  evaluations: reportEvaluations.map((evaluation) => ({
38000
38078
  redisDebug: {
38001
- key: import_redis20.redisKeys.runtimeSignalEvaluationBucket(
38079
+ key: import_redis21.redisKeys.runtimeSignalEvaluationBucket(
38002
38080
  userName3,
38003
38081
  (0, import_time5.getRuntimeStorageDayKey)(evaluation.timestamp),
38004
38082
  evaluation.strategy
38005
38083
  ),
38006
38084
  field: evaluation.evaluationId,
38007
- directKey: import_redis20.redisKeys.runtimeSignalEvaluation(
38085
+ directKey: import_redis21.redisKeys.runtimeSignalEvaluation(
38008
38086
  userName3,
38009
38087
  evaluation.evaluationId
38010
38088
  )
@@ -38069,7 +38147,7 @@ __export(replayRuntimeEvidence_exports, {
38069
38147
  replayRuntimeEvidence: () => replayRuntimeEvidence,
38070
38148
  summarizeReplayComparison: () => summarizeReplayComparison
38071
38149
  });
38072
- var import_promises37, import_node_path32, import_args27, import_chalk43, import_redis21, toEpochMs2, resolveWindow, parseStrategyFilter, asRecord5, asArray2, sum, groupCount, compactMatched, resolveItemStrategy, summarizeReplayComparison, loadReplayResult, getReplayStrategies, loadRuntimePayload, replayRuntimeEvidence, main39;
38150
+ var import_promises37, import_node_path32, import_args27, import_chalk43, import_redis22, toEpochMs2, resolveWindow, parseStrategyFilter, asRecord5, asArray2, sum, groupCount, compactMatched, resolveItemStrategy, summarizeReplayComparison, loadReplayResult, getReplayStrategies, loadRuntimePayload, replayRuntimeEvidence, main39;
38073
38151
  var init_replayRuntimeEvidence = __esm({
38074
38152
  "src/scripts/replayRuntimeEvidence.ts"() {
38075
38153
  "use strict";
@@ -38079,7 +38157,7 @@ var init_replayRuntimeEvidence = __esm({
38079
38157
  import_node_path32 = __toESM(require("path"));
38080
38158
  import_args27 = __toESM(require("args"));
38081
38159
  import_chalk43 = __toESM(require("chalk"));
38082
- import_redis21 = require("@tradejs/infra/redis");
38160
+ import_redis22 = require("@tradejs/infra/redis");
38083
38161
  init_runtimeDebugEvidence();
38084
38162
  init_support2();
38085
38163
  import_args27.default.option(["u", "user"], "Use user config", "root");
@@ -38299,18 +38377,18 @@ var init_replayRuntimeEvidence = __esm({
38299
38377
  return {
38300
38378
  key: replayKey,
38301
38379
  availableKeys: void 0,
38302
- value: await (0, import_redis21.getData)(replayKey, null)
38380
+ value: await (0, import_redis22.getData)(replayKey, null)
38303
38381
  };
38304
38382
  }
38305
- const prefix = import_redis21.redisKeys.backtestResults(userName3, REPLAY_RESULTS_CONFIG, "");
38306
- const keys = (await (0, import_redis21.getKeys)(prefix)).sort(
38383
+ const prefix = import_redis22.redisKeys.backtestResults(userName3, REPLAY_RESULTS_CONFIG, "");
38384
+ const keys = (await (0, import_redis22.getKeys)(prefix)).sort(
38307
38385
  (left, right) => left.localeCompare(right)
38308
38386
  );
38309
38387
  const key2 = keys[keys.length - 1] ?? null;
38310
38388
  return {
38311
38389
  key: key2,
38312
38390
  availableKeys: keys.slice(-10),
38313
- value: key2 ? await (0, import_redis21.getData)(key2, null) : null
38391
+ value: key2 ? await (0, import_redis22.getData)(key2, null) : null
38314
38392
  };
38315
38393
  };
38316
38394
  getReplayStrategies = (replayValue) => {
@@ -39945,13 +40023,13 @@ var init_runtimeEvidenceSync = __esm({
39945
40023
  });
39946
40024
 
39947
40025
  // src/lib/runtimeFeedbackProcess.ts
39948
- var import_promises40, import_node_path37, import_node_crypto22, import_diagnostics2, processRuntimeFeedbackPair;
40026
+ var import_promises40, import_node_path37, import_node_crypto21, import_diagnostics2, processRuntimeFeedbackPair;
39949
40027
  var init_runtimeFeedbackProcess = __esm({
39950
40028
  "src/lib/runtimeFeedbackProcess.ts"() {
39951
40029
  "use strict";
39952
40030
  import_promises40 = __toESM(require("fs/promises"));
39953
40031
  import_node_path37 = __toESM(require("path"));
39954
- import_node_crypto22 = require("crypto");
40032
+ import_node_crypto21 = require("crypto");
39955
40033
  import_diagnostics2 = require("@tradejs/node/diagnostics");
39956
40034
  init_executionCalibration();
39957
40035
  init_runtimeScorecard();
@@ -40010,7 +40088,7 @@ var init_runtimeFeedbackProcess = __esm({
40010
40088
  if (historyDir)
40011
40089
  for (const directory of await (0, import_diagnostics2.discoverRuntimeEvidenceBundles)(historyDir))
40012
40090
  history.push((await (0, import_diagnostics2.verifyRuntimeEvidenceBundle)(directory)).artifact);
40013
- const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "") + "-" + (0, import_node_crypto22.randomUUID)();
40091
+ const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "") + "-" + (0, import_node_crypto21.randomUUID)();
40014
40092
  const runDir = import_node_path37.default.join(outputRoot, artifactId, runId);
40015
40093
  await import_promises40.default.mkdir(runDir, { recursive: true });
40016
40094
  const calibration = buildExecutionCalibrationReport({
@@ -40268,11 +40346,11 @@ var init_runtimeFeedbackSync2 = __esm({
40268
40346
  });
40269
40347
 
40270
40348
  // src/lib/runtimeEvidenceCompositionSnapshots.ts
40271
- var import_node_crypto23, import_promises42, import_node_path41, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord2, sha256, safeSegment4, isExistingDestinationError3, parseManifest, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
40349
+ var import_node_crypto22, import_promises42, import_node_path41, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord2, sha256, safeSegment4, isExistingDestinationError3, parseManifest, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
40272
40350
  var init_runtimeEvidenceCompositionSnapshots = __esm({
40273
40351
  "src/lib/runtimeEvidenceCompositionSnapshots.ts"() {
40274
40352
  "use strict";
40275
- import_node_crypto23 = require("crypto");
40353
+ import_node_crypto22 = require("crypto");
40276
40354
  import_promises42 = __toESM(require("fs/promises"));
40277
40355
  import_node_path41 = __toESM(require("path"));
40278
40356
  init_runtimeEvidenceDeployment();
@@ -40295,7 +40373,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
40295
40373
  };
40296
40374
  };
40297
40375
  isRecord2 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
40298
- sha256 = (value) => (0, import_node_crypto23.createHash)("sha256").update(value).digest("hex");
40376
+ sha256 = (value) => (0, import_node_crypto22.createHash)("sha256").update(value).digest("hex");
40299
40377
  safeSegment4 = (value, label) => {
40300
40378
  const normalized = value.trim();
40301
40379
  if (!normalized || !/^[a-zA-Z0-9._:-]+$/.test(normalized)) {
@@ -40387,7 +40465,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
40387
40465
  const temporaryDir = import_node_path41.default.join(
40388
40466
  evidenceRoot,
40389
40467
  "incoming",
40390
- `snapshot-${compositionId}.tmp-${(0, import_node_crypto23.randomUUID)()}`
40468
+ `snapshot-${compositionId}.tmp-${(0, import_node_crypto22.randomUUID)()}`
40391
40469
  );
40392
40470
  await import_promises42.default.mkdir(temporaryDir, { recursive: true });
40393
40471
  try {
@@ -41354,11 +41432,11 @@ async function collectReleaseEvidenceReferences(references) {
41354
41432
  })
41355
41433
  );
41356
41434
  }
41357
- var import_node_crypto24, import_promises44, import_node_path44, import_types9, import_strategyReleaseEvidence3, SHA256_RE3, LINEAGE_FINGERPRINT_RE, STRATEGY_REVISION_RE, DEPLOYMENT_COMPOSITION_ID_RE, REQUIRED_LONG_WINDOWS, REQUIRED_DIAGNOSTIC_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_EVENTS, safeSegment5, compactTimestamp, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber7, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
41435
+ var import_node_crypto23, import_promises44, import_node_path44, import_types9, import_strategyReleaseEvidence3, SHA256_RE3, LINEAGE_FINGERPRINT_RE, STRATEGY_REVISION_RE, DEPLOYMENT_COMPOSITION_ID_RE, REQUIRED_LONG_WINDOWS, REQUIRED_DIAGNOSTIC_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_EVENTS, safeSegment5, compactTimestamp, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber7, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
41358
41436
  var init_strategyRelease = __esm({
41359
41437
  "src/lib/strategyRelease.ts"() {
41360
41438
  "use strict";
41361
- import_node_crypto24 = require("crypto");
41439
+ import_node_crypto23 = require("crypto");
41362
41440
  import_promises44 = __toESM(require("fs/promises"));
41363
41441
  import_node_path44 = __toESM(require("path"));
41364
41442
  import_types9 = require("@tradejs/types");
@@ -42376,7 +42454,7 @@ var init_strategyRelease = __esm({
42376
42454
  const artifactHashes = manifest.artifactHashes != null && typeof manifest.artifactHashes === "object" && !Array.isArray(manifest.artifactHashes) ? manifest.artifactHashes : null;
42377
42455
  const parsedSpec = JSON.parse(specBytes.toString("utf8"));
42378
42456
  assert3(
42379
- manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto24.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
42457
+ manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto23.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
42380
42458
  "core result is not bound by its completed core research manifest"
42381
42459
  );
42382
42460
  for (const [relativePath, expectedSha256] of Object.entries(
@@ -42408,12 +42486,12 @@ __export(runtimeScorecard_exports, {
42408
42486
  main: () => main46,
42409
42487
  runtimeScorecard: () => runtimeScorecard
42410
42488
  });
42411
- var import_promises45, import_node_crypto25, import_node_path45, import_args34, import_chalk49, flags31, projectRoot14, resolveOptionalPath, readJson2, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main46;
42489
+ var import_promises45, import_node_crypto24, import_node_path45, import_args34, import_chalk49, flags31, projectRoot14, resolveOptionalPath, readJson2, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main46;
42412
42490
  var init_runtimeScorecard2 = __esm({
42413
42491
  "src/scripts/runtimeScorecard.ts"() {
42414
42492
  "use strict";
42415
42493
  import_promises45 = __toESM(require("fs/promises"));
42416
- import_node_crypto25 = require("crypto");
42494
+ import_node_crypto24 = require("crypto");
42417
42495
  import_node_path45 = __toESM(require("path"));
42418
42496
  import_args34 = __toESM(require("args"));
42419
42497
  import_chalk49 = __toESM(require("chalk"));
@@ -42492,7 +42570,7 @@ var init_runtimeScorecard2 = __esm({
42492
42570
  throw new Error(`${label} must be a ${expected} artifact`);
42493
42571
  }
42494
42572
  };
42495
- sha256File2 = async (filePath) => (0, import_node_crypto25.createHash)("sha256").update(await import_promises45.default.readFile(filePath)).digest("hex");
42573
+ sha256File2 = async (filePath) => (0, import_node_crypto24.createHash)("sha256").update(await import_promises45.default.readFile(filePath)).digest("hex");
42496
42574
  loadHistoryArtifacts = async (historyDir) => {
42497
42575
  if (!historyDir) return [];
42498
42576
  const bundleDirs = await (0, runtimeEvidenceArtifacts_exports.discoverRuntimeEvidenceBundles)(historyDir);
@@ -43038,7 +43116,7 @@ __export(serverHealth_exports, {
43038
43116
  main: () => main49,
43039
43117
  resolveServerHealthThresholds: () => resolveServerHealthThresholds
43040
43118
  });
43041
- var import_config10, import_node_child_process12, import_node_os5, import_node_fs11, import_args35, import_redis22, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml6, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main49;
43119
+ var import_config10, import_node_child_process12, import_node_os5, import_node_fs11, import_args35, import_redis23, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml6, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main49;
43042
43120
  var init_serverHealth = __esm({
43043
43121
  "src/scripts/serverHealth.ts"() {
43044
43122
  "use strict";
@@ -43047,7 +43125,7 @@ var init_serverHealth = __esm({
43047
43125
  import_node_os5 = __toESM(require("os"));
43048
43126
  import_node_fs11 = require("fs");
43049
43127
  import_args35 = __toESM(require("args"));
43050
- import_redis22 = require("@tradejs/infra/redis");
43128
+ import_redis23 = require("@tradejs/infra/redis");
43051
43129
  init_telegramReports();
43052
43130
  DEFAULT_STATE = {
43053
43131
  status: "healthy",
@@ -43457,7 +43535,7 @@ var init_serverHealth = __esm({
43457
43535
  const diskPath = String(flags36.diskPath || "/");
43458
43536
  const snapshot = collectServerHealthSnapshot(diskPath);
43459
43537
  const stateKey = getStateKey(String(flags36.user), snapshot.hostname);
43460
- const prevState = await (0, import_redis22.getData)(stateKey, DEFAULT_STATE) ?? DEFAULT_STATE;
43538
+ const prevState = await (0, import_redis23.getData)(stateKey, DEFAULT_STATE) ?? DEFAULT_STATE;
43461
43539
  const evaluation = evaluateServerHealth(snapshot, thresholds);
43462
43540
  const cooldownMs = Math.max(60, Number(flags36.cooldownSec)) * 1e3;
43463
43541
  const now2 = snapshot.timestamp;
@@ -43470,7 +43548,7 @@ var init_serverHealth = __esm({
43470
43548
  lastOkAt: prevState.lastOkAt,
43471
43549
  activeIssueCodes: evaluation.issues.map((issue) => issue.code)
43472
43550
  };
43473
- await (0, import_redis22.setData)(stateKey, nextState2, { expire: 0 });
43551
+ await (0, import_redis23.setData)(stateKey, nextState2, { expire: 0 });
43474
43552
  if (shouldSend) {
43475
43553
  const message = buildAlertMessage({
43476
43554
  evaluation,
@@ -43499,7 +43577,7 @@ var init_serverHealth = __esm({
43499
43577
  lastOkAt: now2,
43500
43578
  activeIssueCodes: []
43501
43579
  };
43502
- await (0, import_redis22.setData)(stateKey, nextState, { expire: 0 });
43580
+ await (0, import_redis23.setData)(stateKey, nextState, { expire: 0 });
43503
43581
  if (recovered) {
43504
43582
  const message = buildRecoveryMessage({ snapshot, prevState });
43505
43583
  if (flags36.printOnly) {
@@ -44846,18 +44924,18 @@ __export(runtimeParity_exports, {
44846
44924
  main: () => main50,
44847
44925
  runtimeParity: () => runtimeParity
44848
44926
  });
44849
- var import_config11, import_node_crypto26, import_args36, import_chalk52, import_constants19, import_time13, import_logger7, import_redis23, import_cli12, import_backtest8, import_connectors16, flags32, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main50;
44927
+ var import_config11, import_node_crypto25, import_args36, import_chalk52, import_constants20, import_time13, import_logger8, import_redis24, import_cli12, import_backtest8, import_connectors16, flags32, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main50;
44850
44928
  var init_runtimeParity2 = __esm({
44851
44929
  "src/scripts/runtimeParity.ts"() {
44852
44930
  "use strict";
44853
44931
  import_config11 = require("dotenv/config");
44854
- import_node_crypto26 = require("crypto");
44932
+ import_node_crypto25 = require("crypto");
44855
44933
  import_args36 = __toESM(require("args"));
44856
44934
  import_chalk52 = __toESM(require("chalk"));
44857
- import_constants19 = require("@tradejs/core/constants");
44935
+ import_constants20 = require("@tradejs/core/constants");
44858
44936
  import_time13 = require("@tradejs/core/time");
44859
- import_logger7 = require("@tradejs/infra/logger");
44860
- import_redis23 = require("@tradejs/infra/redis");
44937
+ import_logger8 = require("@tradejs/infra/logger");
44938
+ import_redis24 = require("@tradejs/infra/redis");
44861
44939
  import_cli12 = require("@tradejs/node/cli");
44862
44940
  import_backtest8 = require("@tradejs/node/backtest");
44863
44941
  import_connectors16 = require("@tradejs/node/connectors");
@@ -44934,7 +45012,7 @@ var init_runtimeParity2 = __esm({
44934
45012
  if (connectorName) {
44935
45013
  return connectorName;
44936
45014
  }
44937
- import_logger7.logger.warn(
45015
+ import_logger8.logger.warn(
44938
45016
  'Unknown connector "%s". Fallback to %s.',
44939
45017
  String(value || "").trim() || String(value),
44940
45018
  import_connectors16.DEFAULT_CONNECTOR_NAME
@@ -45017,8 +45095,8 @@ var init_runtimeParity2 = __esm({
45017
45095
  toleranceMs
45018
45096
  }) => {
45019
45097
  const [userConfig, strategyResults] = await Promise.all([
45020
- (0, import_redis23.getData)(import_redis23.redisKeys.strategyConfig(userName3, strategy), {}),
45021
- (0, import_redis23.getData)(import_redis23.redisKeys.strategyResults(userName3, strategy), {})
45098
+ (0, import_redis24.getData)(import_redis24.redisKeys.strategyConfig(userName3, strategy), {}),
45099
+ (0, import_redis24.getData)(import_redis24.redisKeys.strategyResults(userName3, strategy), {})
45022
45100
  ]);
45023
45101
  const typedResults = strategyResults ?? {};
45024
45102
  const symbolResult = typedResults?.[symbol];
@@ -45068,7 +45146,7 @@ var init_runtimeParity2 = __esm({
45068
45146
  userName: userName3,
45069
45147
  projectRoot: projectRoot16,
45070
45148
  shouldUseDedicatedReferences: true,
45071
- warn: (message) => import_logger7.logger.warn(message)
45149
+ warn: (message) => import_logger8.logger.warn(message)
45072
45150
  });
45073
45151
  await updateMarketHistoryWithBtcReferences({
45074
45152
  marketConnector: connector,
@@ -45155,7 +45233,7 @@ var init_runtimeParity2 = __esm({
45155
45233
  const sourceCounts = countReplayTargetSources(replayTargets);
45156
45234
  const preloadStart = (0, import_time13.getBacktestPreloadStart)(
45157
45235
  window.start,
45158
- import_constants19.BACKTEST_PRELOAD_DAYS
45236
+ import_constants20.BACKTEST_PRELOAD_DAYS
45159
45237
  );
45160
45238
  const replayStartedAt = Date.now();
45161
45239
  const replaySymbolsCount = new Set(
@@ -45234,9 +45312,9 @@ var init_runtimeParity2 = __esm({
45234
45312
  start: window.start,
45235
45313
  end: window.end
45236
45314
  },
45237
- name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto26.randomUUID)().slice(0, 8)}`,
45238
- testId: (0, import_node_crypto26.randomUUID)().slice(0, 8),
45239
- testSuiteId: (0, import_node_crypto26.randomUUID)().slice(0, 8),
45315
+ name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto25.randomUUID)().slice(0, 8)}`,
45316
+ testId: (0, import_node_crypto25.randomUUID)().slice(0, 8),
45317
+ testSuiteId: (0, import_node_crypto25.randomUUID)().slice(0, 8),
45240
45318
  strategyName: target.strategy,
45241
45319
  strategyConfig: replayConfig,
45242
45320
  connectorName,
@@ -45399,12 +45477,12 @@ var init_runtimeStrategies = __esm({
45399
45477
  });
45400
45478
 
45401
45479
  // src/lib/signals/skipStats.ts
45402
- var import_chalk53, import_logger8, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
45480
+ var import_chalk53, import_logger9, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
45403
45481
  var init_skipStats = __esm({
45404
45482
  "src/lib/signals/skipStats.ts"() {
45405
45483
  "use strict";
45406
45484
  import_chalk53 = __toESM(require("chalk"));
45407
- import_logger8 = require("@tradejs/infra/logger");
45485
+ import_logger9 = require("@tradejs/infra/logger");
45408
45486
  init_runtimeSignalsStorage();
45409
45487
  createStrategySkipStats = (runtimeStrategies) => new Map(
45410
45488
  runtimeStrategies.map(({ strategyName }) => [
@@ -45429,24 +45507,24 @@ var init_skipStats = __esm({
45429
45507
  );
45430
45508
  };
45431
45509
  logStrategySkipStats = (runtimeStrategies, strategyStats) => {
45432
- import_logger8.logger.info(import_chalk53.default.yellow("skip stats:"));
45510
+ import_logger9.logger.info(import_chalk53.default.yellow("skip stats:"));
45433
45511
  for (const { strategyName } of runtimeStrategies) {
45434
45512
  const stats = strategyStats.get(strategyName);
45435
45513
  if (!stats) {
45436
45514
  continue;
45437
45515
  }
45438
- import_logger8.logger.info(
45516
+ import_logger9.logger.info(
45439
45517
  `${strategyName}: evaluated=${stats.evaluated}, signals=${stats.signals}`
45440
45518
  );
45441
45519
  const sortedReasons = [...stats.reasons.entries()].sort(
45442
45520
  (left, right) => right[1] - left[1] || left[0].localeCompare(right[0])
45443
45521
  );
45444
45522
  if (!sortedReasons.length) {
45445
- import_logger8.logger.info(" none");
45523
+ import_logger9.logger.info(" none");
45446
45524
  continue;
45447
45525
  }
45448
45526
  for (const [reason, count] of sortedReasons) {
45449
- import_logger8.logger.info(` ${reason}: ${count}`);
45527
+ import_logger9.logger.info(` ${reason}: ${count}`);
45450
45528
  }
45451
45529
  }
45452
45530
  };
@@ -45454,11 +45532,11 @@ var init_skipStats = __esm({
45454
45532
  });
45455
45533
 
45456
45534
  // src/lib/signals/evaluations.ts
45457
- var import_redis24, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, runtimeLineageScopeCacheLoaded, buildRuntimeSignalEvaluationId, buildLineageField, flushRuntimeSignalEvaluations, createRuntimeSignalEvaluationBuffer;
45535
+ var import_redis25, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, runtimeLineageScopeCacheLoaded, buildRuntimeSignalEvaluationId, buildLineageField, flushRuntimeSignalEvaluations, createRuntimeSignalEvaluationBuffer;
45458
45536
  var init_evaluations = __esm({
45459
45537
  "src/lib/signals/evaluations.ts"() {
45460
45538
  "use strict";
45461
- import_redis24 = require("@tradejs/infra/redis");
45539
+ import_redis25 = require("@tradejs/infra/redis");
45462
45540
  init_runtimeSignalsStorage();
45463
45541
  init_runtimeLineage();
45464
45542
  runtimeLineageScopeCache = /* @__PURE__ */ new Map();
@@ -45509,7 +45587,7 @@ var init_evaluations = __esm({
45509
45587
  runtimeLineageScopeCacheDayKey = dayKey;
45510
45588
  runtimeLineageScopeCacheLoaded = false;
45511
45589
  }
45512
- const lineageBucket = import_redis24.redisKeys.runtimeLineageScopeBucket(
45590
+ const lineageBucket = import_redis25.redisKeys.runtimeLineageScopeBucket(
45513
45591
  dayEvaluations[0].userName,
45514
45592
  dayKey
45515
45593
  );
@@ -45517,7 +45595,7 @@ var init_evaluations = __esm({
45517
45595
  (evaluation) => evaluation.runtimeLineage != null
45518
45596
  );
45519
45597
  if (lineageEvaluations.length > 0 && !runtimeLineageScopeCacheLoaded) {
45520
- const storedScopes = await (0, import_redis24.getHashJsonValues)(lineageBucket);
45598
+ const storedScopes = await (0, import_redis25.getHashJsonValues)(lineageBucket);
45521
45599
  for (const scope of storedScopes) {
45522
45600
  const lineageField = buildLineageField(scope);
45523
45601
  runtimeLineageScopeCache.set(`${lineageBucket}:${lineageField}`, scope);
@@ -45562,7 +45640,7 @@ var init_evaluations = __esm({
45562
45640
  lineageWrites.set(lineageField, scope);
45563
45641
  }
45564
45642
  if (lineageWrites.size > 0) {
45565
- await (0, import_redis24.setHashJsonFields)(
45643
+ await (0, import_redis25.setHashJsonFields)(
45566
45644
  lineageBucket,
45567
45645
  [...lineageWrites].map(([field, data]) => ({ field, data })),
45568
45646
  {
@@ -45574,7 +45652,7 @@ var init_evaluations = __esm({
45574
45652
  const statsIncrements = /* @__PURE__ */ new Map();
45575
45653
  for (const evaluation of dayEvaluations) {
45576
45654
  if (shouldStoreDetailedRuntimeSignalEvaluation(evaluation)) {
45577
- const bucket = import_redis24.redisKeys.runtimeSignalEvaluationBucket(
45655
+ const bucket = import_redis25.redisKeys.runtimeSignalEvaluationBucket(
45578
45656
  evaluation.userName,
45579
45657
  dayKey,
45580
45658
  evaluation.strategy
@@ -45586,7 +45664,7 @@ var init_evaluations = __esm({
45586
45664
  });
45587
45665
  detailedWrites.set(bucket, entries);
45588
45666
  }
45589
- const statsBucket = import_redis24.redisKeys.runtimeSignalEvaluationStatsBucket(
45667
+ const statsBucket = import_redis25.redisKeys.runtimeSignalEvaluationStatsBucket(
45590
45668
  evaluation.userName,
45591
45669
  dayKey,
45592
45670
  evaluation.strategy,
@@ -45602,12 +45680,12 @@ var init_evaluations = __esm({
45602
45680
  }
45603
45681
  await Promise.all([
45604
45682
  ...[...detailedWrites].map(
45605
- ([bucket, entries]) => (0, import_redis24.setHashJsonFields)(bucket, entries, {
45683
+ ([bucket, entries]) => (0, import_redis25.setHashJsonFields)(bucket, entries, {
45606
45684
  expire: runtimeSignalRetentionTtl
45607
45685
  })
45608
45686
  ),
45609
45687
  ...[...statsIncrements].map(
45610
- ([bucket, increments]) => (0, import_redis24.incrHashFields)(bucket, increments, {
45688
+ ([bucket, increments]) => (0, import_redis25.incrHashFields)(bucket, increments, {
45611
45689
  expire: runtimeSignalRetentionTtl
45612
45690
  })
45613
45691
  )
@@ -45623,7 +45701,7 @@ var init_evaluations = __esm({
45623
45701
  const runtimeSignalRetentionTtl = getRuntimeSignalRetentionTtlSeconds();
45624
45702
  const signalRefsByBucket = /* @__PURE__ */ new Map();
45625
45703
  for (const { userName: userName3, signal } of pendingSignals) {
45626
- const bucket = import_redis24.redisKeys.runtimeSignalBucket(
45704
+ const bucket = import_redis25.redisKeys.runtimeSignalBucket(
45627
45705
  userName3,
45628
45706
  (0, import_time5.getRuntimeStorageDayKey)(signal.timestamp),
45629
45707
  signal.strategy
@@ -45637,14 +45715,14 @@ var init_evaluations = __esm({
45637
45715
  }
45638
45716
  await Promise.all([
45639
45717
  ...pendingSignals.map(
45640
- ({ signal }) => (0, import_redis24.setData)(
45641
- import_redis24.redisKeys.storeSignal(signal.symbol, signal.signalId),
45718
+ ({ signal }) => (0, import_redis25.setData)(
45719
+ import_redis25.redisKeys.storeSignal(signal.symbol, signal.signalId),
45642
45720
  toStoredRuntimeSignal(signal),
45643
45721
  { expire: runtimeSignalRetentionTtl }
45644
45722
  )
45645
45723
  ),
45646
45724
  ...[...signalRefsByBucket].map(
45647
- ([bucket, entries]) => (0, import_redis24.setHashJsonFields)(bucket, entries, {
45725
+ ([bucket, entries]) => (0, import_redis25.setHashJsonFields)(bucket, entries, {
45648
45726
  expire: runtimeSignalRetentionTtl
45649
45727
  })
45650
45728
  )
@@ -45897,12 +45975,12 @@ var init_daemon = __esm({
45897
45975
  });
45898
45976
 
45899
45977
  // src/lib/signals/klineFeed.ts
45900
- var import_connectors17, import_logger9, import_candles5, FLUSH_DELAY_MS, normalizeSymbols2, createSignalsKlineFeed;
45978
+ var import_connectors17, import_logger10, import_candles5, FLUSH_DELAY_MS, normalizeSymbols2, createSignalsKlineFeed;
45901
45979
  var init_klineFeed = __esm({
45902
45980
  "src/lib/signals/klineFeed.ts"() {
45903
45981
  "use strict";
45904
45982
  import_connectors17 = require("@tradejs/connectors");
45905
- import_logger9 = require("@tradejs/infra/logger");
45983
+ import_logger10 = require("@tradejs/infra/logger");
45906
45984
  import_candles5 = require("@tradejs/infra/timescale/candles");
45907
45985
  init_klineEvents();
45908
45986
  FLUSH_DELAY_MS = 100;
@@ -45956,7 +46034,7 @@ var init_klineFeed = __esm({
45956
46034
  if (flushTimer || closed) return;
45957
46035
  flushTimer = setTimeout(() => {
45958
46036
  void flush().catch(
45959
- (error) => import_logger9.logger.error("websocket candle batch flush failed: %s", String(error))
46037
+ (error) => import_logger10.logger.error("websocket candle batch flush failed: %s", String(error))
45960
46038
  );
45961
46039
  }, FLUSH_DELAY_MS);
45962
46040
  };
@@ -45973,7 +46051,7 @@ var init_klineFeed = __esm({
45973
46051
  confirm: event.confirm,
45974
46052
  receivedAt: event.receivedAt
45975
46053
  }).catch(
45976
- (error) => import_logger9.logger.warn("websocket candle publish failed: %s", String(error))
46054
+ (error) => import_logger10.logger.warn("websocket candle publish failed: %s", String(error))
45977
46055
  );
45978
46056
  if (!event.confirm) return;
45979
46057
  pending.set(`${event.symbol}:${event.candle.timestamp}`, {
@@ -46028,12 +46106,12 @@ var init_klineFeed = __esm({
46028
46106
  });
46029
46107
 
46030
46108
  // src/lib/signals/tickerEvaluator.ts
46031
- var import_strategies13, import_logger10, createSignalsTickerEvaluator;
46109
+ var import_strategies13, import_logger11, createSignalsTickerEvaluator;
46032
46110
  var init_tickerEvaluator = __esm({
46033
46111
  "src/lib/signals/tickerEvaluator.ts"() {
46034
46112
  "use strict";
46035
46113
  import_strategies13 = require("@tradejs/node/strategies");
46036
- import_logger10 = require("@tradejs/infra/logger");
46114
+ import_logger11 = require("@tradejs/infra/logger");
46037
46115
  init_windows();
46038
46116
  init_runtimeLineage();
46039
46117
  init_runtimeModeConfig();
@@ -46193,7 +46271,7 @@ var init_tickerEvaluator = __esm({
46193
46271
  continue;
46194
46272
  }
46195
46273
  if (evaluation.action.startsWith("rebuilt_")) {
46196
- import_logger10.logger.info(
46274
+ import_logger11.logger.info(
46197
46275
  "Rebuilt signals strategy state (%s): %s %s",
46198
46276
  evaluation.action.slice("rebuilt_".length),
46199
46277
  strategyName,
@@ -46296,7 +46374,7 @@ var init_tickerEvaluator = __esm({
46296
46374
  ...signal.riskDecision ? { riskDecision: signal.riskDecision } : {},
46297
46375
  ...signal.ml ? { ml: signal.ml } : {}
46298
46376
  });
46299
- import_logger10.logger.info("Signal found %s by strategy %s", symbol, strategyName);
46377
+ import_logger11.logger.info("Signal found %s by strategy %s", symbol, strategyName);
46300
46378
  }
46301
46379
  return strategySignals;
46302
46380
  };
@@ -46445,7 +46523,7 @@ var init_configuredScopes = __esm({
46445
46523
  });
46446
46524
 
46447
46525
  // src/lib/signals/runner.ts
46448
- var import_progress12, import_chalk54, import_connectors18, import_cli13, import_async5, import_strategies14, import_constants20, import_time14, import_logger11, import_runtimeDeploymentEvents, import_runtimeHeartbeats, import_runtimeStrategies7, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
46526
+ var import_progress12, import_chalk54, import_connectors18, import_cli13, import_async5, import_strategies14, import_constants21, import_time14, import_logger12, import_runtimeDeploymentEvents, import_runtimeHeartbeats, import_runtimeStrategies7, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
46449
46527
  var init_runner = __esm({
46450
46528
  "src/lib/signals/runner.ts"() {
46451
46529
  "use strict";
@@ -46455,9 +46533,9 @@ var init_runner = __esm({
46455
46533
  import_cli13 = require("@tradejs/node/cli");
46456
46534
  import_async5 = require("@tradejs/core/async");
46457
46535
  import_strategies14 = require("@tradejs/core/strategies");
46458
- import_constants20 = require("@tradejs/core/constants");
46536
+ import_constants21 = require("@tradejs/core/constants");
46459
46537
  import_time14 = require("@tradejs/core/time");
46460
- import_logger11 = require("@tradejs/infra/logger");
46538
+ import_logger12 = require("@tradejs/infra/logger");
46461
46539
  import_runtimeDeploymentEvents = require("@tradejs/infra/runtimeDeploymentEvents");
46462
46540
  import_runtimeHeartbeats = require("@tradejs/infra/runtimeHeartbeats");
46463
46541
  import_runtimeStrategies7 = require("@tradejs/node/runtimeStrategies");
@@ -46504,7 +46582,7 @@ var init_runner = __esm({
46504
46582
  deploymentId: config2.deploymentId,
46505
46583
  expectedCompositionId: compositionId
46506
46584
  }),
46507
- onError: (compositionId, error) => import_logger11.logger.warn(
46585
+ onError: (compositionId, error) => import_logger12.logger.warn(
46508
46586
  "runtime evidence snapshot unavailable; trading continues and the next cycle will retry (composition=%s): %s",
46509
46587
  compositionId,
46510
46588
  error instanceof Error ? error.message : String(error)
@@ -46513,7 +46591,7 @@ var init_runner = __esm({
46513
46591
  const resolveSignalsDaemonMaxLiveBars = (runtimeInterval = interval4) => {
46514
46592
  const intervalMinutes = Number(runtimeInterval);
46515
46593
  const preloadBars = Math.ceil(
46516
- import_constants20.SIGNALS_CLI_PRELOAD_DAYS * 24 * 60 / intervalMinutes
46594
+ import_constants21.SIGNALS_CLI_PRELOAD_DAYS * 24 * 60 / intervalMinutes
46517
46595
  );
46518
46596
  return resolvePositiveInteger2(
46519
46597
  process.env.SIGNALS_DAEMON_MAX_LIVE_BARS,
@@ -46532,7 +46610,7 @@ var init_runner = __esm({
46532
46610
  const timeOperation3 = (label, operation) => timeOperation(
46533
46611
  label,
46534
46612
  operation,
46535
- (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
46613
+ (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46536
46614
  );
46537
46615
  const formatSlowSignalsWarning = (params) => [
46538
46616
  "<b>Slow yarn signals run</b>",
@@ -46589,7 +46667,7 @@ var init_runner = __esm({
46589
46667
  userName: config2.userName,
46590
46668
  projectRoot: projectRoot18,
46591
46669
  shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors18.DEFAULT_CONNECTOR_NAME.toLowerCase(),
46592
- warn: (message) => import_logger11.logger.warn(message)
46670
+ warn: (message) => import_logger12.logger.warn(message)
46593
46671
  });
46594
46672
  return {
46595
46673
  connectorName,
@@ -46649,7 +46727,7 @@ var init_runner = __esm({
46649
46727
  }) : [];
46650
46728
  const selectedTickers = selection?.tickers ? [.../* @__PURE__ */ new Set([...selection.tickers, ...selectedActiveSymbols])] : void 0;
46651
46729
  if (selectedActiveSymbols.length) {
46652
- import_logger11.logger.info(
46730
+ import_logger12.logger.info(
46653
46731
  import_chalk54.default.gray(
46654
46732
  `runtime scope retained active symbols: ${selectedActiveSymbols.join(", ")}`
46655
46733
  )
@@ -46687,7 +46765,7 @@ var init_runner = __esm({
46687
46765
  const projectConfig = await (0, import_cli13.loadTradejsConfig)(projectRoot18);
46688
46766
  projectHooks = projectConfig.hooks;
46689
46767
  const currentTimestamp = (0, import_time14.getTimestamp)();
46690
- const preloadStart = (0, import_time14.getTimestamp)(import_constants20.SIGNALS_CLI_PRELOAD_DAYS);
46768
+ const preloadStart = (0, import_time14.getTimestamp)(import_constants21.SIGNALS_CLI_PRELOAD_DAYS);
46691
46769
  if (!config2.cacheOnly && session.klineFeed) {
46692
46770
  const expectedSymbols = universe === "crypto" ? [.../* @__PURE__ */ new Set([...tickers, "BTCUSDT", "ETHUSDT"])] : tickers;
46693
46771
  session.klineFeed.setSubscriptions(expectedSymbols);
@@ -46701,7 +46779,7 @@ var init_runner = __esm({
46701
46779
  })
46702
46780
  );
46703
46781
  await session.klineFeed.flush();
46704
- import_logger11.logger.info(
46782
+ import_logger12.logger.info(
46705
46783
  import_chalk54.default.gray(
46706
46784
  `websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
46707
46785
  )
@@ -46711,17 +46789,17 @@ var init_runner = __esm({
46711
46789
  connectorName,
46712
46790
  interval: interval5,
46713
46791
  symbols: missingSymbols,
46714
- preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
46792
+ preloadDays: import_constants21.SIGNALS_CLI_PRELOAD_DAYS,
46715
46793
  universe,
46716
- log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
46794
+ log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46717
46795
  });
46718
46796
  await updateBtcReferenceHistory({
46719
46797
  marketConnector,
46720
46798
  btcReferences,
46721
46799
  interval: interval5,
46722
- preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
46800
+ preloadDays: import_constants21.SIGNALS_CLI_PRELOAD_DAYS,
46723
46801
  universe,
46724
- log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
46802
+ log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46725
46803
  });
46726
46804
  } else if (!config2.cacheOnly) {
46727
46805
  await updateMarketHistoryWithBtcReferences({
@@ -46730,9 +46808,9 @@ var init_runner = __esm({
46730
46808
  btcReferences,
46731
46809
  interval: interval5,
46732
46810
  symbols: tickers,
46733
- preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
46811
+ preloadDays: import_constants21.SIGNALS_CLI_PRELOAD_DAYS,
46734
46812
  universe,
46735
- log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
46813
+ log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46736
46814
  });
46737
46815
  }
46738
46816
  await prepareMarketContextForRun({
@@ -46746,7 +46824,7 @@ var init_runner = __esm({
46746
46824
  endMs: currentTimestamp,
46747
46825
  preloadStartMs: preloadStart,
46748
46826
  cacheOnly: config2.cacheOnly,
46749
- log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
46827
+ log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46750
46828
  });
46751
46829
  if (config2.updateOnly) {
46752
46830
  return;
@@ -46816,7 +46894,7 @@ var init_runner = __esm({
46816
46894
  ) : configuredRuntimeStrategies;
46817
46895
  if (!runtimeStrategies.length) {
46818
46896
  lifecycle.clear();
46819
- import_logger11.logger.warn(
46897
+ import_logger12.logger.warn(
46820
46898
  "No strategy releases are bound to deployment %s",
46821
46899
  deployment?.id
46822
46900
  );
@@ -46849,7 +46927,7 @@ var init_runner = __esm({
46849
46927
  )
46850
46928
  )
46851
46929
  );
46852
- import_logger11.logger.info(
46930
+ import_logger12.logger.info(
46853
46931
  import_chalk54.default.yellow(
46854
46932
  `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
46855
46933
  )
@@ -46872,7 +46950,7 @@ var init_runner = __esm({
46872
46950
  afterSignalsHookContext
46873
46951
  );
46874
46952
  if (beforeSignalsResult?.abort === true) {
46875
- import_logger11.logger.info(
46953
+ import_logger12.logger.info(
46876
46954
  "signals aborted before ticker evaluation: %s",
46877
46955
  beforeSignalsResult.reason ?? "PROJECT_BEFORE_SIGNALS_ABORTED"
46878
46956
  );
@@ -46886,9 +46964,9 @@ var init_runner = __esm({
46886
46964
  width: 30
46887
46965
  }
46888
46966
  );
46889
- import_logger11.logger.info(import_chalk54.default.yellow(`tickers: ${tickers.length}`));
46967
+ import_logger12.logger.info(import_chalk54.default.yellow(`tickers: ${tickers.length}`));
46890
46968
  const signalsParallel = resolvePositiveInteger2(config2.parallel, 4);
46891
- import_logger11.logger.info(import_chalk54.default.yellow(`signal workers: ${signalsParallel}`));
46969
+ import_logger12.logger.info(import_chalk54.default.yellow(`signal workers: ${signalsParallel}`));
46892
46970
  const evaluateTicker = createSignalsTickerEvaluator({
46893
46971
  userName: config2.userName,
46894
46972
  makeOrders: config2.makeOrders,
@@ -46959,7 +47037,7 @@ var init_runner = __esm({
46959
47037
  config2.userName
46960
47038
  );
46961
47039
  }
46962
- import_logger11.logger.info(
47040
+ import_logger12.logger.info(
46963
47041
  JSON.stringify(
46964
47042
  signals3.map((s) => s.symbol),
46965
47043
  null,
@@ -46972,7 +47050,7 @@ var init_runner = __esm({
46972
47050
  } catch (error) {
46973
47051
  status = "failed";
46974
47052
  failureMessage = error?.message || String(error);
46975
- import_logger11.logger.error(
47053
+ import_logger12.logger.error(
46976
47054
  "signals failed: %s",
46977
47055
  error?.message || String(error)
46978
47056
  );
@@ -46982,7 +47060,7 @@ var init_runner = __esm({
46982
47060
  await runtimeSignalEvaluations.flush();
46983
47061
  } catch (error) {
46984
47062
  telemetryPersistence = "failed";
46985
- import_logger11.logger.error(
47063
+ import_logger12.logger.error(
46986
47064
  "runtime signal evaluation flush failed: %s",
46987
47065
  error?.message || String(error)
46988
47066
  );
@@ -47013,7 +47091,7 @@ var init_runner = __esm({
47013
47091
  durationMs
47014
47092
  });
47015
47093
  } catch (error) {
47016
- import_logger11.logger.error(
47094
+ import_logger12.logger.error(
47017
47095
  "afterSignals hook failed: %s",
47018
47096
  error?.message || String(error)
47019
47097
  );
@@ -47030,20 +47108,20 @@ var init_runner = __esm({
47030
47108
  { userName: config2.userName }
47031
47109
  );
47032
47110
  } catch (error) {
47033
- import_logger11.logger.error(
47111
+ import_logger12.logger.error(
47034
47112
  "slow signals warning failed: %s",
47035
47113
  error?.message || String(error)
47036
47114
  );
47037
47115
  }
47038
47116
  }
47039
- import_logger11.logger.info(
47117
+ import_logger12.logger.info(
47040
47118
  import_chalk54.default.yellow(
47041
47119
  `signals ${status} in ${formatDuration3(durationMs)} (found=${signals3.length})`
47042
47120
  )
47043
47121
  );
47044
- import_logger11.logger.info("");
47045
- import_logger11.logger.info("");
47046
- import_logger11.logger.info("");
47122
+ import_logger12.logger.info("");
47123
+ import_logger12.logger.info("");
47124
+ import_logger12.logger.info("");
47047
47125
  }
47048
47126
  };
47049
47127
  const loadConfiguredSignalsScopes = async (deployment) => {
@@ -47118,14 +47196,14 @@ var init_runner = __esm({
47118
47196
  const sessions = /* @__PURE__ */ new Map();
47119
47197
  const lastBoundaryByScope = /* @__PURE__ */ new Map();
47120
47198
  const stop = (signalName) => {
47121
- import_logger11.logger.info("signals daemon stopping by %s", signalName);
47199
+ import_logger12.logger.info("signals daemon stopping by %s", signalName);
47122
47200
  abortController.abort();
47123
47201
  };
47124
47202
  const stopOnSigint = () => stop("SIGINT");
47125
47203
  const stopOnSigterm = () => stop("SIGTERM");
47126
47204
  process.once("SIGINT", stopOnSigint);
47127
47205
  process.once("SIGTERM", stopOnSigterm);
47128
- import_logger11.logger.info("signals daemon started (deployment-driven scopes)");
47206
+ import_logger12.logger.info("signals daemon started (deployment-driven scopes)");
47129
47207
  try {
47130
47208
  await runSignalsDaemon({
47131
47209
  intervalMs: 6e4,
@@ -47151,7 +47229,7 @@ var init_runner = __esm({
47151
47229
  strategies
47152
47230
  });
47153
47231
  } catch (error) {
47154
- import_logger11.logger.warn(
47232
+ import_logger12.logger.warn(
47155
47233
  "runtime deployment composition event unavailable; trading continues and the next cycle will retry (composition=%s): %s",
47156
47234
  currentDeployment.deploymentCompositionId,
47157
47235
  error instanceof Error ? error.message : String(error)
@@ -47187,7 +47265,7 @@ var init_runner = __esm({
47187
47265
  interval: session.interval,
47188
47266
  universe: session.universe
47189
47267
  });
47190
- import_logger11.logger.info(
47268
+ import_logger12.logger.info(
47191
47269
  "Bybit websocket candle feed enabled (account=%s, universe=%s, interval=%s)",
47192
47270
  session.accountId ?? "default",
47193
47271
  session.universe,
@@ -47209,7 +47287,7 @@ var init_runner = __esm({
47209
47287
  (sum3, session) => sum3 + session.lifecycle.size(),
47210
47288
  0
47211
47289
  );
47212
- import_logger11.logger.info(
47290
+ import_logger12.logger.info(
47213
47291
  "signals daemon resources: rss=%sMB heapUsed=%sMB heapTotal=%sMB stateKeys=%s scopes=%s",
47214
47292
  (memory.rss / 1024 / 1024).toFixed(1),
47215
47293
  (memory.heapUsed / 1024 / 1024).toFixed(1),
@@ -47219,7 +47297,7 @@ var init_runner = __esm({
47219
47297
  );
47220
47298
  },
47221
47299
  onCycleError: (error) => {
47222
- import_logger11.logger.error(
47300
+ import_logger12.logger.error(
47223
47301
  "signals daemon cycle failed: %s",
47224
47302
  error?.message || String(error)
47225
47303
  );
@@ -47359,14 +47437,14 @@ __export(signalsSummary_exports, {
47359
47437
  main: () => main53,
47360
47438
  signalsSummary: () => signalsSummary
47361
47439
  });
47362
- var import_config13, import_userSettings8, import_args38, import_logger12, import_connectors19, import_runtimeStrategies9, flags34, projectRoot17, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml8, formatMskDateTime4, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main53;
47440
+ var import_config13, import_userSettings8, import_args38, import_logger13, import_connectors19, import_runtimeStrategies9, flags34, projectRoot17, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml8, formatMskDateTime4, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main53;
47363
47441
  var init_signalsSummary = __esm({
47364
47442
  "src/scripts/signalsSummary.ts"() {
47365
47443
  "use strict";
47366
47444
  import_config13 = require("dotenv/config");
47367
47445
  import_userSettings8 = require("@tradejs/infra/userSettings");
47368
47446
  import_args38 = __toESM(require("args"));
47369
- import_logger12 = require("@tradejs/infra/logger");
47447
+ import_logger13 = require("@tradejs/infra/logger");
47370
47448
  import_connectors19 = require("@tradejs/node/connectors");
47371
47449
  init_runtimeRedis();
47372
47450
  init_runtimeTradeSync();
@@ -47482,7 +47560,7 @@ var init_signalsSummary = __esm({
47482
47560
  if (connectorName) {
47483
47561
  return connectorName;
47484
47562
  }
47485
- import_logger12.logger.warn(
47563
+ import_logger13.logger.warn(
47486
47564
  'Unknown connector "%s". Fallback to %s.',
47487
47565
  String(value || "").trim() || String(value),
47488
47566
  import_connectors19.DEFAULT_CONNECTOR_NAME
@@ -47564,7 +47642,7 @@ var init_signalsSummary = __esm({
47564
47642
  endTime,
47565
47643
  openPositionCallbacks: {
47566
47644
  onError: (error) => {
47567
- import_logger12.logger.warn(
47645
+ import_logger13.logger.warn(
47568
47646
  "signals summary: getOpenPositionPnl failed for scope account=%s deployment=%s: %s",
47569
47647
  scope.accountId ?? "default",
47570
47648
  scope.deploymentId ?? "default",
@@ -47574,7 +47652,7 @@ var init_signalsSummary = __esm({
47574
47652
  },
47575
47653
  closedPnlCallbacks: {
47576
47654
  onError: (error) => {
47577
- import_logger12.logger.warn(
47655
+ import_logger13.logger.warn(
47578
47656
  "signals summary: getClosedPnl failed for scope account=%s deployment=%s: %s",
47579
47657
  scope.accountId ?? "default",
47580
47658
  scope.deploymentId ?? "default",
@@ -47988,7 +48066,7 @@ none`
47988
48066
  (sum3, stats) => sum3 + stats.evaluated,
47989
48067
  0
47990
48068
  );
47991
- import_logger12.logger.info(
48069
+ import_logger13.logger.info(
47992
48070
  "signals summary deployment=%s window=%sh signals=%s evaluations=%s trades=%s connectors=%s scopes=%s user=%s",
47993
48071
  scope.deploymentId ?? "legacy",
47994
48072
  hours,
@@ -48055,17 +48133,17 @@ var test_ml_exports = {};
48055
48133
  __export(test_ml_exports, {
48056
48134
  main: () => main54
48057
48135
  });
48058
- var import_config14, import_constants21, import_ml3, import_registry6, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main54;
48136
+ var import_config14, import_constants22, import_ml3, import_registry6, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main54;
48059
48137
  var init_test_ml = __esm({
48060
48138
  "src/scripts/test-ml.ts"() {
48061
48139
  "use strict";
48062
48140
  import_config14 = require("dotenv/config");
48063
- import_constants21 = require("@tradejs/core/constants");
48141
+ import_constants22 = require("@tradejs/core/constants");
48064
48142
  import_ml3 = require("@tradejs/infra/ml");
48065
48143
  import_registry6 = require("@tradejs/node/registry");
48066
48144
  now = Date.now();
48067
48145
  INTERVAL_MIN = 15;
48068
- CANDLES = import_constants21.ML_BASE_CANDLES_WINDOW;
48146
+ CANDLES = import_constants22.ML_BASE_CANDLES_WINDOW;
48069
48147
  makeSeries = (len, base, step = 0.1) => Array.from({ length: len }, (_3, i) => base + i * step);
48070
48148
  makeCandles = (startPrice, startTs) => {
48071
48149
  const candles = [];
@@ -48137,8 +48215,8 @@ var init_test_ml = __esm({
48137
48215
  correlation: 0.18,
48138
48216
  touches: 6,
48139
48217
  distance: 0.7,
48140
- candles15m: candles.slice(-import_constants21.ML_BASE_CANDLES_WINDOW),
48141
- btcCandles15m: btcCandles.slice(-import_constants21.ML_BASE_CANDLES_WINDOW),
48218
+ candles15m: candles.slice(-import_constants22.ML_BASE_CANDLES_WINDOW),
48219
+ btcCandles15m: btcCandles.slice(-import_constants22.ML_BASE_CANDLES_WINDOW),
48142
48220
  atr: makeSeries(10, 1.2, 0.02),
48143
48221
  atrPct: makeSeries(10, 1.05, 5e-3),
48144
48222
  maFast: makeSeries(10, currentPrice * 0.995, 0.01),
@@ -48224,14 +48302,14 @@ var user_add_exports = {};
48224
48302
  __export(user_add_exports, {
48225
48303
  main: () => main56
48226
48304
  });
48227
- var import_args39, import_chalk55, import_bcryptjs, import_redis25, flags35, main56;
48305
+ var import_args39, import_chalk55, import_bcryptjs, import_redis26, flags35, main56;
48228
48306
  var init_user_add = __esm({
48229
48307
  "src/scripts/user-add.ts"() {
48230
48308
  "use strict";
48231
48309
  import_args39 = __toESM(require("args"));
48232
48310
  import_chalk55 = __toESM(require("chalk"));
48233
48311
  import_bcryptjs = __toESM(require("bcryptjs"));
48234
- import_redis25 = require("@tradejs/infra/redis");
48312
+ import_redis26 = require("@tradejs/infra/redis");
48235
48313
  import_args39.default.example("yarn user-add -u myname -p 123456", "Create or update user");
48236
48314
  import_args39.default.option(["u", "user"], "Username", "");
48237
48315
  import_args39.default.option(["p", "password"], "Password (plain text)", "");
@@ -48244,14 +48322,14 @@ var init_user_add = __esm({
48244
48322
  process.exit(1);
48245
48323
  }
48246
48324
  const passwordHash = await import_bcryptjs.default.hash(password, 10);
48247
- const existing = await (0, import_redis25.getData)(import_redis25.redisKeys.user(userName3), null);
48325
+ const existing = await (0, import_redis26.getData)(import_redis26.redisKeys.user(userName3), null);
48248
48326
  const next = {
48249
48327
  ...existing ?? {},
48250
48328
  passwordHash,
48251
48329
  userName: userName3,
48252
48330
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
48253
48331
  };
48254
- await (0, import_redis25.setData)(import_redis25.redisKeys.user(userName3), next, {
48332
+ await (0, import_redis26.setData)(import_redis26.redisKeys.user(userName3), next, {
48255
48333
  expire: 0
48256
48334
  });
48257
48335
  console.log(import_chalk55.default.green(`User ${userName3} updated`));
@@ -48270,7 +48348,7 @@ __export(cli_exports, {
48270
48348
  });
48271
48349
  module.exports = __toCommonJS(cli_exports);
48272
48350
  var import_config16 = require("dotenv/config");
48273
- var import_redis26 = require("@tradejs/infra/redis");
48351
+ var import_redis27 = require("@tradejs/infra/redis");
48274
48352
  var import_client9 = require("@tradejs/infra/timescale/client");
48275
48353
  var scriptLoaders = {
48276
48354
  "research-visuals": () => Promise.resolve().then(() => (init_researchVisuals2(), researchVisuals_exports)),
@@ -48345,7 +48423,7 @@ var runLoadedModule = async (loaded) => {
48345
48423
  }
48346
48424
  };
48347
48425
  var cleanupCliResources = async () => {
48348
- await Promise.allSettled([(0, import_redis26.closeRedisConnection)(), (0, import_client9.closeTimescalePool)()]);
48426
+ await Promise.allSettled([(0, import_redis27.closeRedisConnection)(), (0, import_client9.closeTimescalePool)()]);
48349
48427
  };
48350
48428
  var main57 = async () => {
48351
48429
  const [, scriptPath, command = "", ...args40] = process.argv;