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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)) {
@@ -12367,6 +12367,18 @@ var init_binanceMarketContextBackfill = __esm({
12367
12367
  });
12368
12368
 
12369
12369
  // src/lib/derivativesContextBackfill.ts
12370
+ async function resolveCoinalyzeBackfillMarket(userName3, symbol) {
12371
+ const apiKey = await getCoinalyzeApiKey(userName3);
12372
+ if (!apiKey) throw new Error("Missing Coinalyze API key.");
12373
+ const markets = (await fetchCoinalyzeMarkets(apiKey)).filter(
12374
+ (market) => market.quote_asset?.toUpperCase() === "USDT" && market.is_perpetual
12375
+ );
12376
+ const priority = parseList(
12377
+ process.env.COINALYZE_EXCHANGE_PRIORITY || process.env.DERIVATIVES_CONTEXT_EXCHANGE_PRIORITY || "A,6,0"
12378
+ );
12379
+ const { matches: matches2 } = buildMatches([symbol], markets, priority);
12380
+ return { apiKey, marketSymbol: matches2[0]?.marketSymbol };
12381
+ }
12370
12382
  var import_chalk7, import_progress5, import_async, import_constants5, import_indicators, import_derivatives, import_client2, import_userSettings3, HOUR_MS, DAY_MS7, DEFAULT_LOOKBACK_HOURS, SOURCE_INTERVALS, coinalyzeIntervalMap, derivativesIntervalMs, lastRequestTs, asInt2, parseList, parseBooleanFlag, normalizeSymbols, isDerivativesTargetContextEnabled, resolveDerivativesContextBackfillSymbols, chunkArray, isBacktestDerivativesContextEnabled, isSignalsDerivativesContextEnabled, isDerivativesContextBackfillEnabled, shouldBackfillDerivativesContextForBacktest, shouldBackfillDerivativesContextForSignals, resolveDerivativesContextIntervals, resolveDerivativesContextLookbackMs, resolveDerivativesContextBackfillWindow, resolveDerivativesContextIntervalBackfillWindow, resolveDerivativesContextMissingFetchFromMs, resolveDerivativesContextFetchFromMs, resolveDerivativesContextRequiredFetchFromMs, countBackfillWindows, buildBackfillWindows, hasDerivativesWindowCoverage, resolveDerivativesContextMissingCoverageFetchFromMs, groupDerivativesContextMissingFetchRanges, getMissingClosedDerivativesSymbols, coverageKey, extendEdges, getCoinalyzeApiKey, getCoinalyzeBaseUrl, getRequestDelayMs, getRequestTimeoutMs, networkErrorCodes, getNestedErrorValue, getCoinalyzeErrorCause, isRetryableCoinalyzeFetchError, formatCoinalyzeRequestError, fetchJsonWithRateLimit, fetchCoinalyzeMarkets, selectBestMarket, buildMatches, normalizeMetricPoint, toSeriesMap, fetchMetricBatch, skippedBackfillResult2, backfillDerivativesContext, backfillDerivativesContextForBacktest, backfillDerivativesContextForSignals;
12371
12383
  var init_derivativesContextBackfill = __esm({
12372
12384
  "src/lib/derivativesContextBackfill.ts"() {
@@ -13670,7 +13682,7 @@ var init_coinMarketCapContextBackfill = __esm({
13670
13682
  };
13671
13683
  fetchCoinMarketCapIndexRows = async (params) => {
13672
13684
  const rows = [];
13673
- const maxChunkDays = 9;
13685
+ const maxChunkDays = 4;
13674
13686
  const totalChunks = Math.max(
13675
13687
  1,
13676
13688
  Math.ceil(
@@ -14107,11 +14119,27 @@ var init_coinMarketCapContextBackfill = __esm({
14107
14119
  toMs
14108
14120
  })
14109
14121
  );
14110
- const globalDailyReady = globalDailyCached || globalDailyBackfillCovered;
14111
- const referencesDailyReady = referencesDailyCached || referencesDailyBackfillCovered;
14112
- const exchangeLiquidityReady = exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered;
14113
- const fearGreedReady = fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered;
14114
- const indexesReady = indexesCached || indexesBackfillCovered;
14122
+ const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
14123
+ const globalDailyReady = ready(
14124
+ "cmc-global-1d",
14125
+ globalDailyCached || globalDailyBackfillCovered
14126
+ );
14127
+ const referencesDailyReady = ready(
14128
+ "cmc-reference_asset-1d",
14129
+ referencesDailyCached || referencesDailyBackfillCovered
14130
+ );
14131
+ const exchangeLiquidityReady = ready(
14132
+ "cmc-exchange_liquidity-1d",
14133
+ exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
14134
+ );
14135
+ const fearGreedReady = ready(
14136
+ "cmc-fear_greed-1d",
14137
+ fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
14138
+ );
14139
+ const indexesReady = ready(
14140
+ "cmc-index-1d",
14141
+ indexesCached || indexesBackfillCovered
14142
+ );
14115
14143
  let globalStatus = resolveBackfillStatus({
14116
14144
  cached: globalDailyCached,
14117
14145
  covered: globalDailyBackfillCovered
@@ -16343,7 +16371,9 @@ var init_workerPool = __esm({
16343
16371
  chunkTestSuite,
16344
16372
  getProgressSnapshot,
16345
16373
  initialCompletedTests = 0,
16346
- totalTests
16374
+ totalTests,
16375
+ onProgress,
16376
+ onIncomplete
16347
16377
  }) => {
16348
16378
  const chunks = chunkTestSuite(testSuite);
16349
16379
  const fastAiWorkerPgPoolMax = resolveFastAiWorkerPgPoolMax(
@@ -16359,7 +16389,9 @@ var init_workerPool = __esm({
16359
16389
  );
16360
16390
  let completedTests = initialCompletedTests;
16361
16391
  let renderedTests = 0;
16392
+ let pendingResults = 0;
16362
16393
  let isFinishing = false;
16394
+ let isInterrupted = false;
16363
16395
  let signalHandlersRemoved = false;
16364
16396
  const workers = /* @__PURE__ */ new Set();
16365
16397
  const stopWorkers = () => {
@@ -16370,6 +16402,7 @@ var init_workerPool = __esm({
16370
16402
  }
16371
16403
  };
16372
16404
  const handleInterrupt = (signal, exitCode) => {
16405
+ isInterrupted = true;
16373
16406
  stopWorkers();
16374
16407
  void Promise.resolve(onInterrupt?.(signal)).catch((error) => {
16375
16408
  console.error(
@@ -16390,15 +16423,16 @@ var init_workerPool = __esm({
16390
16423
  process.removeListener("SIGTERM", handleSigterm);
16391
16424
  };
16392
16425
  const maybeFinish = async () => {
16393
- if (isFinishing) {
16394
- return;
16395
- }
16396
- if (completedTests !== totalExpectedTests || workers.size > 0) {
16426
+ if (isFinishing || isInterrupted || workers.size > 0 || pendingResults > 0) {
16397
16427
  return;
16398
16428
  }
16399
16429
  isFinishing = true;
16400
16430
  try {
16401
- await onFinish();
16431
+ if (completedTests === totalExpectedTests) {
16432
+ await onFinish();
16433
+ } else {
16434
+ await onIncomplete?.();
16435
+ }
16402
16436
  } finally {
16403
16437
  cleanupSignalHandlers();
16404
16438
  }
@@ -16457,14 +16491,22 @@ var init_workerPool = __esm({
16457
16491
  return;
16458
16492
  }
16459
16493
  completedTests++;
16460
- await onMessage(msg);
16461
- if (completedTests % progressStep2 === 0 || completedTests === totalExpectedTests) {
16462
- tickProgress();
16494
+ onProgress?.(completedTests);
16495
+ pendingResults++;
16496
+ try {
16497
+ await onMessage(msg);
16498
+ if (completedTests % progressStep2 === 0 || completedTests === totalExpectedTests) {
16499
+ tickProgress();
16500
+ }
16501
+ } finally {
16502
+ pendingResults--;
16463
16503
  }
16504
+ await maybeFinish();
16464
16505
  });
16465
16506
  tester.on("error", (err) => {
16466
16507
  workers.delete(tester);
16467
16508
  onWorkerError(err?.message ?? String(err));
16509
+ void maybeFinish();
16468
16510
  });
16469
16511
  tester.on("exit", (code) => {
16470
16512
  workers.delete(tester);
@@ -16876,7 +16918,9 @@ var init_runnerCore = __esm({
16876
16918
  onFinish,
16877
16919
  initialCompletedTests = 0,
16878
16920
  totalTests,
16879
- backtestRunId
16921
+ backtestRunId,
16922
+ onProgress,
16923
+ onIncomplete
16880
16924
  }) => {
16881
16925
  markTestsStarted();
16882
16926
  const { testerWorkerPath, testerNeedsTsRuntime } = resolveTesterWorker();
@@ -16900,6 +16944,8 @@ var init_runnerCore = __esm({
16900
16944
  chunkTestSuite: (suite) => chunkTestSuiteBySymbol(suite, effectiveParallel),
16901
16945
  initialCompletedTests,
16902
16946
  totalTests,
16947
+ onProgress,
16948
+ onIncomplete,
16903
16949
  onInterrupt,
16904
16950
  onMessage: async (msg) => {
16905
16951
  if (msg.error) {
@@ -16955,10 +17001,116 @@ var init_runnerCore = __esm({
16955
17001
  }
16956
17002
  });
16957
17003
 
17004
+ // src/lib/backtest/observeRun.ts
17005
+ 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;
17006
+ var init_observeRun = __esm({
17007
+ "src/lib/backtest/observeRun.ts"() {
17008
+ "use strict";
17009
+ import_constants9 = require("@tradejs/core/constants");
17010
+ import_redis7 = require("@tradejs/infra/redis");
17011
+ import_logger = require("@tradejs/infra/logger");
17012
+ HEARTBEAT_MS = 2e3;
17013
+ ACTIVE_TTL_SECONDS = 30;
17014
+ LINKED_RUN_TTL_SECONDS = 30 * 24 * import_constants9.TTL_1H;
17015
+ 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}$/;
17016
+ MAX_VALUES_PER_PARAMETER = 12;
17017
+ MAX_VALUE_LENGTH = 500;
17018
+ summarizeBacktestParameters = (tests) => {
17019
+ const parameters = /* @__PURE__ */ new Map();
17020
+ for (const test of tests) {
17021
+ for (const [name, value] of Object.entries(test.strategyConfig)) {
17022
+ const serialized = JSON.stringify(value);
17023
+ if (serialized === void 0) continue;
17024
+ const parameter = parameters.get(name) ?? {
17025
+ values: /* @__PURE__ */ new Set(),
17026
+ truncated: false
17027
+ };
17028
+ parameters.set(name, parameter);
17029
+ if (parameter.values.has(serialized)) continue;
17030
+ if (parameter.values.size === MAX_VALUES_PER_PARAMETER || serialized.length > MAX_VALUE_LENGTH) {
17031
+ parameter.truncated = true;
17032
+ } else {
17033
+ parameter.values.add(serialized);
17034
+ }
17035
+ }
17036
+ }
17037
+ return [...parameters].map(([name, { values, truncated }]) => ({
17038
+ name,
17039
+ values: [...values],
17040
+ truncated
17041
+ }));
17042
+ };
17043
+ observeBacktestRun = async (manifest, initialCompleted, parallel) => {
17044
+ if (process.env.TRADEJS_BACKTEST_WEB_JOB === "1") return;
17045
+ const researchStudy = process.env.TRADEJS_RESEARCH_STUDY?.trim();
17046
+ const linkedStudy = researchStudy && RESEARCH_STUDY.test(researchStudy) ? researchStudy : void 0;
17047
+ if (researchStudy && !linkedStudy) {
17048
+ import_logger.logger.warn(
17049
+ "invalid TRADEJS_RESEARCH_STUDY; expected Strategy/YYYY-MM-DD-slug"
17050
+ );
17051
+ }
17052
+ const { testSuite } = manifest;
17053
+ const firstTest = testSuite[0];
17054
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
17055
+ const run = {
17056
+ id: manifest.runId,
17057
+ ...linkedStudy && { researchStudy: linkedStudy },
17058
+ userName: manifest.userName,
17059
+ strategyName: firstTest.strategyName,
17060
+ configId: manifest.config,
17061
+ connector: manifest.connectorName,
17062
+ interval: manifest.interval,
17063
+ startTime: manifest.window.start,
17064
+ endTime: manifest.window.end,
17065
+ symbols: [...new Set(testSuite.map((test) => test.symbol))],
17066
+ settings: {
17067
+ ...manifest.flags,
17068
+ parallel,
17069
+ ...firstTest.executionCosts && {
17070
+ executionCosts: JSON.stringify(firstTest.executionCosts)
17071
+ }
17072
+ },
17073
+ parameters: summarizeBacktestParameters(testSuite),
17074
+ status: "running",
17075
+ completed: initialCompleted,
17076
+ total: testSuite.length,
17077
+ startedAt,
17078
+ updatedAt: startedAt
17079
+ };
17080
+ const save = async (expire) => {
17081
+ run.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
17082
+ try {
17083
+ await import_redis7.cliBacktestRunStorage.put(run, expire);
17084
+ } catch (error) {
17085
+ import_logger.logger.warn("failed to publish CLI backtest progress: %s", String(error));
17086
+ }
17087
+ };
17088
+ await save(ACTIVE_TTL_SECONDS);
17089
+ let pending;
17090
+ const timer = setInterval(() => {
17091
+ pending ??= save(ACTIVE_TTL_SECONDS).finally(() => {
17092
+ pending = void 0;
17093
+ });
17094
+ }, HEARTBEAT_MS).unref();
17095
+ return {
17096
+ progress: (completed) => {
17097
+ run.completed = completed;
17098
+ },
17099
+ finish: async (status) => {
17100
+ clearInterval(timer);
17101
+ await pending;
17102
+ run.status = status;
17103
+ await save(linkedStudy ? LINKED_RUN_TTL_SECONDS : import_constants9.TTL_1H);
17104
+ }
17105
+ };
17106
+ };
17107
+ }
17108
+ });
17109
+
16958
17110
  // src/scripts/backtest.ts
16959
17111
  var backtest_exports = {};
16960
17112
  __export(backtest_exports, {
16961
- BACKTEST_PRELOAD_DAYS: () => import_constants9.BACKTEST_PRELOAD_DAYS,
17113
+ BACKTEST_PRELOAD_DAYS: () => import_constants10.BACKTEST_PRELOAD_DAYS,
16962
17114
  backtest: () => backtest,
16963
17115
  chunkTestSuiteBySymbol: () => chunkTestSuiteBySymbol,
16964
17116
  interval: () => interval,
@@ -16983,7 +17135,7 @@ __export(backtest_exports, {
16983
17135
  toStrategyConfigGrid: () => toStrategyConfigGrid,
16984
17136
  userName: () => userName
16985
17137
  });
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;
17138
+ 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
17139
  var init_backtest = __esm({
16988
17140
  "src/scripts/backtest.ts"() {
16989
17141
  "use strict";
@@ -16993,12 +17145,13 @@ var init_backtest = __esm({
16993
17145
  import_backtest4 = require("@tradejs/core/backtest");
16994
17146
  import_grid = require("@tradejs/core/grid");
16995
17147
  import_data = require("@tradejs/core/data");
16996
- import_redis7 = require("@tradejs/infra/redis");
16997
- import_constants9 = require("@tradejs/core/constants");
17148
+ import_redis8 = require("@tradejs/infra/redis");
17149
+ import_constants10 = require("@tradejs/core/constants");
16998
17150
  init_runnerCore();
16999
17151
  init_cliConfig();
17000
17152
  init_runState();
17001
17153
  init_checkpoint();
17154
+ init_observeRun();
17002
17155
  init_marketContextPrepare();
17003
17156
  if (process.argv.some(
17004
17157
  (arg) => arg === "--live" || String(arg).startsWith("--live=")
@@ -17134,8 +17287,8 @@ var init_backtest = __esm({
17134
17287
  if (!strategyName) {
17135
17288
  throw new Error("Strategy name not found");
17136
17289
  }
17137
- const backtestConfig = await (0, import_redis7.getData)(
17138
- import_redis7.redisKeys.backtestConfig(userName, flags5.config),
17290
+ const backtestConfig = await (0, import_redis8.getData)(
17291
+ import_redis8.redisKeys.backtestConfig(userName, flags5.config),
17139
17292
  null
17140
17293
  );
17141
17294
  if (!backtestConfig) {
@@ -17282,8 +17435,8 @@ var init_backtest = __esm({
17282
17435
  console.log(import_chalk15.default.gray(`full report: ${markdownReportPath}`));
17283
17436
  console.log("");
17284
17437
  if (!isFastMode || flags5.persistResults) {
17285
- await (0, import_redis7.setData)(
17286
- import_redis7.redisKeys.backtestResults(userName, flags5.config, timestamp),
17438
+ await (0, import_redis8.setData)(
17439
+ import_redis8.redisKeys.backtestResults(userName, flags5.config, timestamp),
17287
17440
  {
17288
17441
  config: flags5.config,
17289
17442
  mode: "config",
@@ -17303,11 +17456,10 @@ var init_backtest = __esm({
17303
17456
  errorTests: errorTests2
17304
17457
  },
17305
17458
  {
17306
- expire: import_constants9.TTL_1M
17459
+ expire: import_constants10.TTL_1M
17307
17460
  }
17308
17461
  );
17309
17462
  }
17310
- process.exit();
17311
17463
  };
17312
17464
  restoreCompletedBacktestResults = (completed) => {
17313
17465
  for (const { result } of completed) {
@@ -17388,6 +17540,56 @@ var init_backtest = __esm({
17388
17540
  log: (message) => console.log(import_chalk15.default.gray(message))
17389
17541
  });
17390
17542
  };
17543
+ runBacktestSuite = async (manifest, testSuite, initialCompletedTests = 0) => {
17544
+ const observation = await observeBacktestRun(
17545
+ manifest,
17546
+ initialCompletedTests,
17547
+ effectiveParallel
17548
+ );
17549
+ try {
17550
+ await executeTestSuite({
17551
+ testSuite,
17552
+ window: manifest.window,
17553
+ preloadStart: manifest.preloadStart,
17554
+ backtestRunId: manifest.runId,
17555
+ initialCompletedTests,
17556
+ totalTests: manifest.testSuite.length,
17557
+ onProgress: observation?.progress,
17558
+ onIncomplete: async () => {
17559
+ await observation?.finish("failed");
17560
+ await markBacktestRunStatus({ run: manifest, status: "interrupted" });
17561
+ process.exit(1);
17562
+ },
17563
+ onResult: async (result) => {
17564
+ await saveBacktestCheckpointResult({
17565
+ result,
17566
+ runId: manifest.runId,
17567
+ userName
17568
+ });
17569
+ trackTopResult(result);
17570
+ updateBestTickerResult(result);
17571
+ },
17572
+ onInterrupt: async () => {
17573
+ await observation?.finish("cancelled");
17574
+ await markBacktestRunStatus({ run: manifest, status: "interrupted" });
17575
+ },
17576
+ onFinish: async () => {
17577
+ try {
17578
+ await markBacktestRunStatus({ run: manifest, status: "completed" });
17579
+ await finishBacktest(manifest.testSuite);
17580
+ await observation?.finish("completed");
17581
+ process.exit();
17582
+ } catch (error) {
17583
+ await observation?.finish("failed");
17584
+ throw error;
17585
+ }
17586
+ }
17587
+ });
17588
+ } catch (error) {
17589
+ await observation?.finish("failed");
17590
+ throw error;
17591
+ }
17592
+ };
17391
17593
  backtest = async () => {
17392
17594
  resetRunState();
17393
17595
  const config2 = await loadBacktestConfig();
@@ -17402,33 +17604,10 @@ var init_backtest = __esm({
17402
17604
  if (!remainingSuite.length) {
17403
17605
  await markBacktestRunStatus({ run: manifest2, status: "completed" });
17404
17606
  await finishBacktest(manifest2.testSuite);
17405
- return;
17607
+ process.exit();
17406
17608
  }
17407
17609
  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
- });
17610
+ await runBacktestSuite(manifest2, remainingSuite, completed.length);
17432
17611
  return;
17433
17612
  }
17434
17613
  const preparedRun = await prepareRunEnvironment2(config2.strategyName);
@@ -17489,28 +17668,7 @@ var init_backtest = __esm({
17489
17668
  testSuite
17490
17669
  });
17491
17670
  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
- });
17671
+ await runBacktestSuite(manifest, testSuite);
17514
17672
  };
17515
17673
  main8 = backtest;
17516
17674
  }
@@ -18461,11 +18619,11 @@ var init_memoryProfile = __esm({
18461
18619
  });
18462
18620
 
18463
18621
  // src/lib/replay/portfolioReplayConnector.ts
18464
- var import_constants10, import_math, import_trade, UNKNOWN_STRATEGY, getStrategyName, getPositionPnlSnapshot, createPortfolioReplayConnector;
18622
+ var import_constants11, import_math, import_trade, UNKNOWN_STRATEGY, getStrategyName, getPositionPnlSnapshot, createPortfolioReplayConnector;
18465
18623
  var init_portfolioReplayConnector = __esm({
18466
18624
  "src/lib/replay/portfolioReplayConnector.ts"() {
18467
18625
  "use strict";
18468
- import_constants10 = require("@tradejs/core/constants");
18626
+ import_constants11 = require("@tradejs/core/constants");
18469
18627
  import_math = require("@tradejs/core/math");
18470
18628
  import_trade = require("@tradejs/core/trade");
18471
18629
  init_support2();
@@ -18493,7 +18651,7 @@ var init_portfolioReplayConnector = __esm({
18493
18651
  };
18494
18652
  createPortfolioReplayConnector = (connector, observeEquity = false) => {
18495
18653
  let state = {};
18496
- let amount = import_constants10.INITIAL_BACKTEST_AMOUNT;
18654
+ let amount = import_constants11.INITIAL_BACKTEST_AMOUNT;
18497
18655
  let executionTimestamp = null;
18498
18656
  const positionsBySymbol = /* @__PURE__ */ new Map();
18499
18657
  const currentPriceBySymbol = /* @__PURE__ */ new Map();
@@ -18559,7 +18717,7 @@ var init_portfolioReplayConnector = __esm({
18559
18717
  price,
18560
18718
  qty
18561
18719
  }) => {
18562
- const fee = price * qty * import_constants10.FEE_PERCENT;
18720
+ const fee = price * qty * import_constants11.FEE_PERCENT;
18563
18721
  return {
18564
18722
  fee,
18565
18723
  profit: grossProfit - fee
@@ -18926,7 +19084,7 @@ var init_portfolioReplayConnector = __esm({
18926
19084
  },
18927
19085
  getMarkedEquity: () => {
18928
19086
  if (!equityMarks) return null;
18929
- let equity = amount - import_constants10.INITIAL_BACKTEST_AMOUNT;
19087
+ let equity = amount - import_constants11.INITIAL_BACKTEST_AMOUNT;
18930
19088
  for (const { position } of positionsBySymbol.values()) {
18931
19089
  const mark = equityMarks.get(position.symbol);
18932
19090
  if (mark == null || !Number.isFinite(mark)) return null;
@@ -19328,12 +19486,12 @@ var init_historicalSignalsReplayExecution = __esm({
19328
19486
  });
19329
19487
 
19330
19488
  // src/lib/replay/historicalSignalsReplayResults.ts
19331
- var import_backtest5, import_constants11, emptyStat, positionLogForStats, calculateReplayStat, byTimestamp, byPositionClose, collectHistoricalReplayResult, compactHistoricalReplayResultForPortfolio, mergeHistoricalReplayResults;
19489
+ var import_backtest5, import_constants12, emptyStat, positionLogForStats, calculateReplayStat, byTimestamp, byPositionClose, collectHistoricalReplayResult, compactHistoricalReplayResultForPortfolio, mergeHistoricalReplayResults;
19332
19490
  var init_historicalSignalsReplayResults = __esm({
19333
19491
  "src/lib/replay/historicalSignalsReplayResults.ts"() {
19334
19492
  "use strict";
19335
19493
  import_backtest5 = require("@tradejs/core/backtest");
19336
- import_constants11 = require("@tradejs/core/constants");
19494
+ import_constants12 = require("@tradejs/core/constants");
19337
19495
  emptyStat = () => ({
19338
19496
  orders: 0,
19339
19497
  wins: 0,
@@ -19342,7 +19500,7 @@ var init_historicalSignalsReplayResults = __esm({
19342
19500
  amount: 0
19343
19501
  });
19344
19502
  positionLogForStats = (positionLog) => {
19345
- let amount = import_constants11.INITIAL_BACKTEST_AMOUNT;
19503
+ let amount = import_constants12.INITIAL_BACKTEST_AMOUNT;
19346
19504
  return [...positionLog].sort(
19347
19505
  (left, right) => left.close.timestamp - right.close.timestamp || left.open.timestamp - right.open.timestamp
19348
19506
  ).map((position) => {
@@ -19436,7 +19594,7 @@ var init_historicalSignalsReplayResults = __esm({
19436
19594
  });
19437
19595
 
19438
19596
  // 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;
19597
+ 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
19598
  var init_historicalSignalsReplay = __esm({
19441
19599
  "src/lib/replay/historicalSignalsReplay.ts"() {
19442
19600
  "use strict";
@@ -19447,8 +19605,8 @@ var init_historicalSignalsReplay = __esm({
19447
19605
  import_node_module2 = require("module");
19448
19606
  import_strategies5 = require("@tradejs/core/strategies");
19449
19607
  import_time4 = require("@tradejs/core/time");
19450
- import_logger = require("@tradejs/infra/logger");
19451
- import_redis8 = require("@tradejs/infra/redis");
19608
+ import_logger2 = require("@tradejs/infra/logger");
19609
+ import_redis9 = require("@tradejs/infra/redis");
19452
19610
  import_connectors6 = require("@tradejs/node/connectors");
19453
19611
  import_cli5 = require("@tradejs/node/cli");
19454
19612
  import_strategies6 = require("@tradejs/node/strategies");
@@ -19515,8 +19673,8 @@ var init_historicalSignalsReplay = __esm({
19515
19673
  `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
19674
  );
19517
19675
  }
19518
- const strategyResults = await (0, import_redis8.getData)(
19519
- import_redis8.redisKeys.strategyResults(replayUserName, strategyName),
19676
+ const strategyResults = await (0, import_redis9.getData)(
19677
+ import_redis9.redisKeys.strategyResults(replayUserName, strategyName),
19520
19678
  {}
19521
19679
  );
19522
19680
  return {
@@ -19721,7 +19879,7 @@ var init_historicalSignalsReplay = __esm({
19721
19879
  releaseHistoricalReplayPlan(plan);
19722
19880
  memory?.("execution:released");
19723
19881
  const artifacts = replayConnector.getReplayArtifacts();
19724
- import_logger.logger.info(
19882
+ import_logger2.logger.info(
19725
19883
  import_chalk17.default.gray(
19726
19884
  `signals replay historical cycles: ${plan.orderedTimestamps.length} (aborted=${execution.abortedCycles}) done in ${((Date.now() - startedAt) / 1e3).toFixed(1)}s`
19727
19885
  )
@@ -20297,11 +20455,11 @@ var init_paritySummary = __esm({
20297
20455
  });
20298
20456
 
20299
20457
  // 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;
20458
+ 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
20459
  var init_runtimeSignalsStorage = __esm({
20302
20460
  "src/lib/runtimeSignalsStorage.ts"() {
20303
20461
  "use strict";
20304
- import_constants12 = require("@tradejs/core/constants");
20462
+ import_constants13 = require("@tradejs/core/constants");
20305
20463
  import_data4 = require("@tradejs/core/data");
20306
20464
  import_time5 = require("@tradejs/core/time");
20307
20465
  appendRuntimeSignalEvaluationRun = (runs = [], evaluation) => {
@@ -20336,8 +20494,8 @@ var init_runtimeSignalsStorage = __esm({
20336
20494
  };
20337
20495
  SECONDS_PER_DAY = 86400;
20338
20496
  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;
20497
+ DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS = import_constants13.TTL_3D;
20498
+ RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS = import_constants13.TTL_1M;
20341
20499
  parsePositiveNumber = (value) => {
20342
20500
  if (value == null || value === "") {
20343
20501
  return null;
@@ -20470,11 +20628,11 @@ var init_runtimeSignalsStorage = __esm({
20470
20628
  });
20471
20629
 
20472
20630
  // src/lib/runtimeSignalsLoader.ts
20473
- var import_redis9, isSignalRecord, isRuntimeSignalEvaluationRecord, sortByTimestamp, filterBucketKeysByWindow, loadRuntimeSignals, loadRuntimeSignalEvaluations, loadRuntimeLineageScopes, parseBucketKey, loadRuntimeSignalEvaluationStatsBuckets;
20631
+ var import_redis10, isSignalRecord, isRuntimeSignalEvaluationRecord, sortByTimestamp, filterBucketKeysByWindow, loadRuntimeSignals, loadRuntimeSignalEvaluations, loadRuntimeLineageScopes, parseBucketKey, loadRuntimeSignalEvaluationStatsBuckets;
20474
20632
  var init_runtimeSignalsLoader = __esm({
20475
20633
  "src/lib/runtimeSignalsLoader.ts"() {
20476
20634
  "use strict";
20477
- import_redis9 = require("@tradejs/infra/redis");
20635
+ import_redis10 = require("@tradejs/infra/redis");
20478
20636
  init_runtimeSignalsStorage();
20479
20637
  isSignalRecord = (value) => {
20480
20638
  if (!value || typeof value !== "object") {
@@ -20512,14 +20670,14 @@ var init_runtimeSignalsLoader = __esm({
20512
20670
  startTime,
20513
20671
  endTime
20514
20672
  } = {}) => {
20515
- const bucketPrefix = import_redis9.redisKeys.runtimeSignalBuckets(userName3);
20673
+ const bucketPrefix = import_redis10.redisKeys.runtimeSignalBuckets(userName3);
20516
20674
  const bucketKeys = filterBucketKeysByWindow(
20517
- await (0, import_redis9.getKeys)(bucketPrefix),
20675
+ await (0, import_redis10.getKeys)(bucketPrefix),
20518
20676
  bucketPrefix,
20519
20677
  startTime,
20520
20678
  endTime
20521
20679
  );
20522
- const refs = (await Promise.all(bucketKeys.map((key2) => (0, import_redis9.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalBucketRef);
20680
+ const refs = (await Promise.all(bucketKeys.map((key2) => (0, import_redis10.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalBucketRef);
20523
20681
  const seen = /* @__PURE__ */ new Set();
20524
20682
  const payloads = await Promise.all(
20525
20683
  refs.map(async (ref) => {
@@ -20528,8 +20686,8 @@ var init_runtimeSignalsLoader = __esm({
20528
20686
  return null;
20529
20687
  }
20530
20688
  seen.add(dedupeKey);
20531
- const signal = await (0, import_redis9.getData)(
20532
- import_redis9.redisKeys.storeSignal(ref.symbol, ref.signalId),
20689
+ const signal = await (0, import_redis10.getData)(
20690
+ import_redis10.redisKeys.storeSignal(ref.symbol, ref.signalId),
20533
20691
  null
20534
20692
  );
20535
20693
  return isSignalRecord(signal) ? signal : null;
@@ -20541,14 +20699,14 @@ var init_runtimeSignalsLoader = __esm({
20541
20699
  startTime,
20542
20700
  endTime
20543
20701
  } = {}) => {
20544
- const bucketPrefix = import_redis9.redisKeys.runtimeSignalEvaluationBuckets(userName3);
20702
+ const bucketPrefix = import_redis10.redisKeys.runtimeSignalEvaluationBuckets(userName3);
20545
20703
  const bucketKeys = filterBucketKeysByWindow(
20546
- await (0, import_redis9.getKeys)(bucketPrefix),
20704
+ await (0, import_redis10.getKeys)(bucketPrefix),
20547
20705
  bucketPrefix,
20548
20706
  startTime,
20549
20707
  endTime
20550
20708
  );
20551
- const evaluations = (await Promise.all(bucketKeys.map((key2) => (0, import_redis9.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalEvaluationRecord);
20709
+ const evaluations = (await Promise.all(bucketKeys.map((key2) => (0, import_redis10.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalEvaluationRecord);
20552
20710
  const deduped = /* @__PURE__ */ new Map();
20553
20711
  for (const evaluation of evaluations) {
20554
20712
  deduped.set(evaluation.evaluationId, evaluation);
@@ -20561,8 +20719,8 @@ var init_runtimeSignalsLoader = __esm({
20561
20719
  }) => {
20562
20720
  const records = (await Promise.all(
20563
20721
  (0, import_time5.getRuntimeStorageDayKeys)(startTime, endTime).map(
20564
- (dayKey) => (0, import_redis9.getHashJsonValues)(
20565
- import_redis9.redisKeys.runtimeLineageScopeBucket(userName3, dayKey)
20722
+ (dayKey) => (0, import_redis10.getHashJsonValues)(
20723
+ import_redis10.redisKeys.runtimeLineageScopeBucket(userName3, dayKey)
20566
20724
  )
20567
20725
  )
20568
20726
  )).flat().filter(
@@ -20591,8 +20749,8 @@ var init_runtimeSignalsLoader = __esm({
20591
20749
  };
20592
20750
  };
20593
20751
  loadRuntimeSignalEvaluationStatsBuckets = async (userName3) => {
20594
- const prefix = import_redis9.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3);
20595
- const keys = await (0, import_redis9.getKeys)(prefix);
20752
+ const prefix = import_redis10.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3);
20753
+ const keys = await (0, import_redis10.getKeys)(prefix);
20596
20754
  const entries = await Promise.all(
20597
20755
  keys.map(async (key2) => {
20598
20756
  const parsedKey = parseBucketKey(prefix, key2);
@@ -20602,7 +20760,7 @@ var init_runtimeSignalsLoader = __esm({
20602
20760
  return {
20603
20761
  key: key2,
20604
20762
  ...parsedKey,
20605
- stats: parseRuntimeSignalStatsBucket(await (0, import_redis9.getHashData)(key2))
20763
+ stats: parseRuntimeSignalStatsBucket(await (0, import_redis10.getHashData)(key2))
20606
20764
  };
20607
20765
  })
20608
20766
  );
@@ -20612,13 +20770,13 @@ var init_runtimeSignalsLoader = __esm({
20612
20770
  });
20613
20771
 
20614
20772
  // 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;
20773
+ 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
20774
  var init_runtimeTradeSync = __esm({
20617
20775
  "src/lib/runtimeTradeSync.ts"() {
20618
20776
  "use strict";
20619
- import_constants13 = require("@tradejs/core/constants");
20777
+ import_constants14 = require("@tradejs/core/constants");
20620
20778
  import_time6 = require("@tradejs/core/time");
20621
- import_redis10 = require("@tradejs/infra/redis");
20779
+ import_redis11 = require("@tradejs/infra/redis");
20622
20780
  CLOSED_PNL_LIMIT = 100;
20623
20781
  CLOSED_PNL_RECONCILIATION_LOOKBACK_MS = 24 * 60 * 60 * 1e3;
20624
20782
  EXCHANGE_HISTORY_MAX_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
@@ -20751,7 +20909,7 @@ var init_runtimeTradeSync = __esm({
20751
20909
  const activeTradeKeys = [
20752
20910
  ...new Set(
20753
20911
  trades.filter((trade) => isRuntimeTradeInConnectorScope(trade, connector)).map(
20754
- (trade) => import_redis10.redisKeys.runtimeActiveTrade(
20912
+ (trade) => import_redis11.redisKeys.runtimeActiveTrade(
20755
20913
  userName3,
20756
20914
  trade.symbol,
20757
20915
  trade.deploymentId ?? trade.accountId
@@ -20761,7 +20919,7 @@ var init_runtimeTradeSync = __esm({
20761
20919
  ];
20762
20920
  await Promise.all(
20763
20921
  activeTradeKeys.map(async (key2) => {
20764
- const activeRef = await (0, import_redis10.getData)(key2, null);
20922
+ const activeRef = await (0, import_redis11.getData)(key2, null);
20765
20923
  activeOrderIdByKey.set(
20766
20924
  key2,
20767
20925
  typeof activeRef?.orderId === "string" ? activeRef.orderId : null
@@ -20790,7 +20948,7 @@ var init_runtimeTradeSync = __esm({
20790
20948
  syncedTrades.push(trade);
20791
20949
  continue;
20792
20950
  }
20793
- const activeTradeKey = import_redis10.redisKeys.runtimeActiveTrade(
20951
+ const activeTradeKey = import_redis11.redisKeys.runtimeActiveTrade(
20794
20952
  userName3,
20795
20953
  trade.symbol,
20796
20954
  trade.deploymentId ?? trade.accountId
@@ -20814,15 +20972,15 @@ var init_runtimeTradeSync = __esm({
20814
20972
  currentPnl: openPosition.unrealizedPnl,
20815
20973
  lastSyncedAt: endTime
20816
20974
  };
20817
- await (0, import_redis10.setData)(
20818
- import_redis10.redisKeys.runtimeTrade(userName3, trade.orderId),
20975
+ await (0, import_redis11.setData)(
20976
+ import_redis11.redisKeys.runtimeTrade(userName3, trade.orderId),
20819
20977
  nextTrade2,
20820
20978
  {
20821
20979
  expire: 0
20822
20980
  }
20823
20981
  );
20824
- await (0, import_redis10.setHashJsonField)(
20825
- import_redis10.redisKeys.runtimeTradeBucket(
20982
+ await (0, import_redis11.setHashJsonField)(
20983
+ import_redis11.redisKeys.runtimeTradeBucket(
20826
20984
  userName3,
20827
20985
  (0, import_time6.getRuntimeStorageDayKey)(trade.entryTimestamp)
20828
20986
  ),
@@ -20856,28 +21014,28 @@ var init_runtimeTradeSync = __esm({
20856
21014
  lastSyncedAt: endTime
20857
21015
  };
20858
21016
  await Promise.all([
20859
- (0, import_redis10.setData)(import_redis10.redisKeys.runtimeTrade(userName3, trade.orderId), nextTrade, {
20860
- expire: import_constants13.TTL_1M
21017
+ (0, import_redis11.setData)(import_redis11.redisKeys.runtimeTrade(userName3, trade.orderId), nextTrade, {
21018
+ expire: import_constants14.TTL_1M
20861
21019
  }),
20862
- (0, import_redis10.setHashJsonField)(
20863
- import_redis10.redisKeys.runtimeTradeBucket(
21020
+ (0, import_redis11.setHashJsonField)(
21021
+ import_redis11.redisKeys.runtimeTradeBucket(
20864
21022
  userName3,
20865
21023
  (0, import_time6.getRuntimeStorageDayKey)(trade.entryTimestamp)
20866
21024
  ),
20867
21025
  trade.orderId,
20868
21026
  nextTrade,
20869
- { expire: import_constants13.TTL_1M }
21027
+ { expire: import_constants14.TTL_1M }
20870
21028
  ),
20871
- (0, import_redis10.setHashJsonField)(
20872
- import_redis10.redisKeys.runtimeClosedTradeBucket(
21029
+ (0, import_redis11.setHashJsonField)(
21030
+ import_redis11.redisKeys.runtimeClosedTradeBucket(
20873
21031
  userName3,
20874
21032
  (0, import_time6.getRuntimeStorageDayKey)(nextTrade.exitTimestamp)
20875
21033
  ),
20876
21034
  trade.orderId,
20877
21035
  nextTrade,
20878
- { expire: import_constants13.TTL_1M }
21036
+ { expire: import_constants14.TTL_1M }
20879
21037
  ),
20880
- ...isCurrentActiveTrade ? [(0, import_redis10.delKey)(activeTradeKey)] : []
21038
+ ...isCurrentActiveTrade ? [(0, import_redis11.delKey)(activeTradeKey)] : []
20881
21039
  ]);
20882
21040
  syncedTrades.push(nextTrade);
20883
21041
  }
@@ -24412,16 +24570,16 @@ ${comparison.limitations.join(" ")}
24412
24570
  });
24413
24571
 
24414
24572
  // 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;
24573
+ var import_chalk21, import_constants15, import_data6, import_time8, import_redis12, import_candles2, import_runtimeStrategies4, import_strategies7, prepareReplayBinanceMarketContext, replayMarketContextInterval, cachedTickerSymbols, finishReplay, replayBacktest;
24416
24574
  var init_replayRunner = __esm({
24417
24575
  "src/scripts/replayRunner.ts"() {
24418
24576
  "use strict";
24419
24577
  init_historicalSignalsReplayPreparation();
24420
24578
  import_chalk21 = __toESM(require("chalk"));
24421
- import_constants14 = require("@tradejs/core/constants");
24579
+ import_constants15 = require("@tradejs/core/constants");
24422
24580
  import_data6 = require("@tradejs/core/data");
24423
24581
  import_time8 = require("@tradejs/core/time");
24424
- import_redis11 = require("@tradejs/infra/redis");
24582
+ import_redis12 = require("@tradejs/infra/redis");
24425
24583
  import_candles2 = require("@tradejs/infra/timescale/candles");
24426
24584
  import_runtimeStrategies4 = require("@tradejs/node/runtimeStrategies");
24427
24585
  import_strategies7 = require("@tradejs/node/strategies");
@@ -24475,12 +24633,12 @@ var init_replayRunner = __esm({
24475
24633
  ...connectorName.toLowerCase() === "bybit" ? ["ByBit"] : []
24476
24634
  ];
24477
24635
  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)
24636
+ import_redis12.redisKeys.tickerUniverse(replayUserName, name, universe, accountId),
24637
+ import_redis12.redisKeys.tickerUniverse(replayUserName, name, universe, "default"),
24638
+ import_redis12.redisKeys.tickerUniverse(replayUserName, name)
24481
24639
  ]);
24482
24640
  for (const key2 of [...new Set(keys)]) {
24483
- const cached = await (0, import_redis11.getData)(key2, null);
24641
+ const cached = await (0, import_redis12.getData)(key2, null);
24484
24642
  const symbols = (cached?.tickers ?? []).map(
24485
24643
  (ticker) => String(ticker.symbol ?? "").trim().toUpperCase()
24486
24644
  ).filter(Boolean);
@@ -24522,7 +24680,7 @@ var init_replayRunner = __esm({
24522
24680
  replayResult.orderLog[replayResult.orderLog.length - 1]?.timestamp ?? finishedAt.getTime()
24523
24681
  )}`
24524
24682
  }) : null;
24525
- const replayKey = import_redis11.redisKeys.backtestResults(
24683
+ const replayKey = import_redis12.redisKeys.backtestResults(
24526
24684
  replayUserName,
24527
24685
  REPLAY_RESULTS_CONFIG,
24528
24686
  timestamp
@@ -24556,7 +24714,7 @@ var init_replayRunner = __esm({
24556
24714
  console.log(import_chalk21.default.green(`Portfolio report: ${portfolioReport.html}`));
24557
24715
  console.log(import_chalk21.default.green(`Portfolio report JSON: ${portfolioReport.json}`));
24558
24716
  }
24559
- await (0, import_redis11.setData)(
24717
+ await (0, import_redis12.setData)(
24560
24718
  replayKey,
24561
24719
  {
24562
24720
  config: REPLAY_RESULTS_CONFIG,
@@ -24583,17 +24741,17 @@ var init_replayRunner = __esm({
24583
24741
  ...portfolioReport ? { portfolioReport } : {}
24584
24742
  },
24585
24743
  {
24586
- expire: import_constants14.TTL_1M
24744
+ expire: import_constants15.TTL_1M
24587
24745
  }
24588
24746
  );
24589
24747
  if (replayChartSnapshot) {
24590
24748
  await Promise.all(
24591
24749
  replayChartSnapshot.strategies.map(
24592
- (card) => (0, import_redis11.setData)(
24593
- import_redis11.redisKeys.strategyChartCard(replayUserName, "replay", card.cardId),
24750
+ (card) => (0, import_redis12.setData)(
24751
+ import_redis12.redisKeys.strategyChartCard(replayUserName, "replay", card.cardId),
24594
24752
  card,
24595
24753
  {
24596
- expire: import_constants14.TTL_1M
24754
+ expire: import_constants15.TTL_1M
24597
24755
  }
24598
24756
  )
24599
24757
  )
@@ -25045,7 +25203,7 @@ var init_binanceMarketIngest = __esm({
25045
25203
  import_client4 = require("@tradejs/infra/timescale/client");
25046
25204
  init_binanceMarketData();
25047
25205
  import_args9.default.example(
25048
- "yarn cli:node8g binance:market-ingest --all --symbols BTCUSDT,ETHUSDT --days 0.05 --interval 1m --write",
25206
+ "yarn cli:node8g binance:market-ingest --all --symbols BTCUSDT,ETHUSDT --days 0.05 --interval 15m --write",
25049
25207
  "Ingest Binance public market breadth and historical aggTrades buckets"
25050
25208
  );
25051
25209
  import_args9.default.option(
@@ -25053,7 +25211,7 @@ var init_binanceMarketIngest = __esm({
25053
25211
  "Comma-separated target symbols",
25054
25212
  "BTCUSDT,ETHUSDT"
25055
25213
  );
25056
- import_args9.default.option(["i", "interval"], "Aggregation interval: 1m,5m,15m,1h", "1m");
25214
+ import_args9.default.option(["i", "interval"], "Aggregation interval: 5m,15m,1h", "15m");
25057
25215
  import_args9.default.option(["d", "days"], "Lookback window in days", "1");
25058
25216
  import_args9.default.option(["h", "hours"], "Lookback window in hours; overrides --days");
25059
25217
  import_args9.default.option(["a", "aggTrades"], "Fetch and bucket Binance aggTrades");
@@ -25087,7 +25245,6 @@ var init_binanceMarketIngest = __esm({
25087
25245
  };
25088
25246
  sleep4 = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
25089
25247
  intervalToConnectorInterval = (interval4) => {
25090
- if (interval4 === "1m") return "1";
25091
25248
  if (interval4 === "5m") return "5";
25092
25249
  if (interval4 === "15m") return "15";
25093
25250
  return "60";
@@ -25143,6 +25300,7 @@ var init_binanceMarketIngest = __esm({
25143
25300
  main11 = async () => {
25144
25301
  const symbols = normalizeBinanceSymbols(flags7.symbols);
25145
25302
  const interval4 = normalizeMarketFeatureInterval(flags7.interval);
25303
+ if (interval4 === "1m") throw new Error("Use interval 5m, 15m, or 1h");
25146
25304
  const hours = flags7.hours == null ? null : asFloat2(flags7.hours, 0);
25147
25305
  const days = hours != null && hours > 0 ? hours / 24 : asFloat2(flags7.days, 1);
25148
25306
  const breadthUniverses = (0, import_strategies9.getBinanceBreadthUniverses)();
@@ -25256,7 +25414,7 @@ var init_binanceMarketIngest = __esm({
25256
25414
  });
25257
25415
 
25258
25416
  // 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;
25417
+ var import_lodash, import_connectors10, import_data7, import_strategies10, import_async3, import_constants16, import_time9, import_logger3, import_redis13, projectRoot4, runBot;
25260
25418
  var init_runBot = __esm({
25261
25419
  "src/lib/runBot.ts"() {
25262
25420
  "use strict";
@@ -25265,33 +25423,33 @@ var init_runBot = __esm({
25265
25423
  import_data7 = require("@tradejs/core/data");
25266
25424
  import_strategies10 = require("@tradejs/node/strategies");
25267
25425
  import_async3 = require("@tradejs/core/async");
25268
- import_constants15 = require("@tradejs/core/constants");
25426
+ import_constants16 = require("@tradejs/core/constants");
25269
25427
  import_time9 = require("@tradejs/core/time");
25270
- import_logger2 = require("@tradejs/infra/logger");
25271
- import_redis12 = require("@tradejs/infra/redis");
25428
+ import_logger3 = require("@tradejs/infra/logger");
25429
+ import_redis13 = require("@tradejs/infra/redis");
25272
25430
  projectRoot4 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
25273
25431
  runBot = async () => {
25274
25432
  const botResults = [];
25275
- const preloadStart = (0, import_time9.getTimestamp)(import_constants15.BOT_PRELOAD_DAYS);
25433
+ const preloadStart = (0, import_time9.getTimestamp)(import_constants16.BOT_PRELOAD_DAYS);
25276
25434
  const end = (0, import_time9.getTimestamp)();
25277
- const keys = await (0, import_redis12.getKeys)(import_redis12.redisKeys.botsPrefix());
25435
+ const keys = await (0, import_redis13.getKeys)(import_redis13.redisKeys.botsPrefix());
25278
25436
  const botKeys = keys.filter((key2) => key2.endsWith(":bots"));
25279
25437
  await (0, import_async3.delay)(5e3);
25280
- import_logger2.logger.log("info", "files count: %s", botKeys.length);
25438
+ import_logger3.logger.log("info", "files count: %s", botKeys.length);
25281
25439
  for await (const key2 of botKeys) {
25282
25440
  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));
25441
+ import_logger3.logger.log("info", "user: %s", userName3);
25442
+ const botConfig = await (0, import_redis13.getData)(import_redis13.redisKeys.bots(userName3));
25285
25443
  if (import_lodash.default.isEmpty(botConfig)) {
25286
- import_logger2.logger.log("error", "botConfig is empty: %s", userName3);
25444
+ import_logger3.logger.log("error", "botConfig is empty: %s", userName3);
25287
25445
  continue;
25288
25446
  }
25289
- import_logger2.logger.log("info", "bots count: %s", botConfig.length);
25447
+ import_logger3.logger.log("info", "bots count: %s", botConfig.length);
25290
25448
  for await (const bot of botConfig) {
25291
25449
  const { symbol, strategyName, strategyConfig, connectorName, disabled } = bot;
25292
- import_logger2.logger.log("info", "bot %s", symbol);
25450
+ import_logger3.logger.log("info", "bot %s", symbol);
25293
25451
  if (disabled) {
25294
- import_logger2.logger.log("error", "bot %s disabled", symbol);
25452
+ import_logger3.logger.log("error", "bot %s disabled", symbol);
25295
25453
  continue;
25296
25454
  }
25297
25455
  try {
@@ -25371,7 +25529,7 @@ var init_runBot = __esm({
25371
25529
  btcCoinbaseData,
25372
25530
  connector
25373
25531
  });
25374
- import_logger2.logger.log("info", "strategy created");
25532
+ import_logger3.logger.log("info", "strategy created");
25375
25533
  if (!candle || !btcCandle) {
25376
25534
  throw new Error("Candle is empty");
25377
25535
  }
@@ -25381,11 +25539,11 @@ var init_runBot = __esm({
25381
25539
  status: JSON.stringify(status)
25382
25540
  });
25383
25541
  } catch (err) {
25384
- import_logger2.logger.log("error", "bot %s error: %s", bot.symbol, (0, import_data7.toJson)(err, false));
25542
+ import_logger3.logger.log("error", "bot %s error: %s", bot.symbol, (0, import_data7.toJson)(err, false));
25385
25543
  }
25386
25544
  }
25387
25545
  }
25388
- import_logger2.logger.log("info", "botResults: %s", (0, import_data7.toJson)(botResults, true));
25546
+ import_logger3.logger.log("info", "botResults: %s", (0, import_data7.toJson)(botResults, true));
25389
25547
  return botResults;
25390
25548
  };
25391
25549
  }
@@ -25809,7 +25967,7 @@ var cleanTests_exports = {};
25809
25967
  __export(cleanTests_exports, {
25810
25968
  main: () => main16
25811
25969
  });
25812
- var import_args13, import_promises20, import_path7, import_chalk25, import_cli8, import_backtestArtifacts2, import_redis13, flags11, extractUsers, getUsersToClean, cleanUserTests, main16;
25970
+ var import_args13, import_promises20, import_path7, import_chalk25, import_cli8, import_backtestArtifacts2, import_redis14, flags11, extractUsers, getUsersToClean, cleanUserTests, main16;
25813
25971
  var init_cleanTests = __esm({
25814
25972
  "src/scripts/cleanTests.ts"() {
25815
25973
  "use strict";
@@ -25819,7 +25977,7 @@ var init_cleanTests = __esm({
25819
25977
  import_chalk25 = __toESM(require("chalk"));
25820
25978
  import_cli8 = require("@tradejs/node/cli");
25821
25979
  import_backtestArtifacts2 = require("@tradejs/infra/backtestArtifacts");
25822
- import_redis13 = require("@tradejs/infra/redis");
25980
+ import_redis14 = require("@tradejs/infra/redis");
25823
25981
  import_args13.default.option(["U", "user"], "Clean tests for user", "");
25824
25982
  import_args13.default.option(["C", "cache"], "Clean only cache keys", false);
25825
25983
  flags11 = import_args13.default.parse(process.argv);
@@ -25845,7 +26003,7 @@ var init_cleanTests = __esm({
25845
26003
  if (userName3) {
25846
26004
  return [userName3];
25847
26005
  }
25848
- const keys = await (0, import_redis13.getKeys)(import_redis13.redisKeys.users());
26006
+ const keys = await (0, import_redis14.getKeys)(import_redis14.redisKeys.users());
25849
26007
  return extractUsers(keys);
25850
26008
  };
25851
26009
  cleanUserTests = async (userName3) => {
@@ -25894,6 +26052,184 @@ var init_cleanTests = __esm({
25894
26052
  }
25895
26053
  });
25896
26054
 
26055
+ // src/scripts/coverageBackfill.ts
26056
+ var coverageBackfill_exports = {};
26057
+ __export(coverageBackfill_exports, {
26058
+ main: () => main17
26059
+ });
26060
+ async function fetchTarget(userName3, request, target, loaded) {
26061
+ const { dataset, end } = target;
26062
+ const { series, day } = request;
26063
+ const endMs = end - 1;
26064
+ const interval4 = dataset.interval;
26065
+ const missing = (time2) => time2 >= day && time2 < end && !loaded.has(time2);
26066
+ if (dataset.provider === "CoinMarketCap") {
26067
+ await backfillCoinMarketCapContext({
26068
+ userName: userName3,
26069
+ startMs: day,
26070
+ preloadStartMs: day,
26071
+ endMs: end,
26072
+ repairDataset: dataset.id
26073
+ });
26074
+ return;
26075
+ }
26076
+ if (dataset.provider === "Coinalyze") {
26077
+ if (interval4 !== "15m" && interval4 !== "1h") return;
26078
+ const { apiKey, marketSymbol } = await resolveCoinalyzeBackfillMarket(
26079
+ userName3,
26080
+ series
26081
+ );
26082
+ if (!marketSymbol) return;
26083
+ const { derivativesRows = [] } = await import_connectors11.marketDataProviders.coinalyze.fetchWindow({
26084
+ symbol: series,
26085
+ marketSymbol,
26086
+ apiKey,
26087
+ interval: interval4,
26088
+ fromMs: day,
26089
+ toMs: endMs
26090
+ });
26091
+ await (0, import_derivatives2.upsertDerivatives)(
26092
+ derivativesRows.filter(({ ts }) => missing(ts.getTime())).flatMap((row) => {
26093
+ const { symbol, ts, interval: interval5, source } = row;
26094
+ if (dataset.id.startsWith("coinalyze-open-interest-")) {
26095
+ return row.openInterest == null ? [] : [
26096
+ {
26097
+ symbol,
26098
+ ts,
26099
+ interval: interval5,
26100
+ source,
26101
+ openInterest: row.openInterest
26102
+ }
26103
+ ];
26104
+ }
26105
+ if (dataset.id.startsWith("coinalyze-funding-")) {
26106
+ return row.fundingRate == null ? [] : [
26107
+ {
26108
+ symbol,
26109
+ ts,
26110
+ interval: interval5,
26111
+ source,
26112
+ fundingRate: row.fundingRate
26113
+ }
26114
+ ];
26115
+ }
26116
+ const { liqLong, liqShort, liqTotal } = row;
26117
+ return liqLong == null && liqShort == null && liqTotal == null ? [] : [{ symbol, ts, interval: interval5, source, liqLong, liqShort, liqTotal }];
26118
+ })
26119
+ );
26120
+ return;
26121
+ }
26122
+ if (dataset.id === "binance-coinbase-spread-15m") {
26123
+ const { spreadRows = [] } = await import_connectors11.marketDataProviders.binance_coinbase_spread.fetchWindow({
26124
+ symbol: series,
26125
+ interval: "15m",
26126
+ fromMs: day,
26127
+ toMs: endMs
26128
+ });
26129
+ await (0, import_spread.upsertSpreadRows)(
26130
+ spreadRows.filter(({ ts }) => missing(ts.getTime()))
26131
+ );
26132
+ return;
26133
+ }
26134
+ const provider = dataset.provider === "Bybit" ? "bybit" : "binance";
26135
+ const connector = await import_connectors11.connectors[provider === "bybit" ? import_connectors11.ConnectorNames.ByBit : import_connectors11.ConnectorNames.Binance]({ userName: userName3 });
26136
+ const connectorInterval = interval4 === "5m" ? "5" : interval4 === "1h" ? "60" : "15";
26137
+ const fetchCandles = async (symbol, start) => {
26138
+ const candles = await connector.kline({
26139
+ symbol,
26140
+ interval: connectorInterval,
26141
+ start,
26142
+ end: endMs,
26143
+ silent: true
26144
+ });
26145
+ return candles.filter(
26146
+ ({ timestamp }) => timestamp >= start && timestamp < end
26147
+ );
26148
+ };
26149
+ if (dataset.id.includes("-candles-")) {
26150
+ const candles = (await fetchCandles(series, day)).filter(
26151
+ ({ timestamp }) => missing(timestamp)
26152
+ );
26153
+ await (0, import_candles3.upsertCandles)(
26154
+ (0, import_candles3.toRows)(provider, series, Number(connectorInterval), candles)
26155
+ );
26156
+ return;
26157
+ }
26158
+ if (interval4 === "1d") return;
26159
+ if (dataset.id.startsWith("binance-trade-flow-")) {
26160
+ await (0, import_marketContext5.upsertMarketTradeFlowRows)(
26161
+ buildKlineTradeFlowRows({
26162
+ symbol: series,
26163
+ interval: interval4,
26164
+ candles: (await fetchCandles(series, day)).filter(
26165
+ ({ timestamp }) => missing(timestamp)
26166
+ )
26167
+ })
26168
+ );
26169
+ return;
26170
+ }
26171
+ const universe = (0, import_strategies11.getBinanceBreadthUniverses)().find(
26172
+ (item) => item.universe === series
26173
+ );
26174
+ if (!universe)
26175
+ throw new Error("The historical Binance basket is unavailable.");
26176
+ const candlesBySymbol = {};
26177
+ const warmup = day - 2 * DAY_MS11;
26178
+ for (let offset = 0; offset < universe.symbols.length; offset += 4) {
26179
+ const entries = await Promise.all(
26180
+ universe.symbols.slice(offset, offset + 4).map(
26181
+ async (symbol) => [symbol, await fetchCandles(symbol, warmup)]
26182
+ )
26183
+ );
26184
+ Object.assign(candlesBySymbol, Object.fromEntries(entries));
26185
+ }
26186
+ const rows = buildMarketBreadthRows({
26187
+ universe: series,
26188
+ interval: interval4,
26189
+ candlesBySymbol,
26190
+ btcCandles: candlesBySymbol.BTCUSDT ?? await fetchCandles("BTCUSDT", warmup)
26191
+ });
26192
+ await (0, import_marketContext5.upsertMarketBreadthRows)(rows.filter(({ ts }) => missing(ts.getTime())));
26193
+ }
26194
+ async function main17() {
26195
+ const [userName3, dataset, series, day] = process.argv.slice(2);
26196
+ const request = { dataset, series, day: Number(day) };
26197
+ const target = (0, import_dataCoverage.resolveDataBackfill)(request);
26198
+ if (!target || !userName3)
26199
+ throw new Error(
26200
+ "Expected user, dataset, series and UTC day in milliseconds."
26201
+ );
26202
+ await (0, import_client5.waitForDbReady)();
26203
+ const before = await (0, import_dataCoverage.readDataBackfillSlots)(request, target.end);
26204
+ if (before.loaded.size < before.expected)
26205
+ await fetchTarget(userName3, request, target, before.loaded);
26206
+ const after = await (0, import_dataCoverage.readDataBackfillSlots)(request, target.end);
26207
+ const result = {
26208
+ loaded: after.loaded.size,
26209
+ added: Math.max(0, after.loaded.size - before.loaded.size),
26210
+ missing: Math.max(0, after.expected - after.loaded.size)
26211
+ };
26212
+ console.log(`TRADEJS_DATA_BACKFILL ${JSON.stringify(result)}`);
26213
+ }
26214
+ var import_connectors11, import_candles3, import_client5, import_dataCoverage, import_derivatives2, import_marketContext5, import_spread, import_strategies11, DAY_MS11;
26215
+ var init_coverageBackfill = __esm({
26216
+ "src/scripts/coverageBackfill.ts"() {
26217
+ "use strict";
26218
+ import_connectors11 = require("@tradejs/connectors");
26219
+ import_candles3 = require("@tradejs/infra/timescale/candles");
26220
+ import_client5 = require("@tradejs/infra/timescale/client");
26221
+ import_dataCoverage = require("@tradejs/infra/timescale/dataCoverage");
26222
+ import_derivatives2 = require("@tradejs/infra/timescale/derivatives");
26223
+ import_marketContext5 = require("@tradejs/infra/timescale/marketContext");
26224
+ import_spread = require("@tradejs/infra/timescale/spread");
26225
+ import_strategies11 = require("@tradejs/node/strategies");
26226
+ init_binanceMarketData();
26227
+ init_coinMarketCapContextBackfill();
26228
+ init_derivativesContextBackfill();
26229
+ DAY_MS11 = 864e5;
26230
+ }
26231
+ });
26232
+
25897
26233
  // src/lib/continuity.ts
25898
26234
  var import_types6, parseContinuityUniverse, resolveContinuityUniverses, findRepairableContinuityGap;
25899
26235
  var init_continuity = __esm({
@@ -25932,22 +26268,22 @@ var init_continuity = __esm({
25932
26268
  // src/scripts/continuity.ts
25933
26269
  var continuity_exports = {};
25934
26270
  __export(continuity_exports, {
25935
- main: () => main17
26271
+ main: () => main18
25936
26272
  });
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;
26273
+ var import_args14, import_progress9, import_chalk26, import_connectors12, import_cli9, import_constants17, import_time10, import_logger4, import_candles4, import_client6, flags12, interval2, intervalKey, projectRoot5, parseProviders, runContinuity, main18;
25938
26274
  var init_continuity2 = __esm({
25939
26275
  "src/scripts/continuity.ts"() {
25940
26276
  "use strict";
25941
26277
  import_args14 = __toESM(require("args"));
25942
26278
  import_progress9 = __toESM(require("progress"));
25943
26279
  import_chalk26 = __toESM(require("chalk"));
25944
- import_connectors11 = require("@tradejs/node/connectors");
26280
+ import_connectors12 = require("@tradejs/node/connectors");
25945
26281
  import_cli9 = require("@tradejs/node/cli");
25946
- import_constants16 = require("@tradejs/core/constants");
26282
+ import_constants17 = require("@tradejs/core/constants");
25947
26283
  import_time10 = require("@tradejs/core/time");
25948
- import_logger3 = require("@tradejs/infra/logger");
25949
- import_candles3 = require("@tradejs/infra/timescale/candles");
25950
- import_client5 = require("@tradejs/infra/timescale/client");
26284
+ import_logger4 = require("@tradejs/infra/logger");
26285
+ import_candles4 = require("@tradejs/infra/timescale/candles");
26286
+ import_client6 = require("@tradejs/infra/timescale/client");
25951
26287
  init_continuity();
25952
26288
  import_args14.default.option(["t", "tickers"], "Selected tickers");
25953
26289
  import_args14.default.option(["f", "timeframe"], "Timeframe", 15);
@@ -25963,7 +26299,7 @@ var init_continuity2 = __esm({
25963
26299
  intervalKey = flags12.timeframe.toString();
25964
26300
  projectRoot5 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
25965
26301
  parseProviders = async (value) => {
25966
- const allProviders = await (0, import_connectors11.getAvailableConnectorProviders)(projectRoot5);
26302
+ const allProviders = await (0, import_connectors12.getAvailableConnectorProviders)(projectRoot5);
25967
26303
  const raw = String(value || "").trim().toLowerCase();
25968
26304
  if (!raw || raw === "all") {
25969
26305
  return allProviders;
@@ -25972,7 +26308,7 @@ var init_continuity2 = __esm({
25972
26308
  const uniqueSelected = [...new Set(selected)];
25973
26309
  const invalid = uniqueSelected.filter((item) => !allProviders.includes(item));
25974
26310
  if (invalid.length) {
25975
- import_logger3.logger.error(
26311
+ import_logger4.logger.error(
25976
26312
  "Unknown provider(s): %s. Supported: %s",
25977
26313
  invalid.join(", "),
25978
26314
  allProviders.join(", ")
@@ -26007,7 +26343,7 @@ var init_continuity2 = __esm({
26007
26343
  let broken = 0;
26008
26344
  let fixed = 0;
26009
26345
  const expectedMs = interval2 * 60 * 1e3;
26010
- import_logger3.logger.info(
26346
+ import_logger4.logger.info(
26011
26347
  import_chalk26.default.yellow(`continuity ${connectorName}:${universe}: ${tickers.length}`)
26012
26348
  );
26013
26349
  for await (const symbol of tickers) {
@@ -26021,7 +26357,7 @@ var init_continuity2 = __esm({
26021
26357
  let gap = findRepairableContinuityGap(data, expectedMs, universe);
26022
26358
  if (gap) {
26023
26359
  broken++;
26024
- import_logger3.logger.warn(
26360
+ import_logger4.logger.warn(
26025
26361
  "[%s:%s] gap %s %s: %s -> %s (%ss)",
26026
26362
  provider,
26027
26363
  universe,
@@ -26031,7 +26367,7 @@ var init_continuity2 = __esm({
26031
26367
  (0, import_time10.formatUnix)(gap.ts),
26032
26368
  gap.diffSeconds
26033
26369
  );
26034
- await (0, import_candles3.deleteCandles)(provider, symbol, interval2);
26370
+ await (0, import_candles4.deleteCandles)(provider, symbol, interval2);
26035
26371
  const reloaded = await connector.kline({
26036
26372
  symbol,
26037
26373
  interval: intervalKey,
@@ -26050,47 +26386,47 @@ var init_continuity2 = __esm({
26050
26386
  symbol: import_chalk26.default.gray(symbol)
26051
26387
  });
26052
26388
  }
26053
- import_logger3.logger.info(
26389
+ import_logger4.logger.info(
26054
26390
  import_chalk26.default.yellow(
26055
26391
  `[${provider}:${universe}] broken: ${broken}/${tickers.length}, fixed: ${fixed}`
26056
26392
  )
26057
26393
  );
26058
26394
  };
26059
- main17 = async () => {
26395
+ main18 = async () => {
26060
26396
  if (!Number.isFinite(interval2) || interval2 <= 0) {
26061
- import_logger3.logger.error("Invalid timeframe: %s", flags12.timeframe);
26397
+ import_logger4.logger.error("Invalid timeframe: %s", flags12.timeframe);
26062
26398
  process.exit(1);
26063
26399
  }
26064
- await (0, import_client5.waitForDbReady)();
26065
- const reloadStart = (0, import_time10.getTimestamp)(import_constants16.PRELOAD_DAYS);
26400
+ await (0, import_client6.waitForDbReady)();
26401
+ const reloadStart = (0, import_time10.getTimestamp)(import_constants17.PRELOAD_DAYS);
26066
26402
  const reloadEnd = (0, import_time10.getTimestamp)();
26067
26403
  let requestedUniverse;
26068
26404
  try {
26069
26405
  requestedUniverse = parseContinuityUniverse(flags12.universe);
26070
26406
  } catch (error) {
26071
- import_logger3.logger.error(error.message);
26407
+ import_logger4.logger.error(error.message);
26072
26408
  process.exit(1);
26073
26409
  }
26074
26410
  const providerIds = await parseProviders(flags12.provider);
26075
26411
  const providers = await Promise.all(
26076
26412
  providerIds.map(async (providerId) => {
26077
- const connectorName = await (0, import_connectors11.getConnectorNameByProvider)(
26413
+ const connectorName = await (0, import_connectors12.getConnectorNameByProvider)(
26078
26414
  providerId,
26079
26415
  projectRoot5
26080
26416
  );
26081
26417
  if (!connectorName) {
26082
- import_logger3.logger.warn(
26418
+ import_logger4.logger.warn(
26083
26419
  'Skip provider "%s": connector mapping is missing',
26084
26420
  providerId
26085
26421
  );
26086
26422
  return null;
26087
26423
  }
26088
- const creator = await (0, import_connectors11.getConnectorCreatorByName)(
26424
+ const creator = await (0, import_connectors12.getConnectorCreatorByName)(
26089
26425
  connectorName,
26090
26426
  projectRoot5
26091
26427
  );
26092
26428
  if (!creator) {
26093
- import_logger3.logger.warn(
26429
+ import_logger4.logger.warn(
26094
26430
  'Skip provider "%s": connector "%s" is not registered',
26095
26431
  providerId,
26096
26432
  connectorName
@@ -26106,7 +26442,7 @@ var init_continuity2 = __esm({
26106
26442
  );
26107
26443
  const activeProviders = providers.filter(Boolean);
26108
26444
  if (!activeProviders.length) {
26109
- import_logger3.logger.error("No connector providers available");
26445
+ import_logger4.logger.error("No connector providers available");
26110
26446
  process.exit(1);
26111
26447
  }
26112
26448
  for await (const provider of activeProviders) {
@@ -26118,7 +26454,7 @@ var init_continuity2 = __esm({
26118
26454
  defaultConnector.capabilities.supportedUniverses
26119
26455
  );
26120
26456
  if (!universes.length) {
26121
- import_logger3.logger.warn(
26457
+ import_logger4.logger.warn(
26122
26458
  'Skip provider "%s": universe "%s" is not supported',
26123
26459
  provider.id,
26124
26460
  requestedUniverse
@@ -26147,9 +26483,9 @@ var init_continuity2 = __esm({
26147
26483
  // src/scripts/derivativesIngest.ts
26148
26484
  var derivativesIngest_exports = {};
26149
26485
  __export(derivativesIngest_exports, {
26150
- main: () => main18
26486
+ main: () => main19
26151
26487
  });
26152
- var import_config4, import_args15, import_chalk27, import_indicators3, import_client6, import_derivatives2, import_spread, import_userSettings5, import_connectors12, flags13, asInt5, main18;
26488
+ var import_config4, import_args15, import_chalk27, import_indicators3, import_client7, import_derivatives3, import_spread2, import_userSettings5, import_connectors13, flags13, asInt5, main19;
26153
26489
  var init_derivativesIngest = __esm({
26154
26490
  "src/scripts/derivativesIngest.ts"() {
26155
26491
  "use strict";
@@ -26157,11 +26493,11 @@ var init_derivativesIngest = __esm({
26157
26493
  import_args15 = __toESM(require("args"));
26158
26494
  import_chalk27 = __toESM(require("chalk"));
26159
26495
  import_indicators3 = require("@tradejs/core/indicators");
26160
- import_client6 = require("@tradejs/infra/timescale/client");
26161
- import_derivatives2 = require("@tradejs/infra/timescale/derivatives");
26162
- import_spread = require("@tradejs/infra/timescale/spread");
26496
+ import_client7 = require("@tradejs/infra/timescale/client");
26497
+ import_derivatives3 = require("@tradejs/infra/timescale/derivatives");
26498
+ import_spread2 = require("@tradejs/infra/timescale/spread");
26163
26499
  import_userSettings5 = require("@tradejs/infra/userSettings");
26164
- import_connectors12 = require("@tradejs/connectors");
26500
+ import_connectors13 = require("@tradejs/connectors");
26165
26501
  import_args15.default.example(
26166
26502
  "yarn ts-node ./src/scripts/derivativesIngest --provider coinalyze --symbols BTCUSDT,ETHUSDT --intervals 15m --days 120",
26167
26503
  "Ingest market features (derivatives/spread) into Timescale by provider"
@@ -26181,9 +26517,9 @@ var init_derivativesIngest = __esm({
26181
26517
  const parsed = Number.parseInt(String(value ?? ""), 10);
26182
26518
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
26183
26519
  };
26184
- main18 = async () => {
26520
+ main19 = async () => {
26185
26521
  const providerName = String(flags13.provider || "coinalyze").trim().toLowerCase();
26186
- const provider = import_connectors12.marketDataProviders[providerName];
26522
+ const provider = import_connectors13.marketDataProviders[providerName];
26187
26523
  if (!provider) {
26188
26524
  throw new Error(`Unsupported provider: ${providerName}`);
26189
26525
  }
@@ -26197,7 +26533,7 @@ var init_derivativesIngest = __esm({
26197
26533
  const coinalyzeApiKey = providerName === "coinalyze" ? (await (0, import_userSettings5.getUserSettings)(userName3)).COINALYZE_API_KEY : void 0;
26198
26534
  if (!symbols.length) throw new Error("No symbols provided");
26199
26535
  if (!intervals.length) throw new Error("No intervals provided");
26200
- await (0, import_client6.waitForDbReady)();
26536
+ await (0, import_client7.waitForDbReady)();
26201
26537
  const now2 = Date.now();
26202
26538
  const fromMs = now2 - days * 24 * 60 * 60 * 1e3;
26203
26539
  let totalDerivativesRows = 0;
@@ -26226,12 +26562,12 @@ var init_derivativesIngest = __esm({
26226
26562
  });
26227
26563
  const derivativesRows = window.derivativesRows ?? [];
26228
26564
  if (derivativesRows.length) {
26229
- await (0, import_derivatives2.upsertDerivatives)(derivativesRows);
26565
+ await (0, import_derivatives3.upsertDerivatives)(derivativesRows);
26230
26566
  totalDerivativesRows += derivativesRows.length;
26231
26567
  }
26232
26568
  const spreadRows = window.spreadRows ?? [];
26233
26569
  if (spreadRows.length) {
26234
- await (0, import_spread.upsertSpreadRows)(spreadRows);
26570
+ await (0, import_spread2.upsertSpreadRows)(spreadRows);
26235
26571
  totalSpreadRows += spreadRows.length;
26236
26572
  }
26237
26573
  cursor = toMs + 1;
@@ -26251,9 +26587,9 @@ var init_derivativesIngest = __esm({
26251
26587
  // src/scripts/derivativesIngestCoinalyzeAll.ts
26252
26588
  var derivativesIngestCoinalyzeAll_exports = {};
26253
26589
  __export(derivativesIngestCoinalyzeAll_exports, {
26254
- main: () => main19
26590
+ main: () => main20
26255
26591
  });
26256
- var import_config5, import_args16, import_chalk28, import_progress10, import_lodash2, import_connectors13, import_indicators4, import_async4, import_userSettings6, import_cli10, import_derivatives3, import_client7, coinalyzeIntervalMap2, flags14, asInt6, parseList2, coinalyzeBaseUrl, coinalyzeMaxRetries, lastRequestTs3, fetchJsonWithRateLimit2, fetchCoinalyzeMarkets2, selectBestMarket2, buildMatches2, normalizeMetricPoint2, toSeriesMap2, fetchMetricBatch2, main19;
26592
+ var import_config5, import_args16, import_chalk28, import_progress10, import_lodash2, import_connectors14, import_indicators4, import_async4, import_userSettings6, import_cli10, import_derivatives4, import_client8, coinalyzeIntervalMap2, flags14, asInt6, parseList2, coinalyzeBaseUrl, coinalyzeMaxRetries, lastRequestTs3, fetchJsonWithRateLimit2, fetchCoinalyzeMarkets2, selectBestMarket2, buildMatches2, normalizeMetricPoint2, toSeriesMap2, fetchMetricBatch2, main20;
26257
26593
  var init_derivativesIngestCoinalyzeAll = __esm({
26258
26594
  "src/scripts/derivativesIngestCoinalyzeAll.ts"() {
26259
26595
  "use strict";
@@ -26262,13 +26598,13 @@ var init_derivativesIngestCoinalyzeAll = __esm({
26262
26598
  import_chalk28 = __toESM(require("chalk"));
26263
26599
  import_progress10 = __toESM(require("progress"));
26264
26600
  import_lodash2 = __toESM(require("lodash"));
26265
- import_connectors13 = require("@tradejs/connectors");
26601
+ import_connectors14 = require("@tradejs/connectors");
26266
26602
  import_indicators4 = require("@tradejs/core/indicators");
26267
26603
  import_async4 = require("@tradejs/core/async");
26268
26604
  import_userSettings6 = require("@tradejs/infra/userSettings");
26269
26605
  import_cli10 = require("@tradejs/node/cli");
26270
- import_derivatives3 = require("@tradejs/infra/timescale/derivatives");
26271
- import_client7 = require("@tradejs/infra/timescale/client");
26606
+ import_derivatives4 = require("@tradejs/infra/timescale/derivatives");
26607
+ import_client8 = require("@tradejs/infra/timescale/client");
26272
26608
  coinalyzeIntervalMap2 = {
26273
26609
  "15m": "15min",
26274
26610
  "1h": "1hour"
@@ -26462,7 +26798,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
26462
26798
  const raw = await fetchJsonWithRateLimit2(url.toString(), apiKey);
26463
26799
  return toSeriesMap2(raw, metric);
26464
26800
  };
26465
- main19 = async () => {
26801
+ main20 = async () => {
26466
26802
  const userName3 = String(flags14.user || "root").trim() || "root";
26467
26803
  const intervals = (0, import_indicators4.normalizeDerivativesIntervals)(
26468
26804
  flags14.intervals
@@ -26480,7 +26816,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
26480
26816
  `Missing COINALYZE_API_KEY in user settings for user ${userName3}`
26481
26817
  );
26482
26818
  }
26483
- const connectorFactory = import_connectors13.connectors[import_connectors13.ConnectorNames.ByBit];
26819
+ const connectorFactory = import_connectors14.connectors[import_connectors14.ConnectorNames.ByBit];
26484
26820
  const bybit = await connectorFactory({
26485
26821
  userName: userName3
26486
26822
  });
@@ -26532,7 +26868,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
26532
26868
  );
26533
26869
  return;
26534
26870
  }
26535
- await (0, import_client7.waitForDbReady)();
26871
+ await (0, import_client8.waitForDbReady)();
26536
26872
  const now2 = Date.now();
26537
26873
  const fromMs = now2 - days * 24 * 60 * 60 * 1e3;
26538
26874
  const symbolBatches = import_lodash2.default.chunk(matches2, symbolBatchSize);
@@ -26600,7 +26936,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
26600
26936
  return (0, import_indicators4.coinalyzePointsToRows)(points, interval4, "coinalyze");
26601
26937
  });
26602
26938
  if (rows.length) {
26603
- await (0, import_derivatives3.upsertDerivatives)(rows);
26939
+ await (0, import_derivatives4.upsertDerivatives)(rows);
26604
26940
  totalRows += rows.length;
26605
26941
  }
26606
26942
  const confirmedLiquidationWindow = (0, import_indicators4.resolveCoinalyzeConfirmedIntradayCoverage)({
@@ -26610,7 +26946,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
26610
26946
  nowMs: now2
26611
26947
  });
26612
26948
  if (confirmedLiquidationWindow) {
26613
- await (0, import_derivatives3.applyDerivativesMetricCoverage)(
26949
+ await (0, import_derivatives4.applyDerivativesMetricCoverage)(
26614
26950
  batch.map((item) => {
26615
26951
  const marketSymbol = item.marketSymbol.toUpperCase();
26616
26952
  const eventRowsCount = (liqMap.get(marketSymbol) ?? []).filter(
@@ -26669,9 +27005,9 @@ var init_derivativesIngestCoinalyzeAll = __esm({
26669
27005
  // src/scripts/doctor.ts
26670
27006
  var doctor_exports = {};
26671
27007
  __export(doctor_exports, {
26672
- main: () => main20
27008
+ main: () => main21
26673
27009
  });
26674
- var import_config6, import_args17, import_chalk29, import_ioredis, import_pg2, import_node_net, okLabel, failLabel, infoLabel, toPort, parseAddress, checkRedis, checkPostgres, checkMlGrpc, flags15, main20;
27010
+ var import_config6, import_args17, import_chalk29, import_ioredis, import_pg2, import_node_net, okLabel, failLabel, infoLabel, toPort, parseAddress, checkRedis, checkPostgres, checkMlGrpc, flags15, main21;
26675
27011
  var init_doctor = __esm({
26676
27012
  "src/scripts/doctor.ts"() {
26677
27013
  "use strict";
@@ -26796,7 +27132,7 @@ var init_doctor = __esm({
26796
27132
  };
26797
27133
  import_args17.default.option("require-ml", "Treat ML gRPC connectivity as required", false).option("skip-ml", "Skip ML gRPC check", false);
26798
27134
  flags15 = import_args17.default.parse(process.argv);
26799
- main20 = async () => {
27135
+ main21 = async () => {
26800
27136
  const checks = [];
26801
27137
  checks.push(await checkRedis());
26802
27138
  checks.push(await checkPostgres());
@@ -26844,11 +27180,11 @@ var init_doctor = __esm({
26844
27180
  });
26845
27181
 
26846
27182
  // 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;
27183
+ 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
27184
  var init_executionCalibration = __esm({
26849
27185
  "src/lib/executionCalibration.ts"() {
26850
27186
  "use strict";
26851
- import_constants17 = require("@tradejs/core/constants");
27187
+ import_constants18 = require("@tradejs/core/constants");
26852
27188
  import_data8 = require("@tradejs/core/data");
26853
27189
  import_trade3 = require("@tradejs/core/trade");
26854
27190
  roundMetric = (value, decimals = 6) => typeof value === "number" && Number.isFinite(value) ? Number(value.toFixed(decimals)) : null;
@@ -27233,7 +27569,7 @@ var init_executionCalibration = __esm({
27233
27569
  actualPrice: fillAvgPrice
27234
27570
  });
27235
27571
  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)
27572
+ import_constants18.BACKTEST_BASE_SLIPPAGE_BPS + (spreadBps ?? 0) * import_constants18.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER + import_constants18.BACKTEST_MARKET_IMPACT_BPS + (currentDelayRiskBps ?? 0)
27237
27573
  ) : null;
27238
27574
  const residualVsCurrentModelBps = signalToFillAdverseBps != null && currentModelEntrySlippageBps != null ? roundMetric(signalToFillAdverseBps - currentModelEntrySlippageBps) : null;
27239
27575
  return {
@@ -27428,7 +27764,7 @@ var init_executionCalibration = __esm({
27428
27764
  }
27429
27765
  return Math.max(
27430
27766
  0,
27431
- sample.arrivalToFillAdverseBps - (sample.spreadBps ?? 0) * (spreadMultiplier ?? import_constants17.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER)
27767
+ sample.arrivalToFillAdverseBps - (sample.spreadBps ?? 0) * (spreadMultiplier ?? import_constants18.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER)
27432
27768
  );
27433
27769
  }).filter(
27434
27770
  (value) => value != null && Number.isFinite(value)
@@ -27491,9 +27827,9 @@ var init_executionCalibration = __esm({
27491
27827
  generatedAt: nowMs,
27492
27828
  sources: sourcePaths,
27493
27829
  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
27830
+ baseSlippageBps: import_constants18.BACKTEST_BASE_SLIPPAGE_BPS,
27831
+ spreadMultiplier: import_constants18.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER,
27832
+ marketImpactBps: import_constants18.BACKTEST_MARKET_IMPACT_BPS
27497
27833
  },
27498
27834
  counts: {
27499
27835
  runtimeTrades: runtimeRows.length,
@@ -27534,9 +27870,9 @@ var init_executionCalibration = __esm({
27534
27870
  var executionCalibration_exports = {};
27535
27871
  __export(executionCalibration_exports, {
27536
27872
  executionCalibration: () => executionCalibration,
27537
- main: () => main21
27873
+ main: () => main22
27538
27874
  });
27539
- var import_promises21, import_node_path17, import_args18, import_chalk30, flags16, projectRoot6, readJsonFile, resolveInputPath, executionCalibration, main21;
27875
+ var import_promises21, import_node_path17, import_args18, import_chalk30, flags16, projectRoot6, readJsonFile, resolveInputPath, executionCalibration, main22;
27540
27876
  var init_executionCalibration2 = __esm({
27541
27877
  "src/scripts/executionCalibration.ts"() {
27542
27878
  "use strict";
@@ -27611,7 +27947,7 @@ var init_executionCalibration2 = __esm({
27611
27947
  )
27612
27948
  );
27613
27949
  };
27614
- main21 = executionCalibration;
27950
+ main22 = executionCalibration;
27615
27951
  }
27616
27952
  });
27617
27953
 
@@ -27729,15 +28065,15 @@ volumes:
27729
28065
  // src/scripts/infraDown.ts
27730
28066
  var infraDown_exports = {};
27731
28067
  __export(infraDown_exports, {
27732
- main: () => main22
28068
+ main: () => main23
27733
28069
  });
27734
- var import_chalk32, main22;
28070
+ var import_chalk32, main23;
27735
28071
  var init_infraDown = __esm({
27736
28072
  "src/scripts/infraDown.ts"() {
27737
28073
  "use strict";
27738
28074
  import_chalk32 = __toESM(require("chalk"));
27739
28075
  init_infraCommon();
27740
- main22 = async () => {
28076
+ main23 = async () => {
27741
28077
  const composePath = requireDevComposeFile();
27742
28078
  console.log(import_chalk32.default.cyan("Stopping dev infra (timescale, redis)..."));
27743
28079
  runDockerCompose(composePath, ["stop", "timescale", "redis"]);
@@ -27749,15 +28085,15 @@ var init_infraDown = __esm({
27749
28085
  // src/scripts/infraInit.ts
27750
28086
  var infraInit_exports = {};
27751
28087
  __export(infraInit_exports, {
27752
- main: () => main23
28088
+ main: () => main24
27753
28089
  });
27754
- var import_chalk33, main23;
28090
+ var import_chalk33, main24;
27755
28091
  var init_infraInit = __esm({
27756
28092
  "src/scripts/infraInit.ts"() {
27757
28093
  "use strict";
27758
28094
  import_chalk33 = __toESM(require("chalk"));
27759
28095
  init_infraCommon();
27760
- main23 = async () => {
28096
+ main24 = async () => {
27761
28097
  initDevComposeFile();
27762
28098
  console.log(import_chalk33.default.green("Dev infra files are initialized."));
27763
28099
  };
@@ -27767,15 +28103,15 @@ var init_infraInit = __esm({
27767
28103
  // src/scripts/infraUp.ts
27768
28104
  var infraUp_exports = {};
27769
28105
  __export(infraUp_exports, {
27770
- main: () => main24
28106
+ main: () => main25
27771
28107
  });
27772
- var import_chalk34, main24;
28108
+ var import_chalk34, main25;
27773
28109
  var init_infraUp = __esm({
27774
28110
  "src/scripts/infraUp.ts"() {
27775
28111
  "use strict";
27776
28112
  import_chalk34 = __toESM(require("chalk"));
27777
28113
  init_infraCommon();
27778
- main24 = async () => {
28114
+ main25 = async () => {
27779
28115
  const composePath = requireDevComposeFile();
27780
28116
  console.log(import_chalk34.default.cyan("Starting dev infra (timescale, redis)..."));
27781
28117
  runDockerCompose(composePath, [
@@ -27795,27 +28131,27 @@ var init_infraUp = __esm({
27795
28131
  // src/scripts/cleanupMarketContext.ts
27796
28132
  var cleanupMarketContext_exports = {};
27797
28133
  __export(cleanupMarketContext_exports, {
27798
- main: () => main25
28134
+ main: () => main26
27799
28135
  });
27800
- var import_config7, import_args19, import_chalk35, import_client8, import_marketContext5, flags17, main25;
28136
+ var import_config7, import_args19, import_chalk35, import_client9, import_marketContext6, flags17, main26;
27801
28137
  var init_cleanupMarketContext = __esm({
27802
28138
  "src/scripts/cleanupMarketContext.ts"() {
27803
28139
  "use strict";
27804
28140
  import_config7 = require("dotenv/config");
27805
28141
  import_args19 = __toESM(require("args"));
27806
28142
  import_chalk35 = __toESM(require("chalk"));
27807
- import_client8 = require("@tradejs/infra/timescale/client");
27808
- import_marketContext5 = require("@tradejs/infra/timescale/marketContext");
28143
+ import_client9 = require("@tradejs/infra/timescale/client");
28144
+ import_marketContext6 = require("@tradejs/infra/timescale/marketContext");
27809
28145
  import_args19.default.example(
27810
28146
  "yarn cli maintenance:cleanup-market-context --apply",
27811
28147
  "Remove deprecated snapshot-only market context data from Timescale"
27812
28148
  );
27813
28149
  import_args19.default.option(["a", "apply"], "Apply destructive cleanup; default is dry-run");
27814
28150
  flags17 = import_args19.default.parse(process.argv);
27815
- main25 = async () => {
28151
+ main26 = async () => {
27816
28152
  const apply = Boolean(flags17.apply);
27817
- await (0, import_client8.waitForDbReady)();
27818
- const items = await (0, import_marketContext5.cleanupDeprecatedMarketContext)({ apply });
28153
+ await (0, import_client9.waitForDbReady)();
28154
+ const items = await (0, import_marketContext6.cleanupDeprecatedMarketContext)({ apply });
27819
28155
  if (!items.length) {
27820
28156
  console.log(import_chalk35.default.green("No deprecated market context data found."));
27821
28157
  return;
@@ -27838,17 +28174,17 @@ var init_cleanupMarketContext = __esm({
27838
28174
  // src/scripts/migration.ts
27839
28175
  var migration_exports = {};
27840
28176
  __export(migration_exports, {
27841
- main: () => main26
28177
+ main: () => main27
27842
28178
  });
27843
- var import_progress11, import_chalk36, import_logger4, import_files, import_candles4, DIR, re, BATCH, projectRoot7, migrateFile, main26;
28179
+ var import_progress11, import_chalk36, import_logger5, import_files, import_candles5, DIR, re, BATCH, projectRoot7, migrateFile, main27;
27844
28180
  var init_migration = __esm({
27845
28181
  "src/scripts/migration.ts"() {
27846
28182
  "use strict";
27847
28183
  import_progress11 = __toESM(require("progress"));
27848
28184
  import_chalk36 = __toESM(require("chalk"));
27849
- import_logger4 = require("@tradejs/infra/logger");
28185
+ import_logger5 = require("@tradejs/infra/logger");
27850
28186
  import_files = require("@tradejs/infra/files");
27851
- import_candles4 = require("@tradejs/infra/timescale/candles");
28187
+ import_candles5 = require("@tradejs/infra/timescale/candles");
27852
28188
  DIR = "data/history";
27853
28189
  re = /^(.+?)_(\d+)\.json$/;
27854
28190
  BATCH = 2e3;
@@ -27864,12 +28200,12 @@ var init_migration = __esm({
27864
28200
  [],
27865
28201
  projectRoot7
27866
28202
  );
27867
- const rows = (0, import_candles4.toRows)("bybit", symbol, interval4, data);
28203
+ const rows = (0, import_candles5.toRows)("bybit", symbol, interval4, data);
27868
28204
  for (let i = 0; i < rows.length; i += BATCH) {
27869
- await (0, import_candles4.upsertCandles)(rows.slice(i, i + BATCH));
28205
+ await (0, import_candles5.upsertCandles)(rows.slice(i, i + BATCH));
27870
28206
  }
27871
28207
  };
27872
- main26 = async () => {
28208
+ main27 = async () => {
27873
28209
  const files = await (0, import_files.getFiles)(DIR, projectRoot7);
27874
28210
  const bar = new import_progress11.default(
27875
28211
  ":current/:total [:bar][:percent] :eta(s) :file",
@@ -27882,7 +28218,7 @@ var init_migration = __esm({
27882
28218
  try {
27883
28219
  await migrateFile(file);
27884
28220
  } catch (e) {
27885
- import_logger4.logger.error("Failed: %s %s", file, e);
28221
+ import_logger5.logger.error("Failed: %s %s", file, e);
27886
28222
  } finally {
27887
28223
  bar.tick(1, {
27888
28224
  file: import_chalk36.default.gray(file)
@@ -27895,12 +28231,12 @@ var init_migration = __esm({
27895
28231
  });
27896
28232
 
27897
28233
  // src/lib/marketData/klineEvents.ts
27898
- var import_ioredis2, import_redis14, MARKET_KLINE_CHANNEL, positiveInt2, redisOptions, buildMarketKlineTopic, publishMarketKlineEvent, createMarketKlineSubscriber, parseMarketKlineEvent;
28234
+ var import_ioredis2, import_redis15, MARKET_KLINE_CHANNEL, positiveInt2, redisOptions, buildMarketKlineTopic, publishMarketKlineEvent, createMarketKlineSubscriber, parseMarketKlineEvent;
27899
28235
  var init_klineEvents = __esm({
27900
28236
  "src/lib/marketData/klineEvents.ts"() {
27901
28237
  "use strict";
27902
28238
  import_ioredis2 = __toESM(require("ioredis"));
27903
- import_redis14 = require("@tradejs/infra/redis");
28239
+ import_redis15 = require("@tradejs/infra/redis");
27904
28240
  MARKET_KLINE_CHANNEL = "tradejs:market:kline";
27905
28241
  positiveInt2 = (value, fallback) => {
27906
28242
  const parsed = Number(value);
@@ -27919,7 +28255,7 @@ var init_klineEvents = __esm({
27919
28255
  event.symbol.trim().toUpperCase(),
27920
28256
  event.interval
27921
28257
  ].join(":");
27922
- publishMarketKlineEvent = (event) => (0, import_redis14.publishData)(MARKET_KLINE_CHANNEL, event);
28258
+ publishMarketKlineEvent = (event) => (0, import_redis15.publishData)(MARKET_KLINE_CHANNEL, event);
27923
28259
  createMarketKlineSubscriber = () => new import_ioredis2.default(redisOptions());
27924
28260
  parseMarketKlineEvent = (payload) => {
27925
28261
  try {
@@ -27936,13 +28272,13 @@ var init_klineEvents = __esm({
27936
28272
  });
27937
28273
 
27938
28274
  // src/lib/marketData/marketWsGateway.ts
27939
- var import_http, import_ws, import_logger5, MAX_TOPICS_PER_CLIENT, TOPIC_PATTERN, parseSubscriptionCommand, applySubscriptionCommand, startMarketWsGateway;
28275
+ var import_http, import_ws, import_logger6, MAX_TOPICS_PER_CLIENT, TOPIC_PATTERN, parseSubscriptionCommand, applySubscriptionCommand, startMarketWsGateway;
27940
28276
  var init_marketWsGateway = __esm({
27941
28277
  "src/lib/marketData/marketWsGateway.ts"() {
27942
28278
  "use strict";
27943
28279
  import_http = __toESM(require("http"));
27944
28280
  import_ws = require("ws");
27945
- import_logger5 = require("@tradejs/infra/logger");
28281
+ import_logger6 = require("@tradejs/infra/logger");
27946
28282
  init_klineEvents();
27947
28283
  MAX_TOPICS_PER_CLIENT = 20;
27948
28284
  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 +28392,7 @@ var init_marketWsGateway = __esm({
28056
28392
  resolve();
28057
28393
  });
28058
28394
  });
28059
- import_logger5.logger.info("market websocket gateway listening on %s:%s", host, port);
28395
+ import_logger6.logger.info("market websocket gateway listening on %s:%s", host, port);
28060
28396
  return {
28061
28397
  close: async () => {
28062
28398
  clearInterval(heartbeat);
@@ -28075,14 +28411,14 @@ var init_marketWsGateway = __esm({
28075
28411
  // src/scripts/marketWs.ts
28076
28412
  var marketWs_exports = {};
28077
28413
  __export(marketWs_exports, {
28078
- main: () => main27
28414
+ main: () => main28
28079
28415
  });
28080
- var main27;
28416
+ var main28;
28081
28417
  var init_marketWs = __esm({
28082
28418
  "src/scripts/marketWs.ts"() {
28083
28419
  "use strict";
28084
28420
  init_marketWsGateway();
28085
- main27 = async () => {
28421
+ main28 = async () => {
28086
28422
  const gateway = await startMarketWsGateway();
28087
28423
  const abortController = new AbortController();
28088
28424
  const stop = () => abortController.abort();
@@ -28196,25 +28532,25 @@ const timer = setInterval(() => {
28196
28532
  // src/scripts/mcpWorker.ts
28197
28533
  var mcpWorker_exports = {};
28198
28534
  __export(mcpWorker_exports, {
28199
- main: () => main28
28535
+ main: () => main29
28200
28536
  });
28201
- var import_node_child_process4, import_node_crypto15, import_promises23, import_redis15, import_mcp, pause, leaseKey, LEASE_SECONDS, JOB_TIMEOUT_MS, main28;
28537
+ var import_node_child_process4, import_node_crypto15, import_promises23, import_redis16, import_mcp, pause, leaseKey, LEASE_SECONDS, JOB_TIMEOUT_MS, main29;
28202
28538
  var init_mcpWorker = __esm({
28203
28539
  "src/scripts/mcpWorker.ts"() {
28204
28540
  "use strict";
28205
28541
  import_node_child_process4 = require("child_process");
28206
28542
  import_node_crypto15 = require("crypto");
28207
28543
  import_promises23 = require("fs/promises");
28208
- import_redis15 = require("@tradejs/infra/redis");
28544
+ import_redis16 = require("@tradejs/infra/redis");
28209
28545
  import_mcp = require("@tradejs/node/mcp");
28210
28546
  init_mcpReplayProcess();
28211
28547
  pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
28212
28548
  leaseKey = "worker:lease";
28213
28549
  LEASE_SECONDS = 15;
28214
28550
  JOB_TIMEOUT_MS = 60 * 60 * 1e3;
28215
- main28 = async (options = {}) => {
28551
+ main29 = async (options = {}) => {
28216
28552
  const owner = (0, import_node_crypto15.randomUUID)();
28217
- if (!await import_redis15.mcpStorage.put(leaseKey, owner, LEASE_SECONDS, true))
28553
+ if (!await import_redis16.mcpStorage.put(leaseKey, owner, LEASE_SECONDS, true))
28218
28554
  throw new Error("Another MCP worker owns this storage");
28219
28555
  let stopping = false;
28220
28556
  let child;
@@ -28278,10 +28614,10 @@ var init_mcpWorker = __esm({
28278
28614
  if (renewing || leaseLost) return;
28279
28615
  renewing = true;
28280
28616
  try {
28281
- if (!await import_redis15.mcpStorage.compare(leaseKey, owner, owner, LEASE_SECONDS))
28617
+ if (!await import_redis16.mcpStorage.compare(leaseKey, owner, owner, LEASE_SECONDS))
28282
28618
  throw new Error("Worker lease lost");
28283
28619
  await updateReplayReady();
28284
- await import_redis15.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
28620
+ await import_redis16.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
28285
28621
  } catch {
28286
28622
  leaseLost = true;
28287
28623
  stop();
@@ -28292,15 +28628,15 @@ var init_mcpWorker = __esm({
28292
28628
  try {
28293
28629
  manifestHash = await (0, import_mcp.mcpPackageManifestHash)();
28294
28630
  await updateReplayReady();
28295
- await import_redis15.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
28631
+ await import_redis16.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
28296
28632
  let cursor = "0";
28297
28633
  do {
28298
- const page = await import_redis15.mcpStorage.scan("jobs:", cursor);
28634
+ const page = await import_redis16.mcpStorage.scan("jobs:", cursor);
28299
28635
  cursor = page.cursor;
28300
28636
  for (const key2 of page.ids) {
28301
- const job = await import_redis15.mcpStorage.get(key2);
28637
+ const job = await import_redis16.mcpStorage.get(key2);
28302
28638
  if (job?.status === "running")
28303
- await import_redis15.mcpStorage.compare(
28639
+ await import_redis16.mcpStorage.compare(
28304
28640
  key2,
28305
28641
  job,
28306
28642
  {
@@ -28321,10 +28657,10 @@ var init_mcpWorker = __esm({
28321
28657
  let queued;
28322
28658
  cursor = "0";
28323
28659
  do {
28324
- const page = await import_redis15.mcpStorage.scan("jobs:", cursor);
28660
+ const page = await import_redis16.mcpStorage.scan("jobs:", cursor);
28325
28661
  cursor = page.cursor;
28326
28662
  for (const key2 of page.ids) {
28327
- const job = await import_redis15.mcpStorage.get(key2);
28663
+ const job = await import_redis16.mcpStorage.get(key2);
28328
28664
  if (job && ["queued", "waiting_resources", "waiting_executor"].includes(
28329
28665
  job.status
28330
28666
  ) && (!queued || job.createdAt < queued.createdAt))
@@ -28342,10 +28678,10 @@ var init_mcpWorker = __esm({
28342
28678
  ...queued.kind === "runtime-feedback-replay" ? {} : { startedAt: Date.now() },
28343
28679
  updatedAt: Date.now()
28344
28680
  };
28345
- if (!await import_redis15.mcpStorage.compare(jobKey, queued, started, import_mcp.MCP_JOB_TTL))
28681
+ if (!await import_redis16.mcpStorage.compare(jobKey, queued, started, import_mcp.MCP_JOB_TTL))
28346
28682
  continue;
28347
28683
  if (started.kind !== "runtime-feedback-replay" && started.packageManifestSha256 !== manifestHash) {
28348
- await import_redis15.mcpStorage.compare(
28684
+ await import_redis16.mcpStorage.compare(
28349
28685
  jobKey,
28350
28686
  started,
28351
28687
  {
@@ -28360,8 +28696,8 @@ var init_mcpWorker = __esm({
28360
28696
  }
28361
28697
  await (0, import_promises23.mkdir)((0, import_mcp.mcpJobDirectory)(started), { recursive: true });
28362
28698
  if (started.kind === "backtest")
28363
- await (0, import_redis15.setDataStrict)(
28364
- import_redis15.redisKeys.backtestConfig(
28699
+ await (0, import_redis16.setDataStrict)(
28700
+ import_redis16.redisKeys.backtestConfig(
28365
28701
  started.userName,
28366
28702
  String(started.request.frozenConfigId)
28367
28703
  ),
@@ -28410,7 +28746,7 @@ var init_mcpWorker = __esm({
28410
28746
  env: process.env
28411
28747
  });
28412
28748
  } catch (error) {
28413
- await import_redis15.mcpStorage.compare(
28749
+ await import_redis16.mcpStorage.compare(
28414
28750
  jobKey,
28415
28751
  started,
28416
28752
  {
@@ -28448,7 +28784,7 @@ var init_mcpWorker = __esm({
28448
28784
  let killAt;
28449
28785
  const monitor = setInterval(async () => {
28450
28786
  try {
28451
- const latest = await import_redis15.mcpStorage.get(jobKey);
28787
+ const latest = await import_redis16.mcpStorage.get(jobKey);
28452
28788
  if (!latest || latest.cancelRequested || stopping || timedOut) {
28453
28789
  killAt ??= Date.now();
28454
28790
  signalChild(Date.now() - killAt > 8e3 ? "SIGKILL" : "SIGTERM");
@@ -28473,7 +28809,7 @@ var init_mcpWorker = __esm({
28473
28809
  }
28474
28810
  }
28475
28811
  if (latest && !leaseLost)
28476
- await import_redis15.mcpStorage.compare(
28812
+ await import_redis16.mcpStorage.compare(
28477
28813
  jobKey,
28478
28814
  latest,
28479
28815
  {
@@ -28504,7 +28840,7 @@ var init_mcpWorker = __esm({
28504
28840
  child = void 0;
28505
28841
  if (!leaseLost) {
28506
28842
  for (let attempt = 0; attempt < 4; attempt++) {
28507
- const latest = await import_redis15.mcpStorage.get(jobKey);
28843
+ const latest = await import_redis16.mcpStorage.get(jobKey);
28508
28844
  if (!latest) break;
28509
28845
  const cancelled = latest.cancelRequested;
28510
28846
  const next = {
@@ -28520,7 +28856,7 @@ var init_mcpWorker = __esm({
28520
28856
  ) || logs.at(-1) : void 0) || "Research process failed"
28521
28857
  } : {}
28522
28858
  };
28523
- if (await import_redis15.mcpStorage.compare(jobKey, latest, next, import_mcp.MCP_JOB_TTL))
28859
+ if (await import_redis16.mcpStorage.compare(jobKey, latest, next, import_mcp.MCP_JOB_TTL))
28524
28860
  break;
28525
28861
  }
28526
28862
  }
@@ -28530,8 +28866,8 @@ var init_mcpWorker = __esm({
28530
28866
  options.signal?.removeEventListener("abort", stop);
28531
28867
  process.removeListener("SIGINT", stop);
28532
28868
  process.removeListener("SIGTERM", stop);
28533
- if (await import_redis15.mcpStorage.release(leaseKey, owner))
28534
- await import_redis15.mcpStorage.remove("worker:heartbeat");
28869
+ if (await import_redis16.mcpStorage.release(leaseKey, owner))
28870
+ await import_redis16.mcpStorage.remove("worker:heartbeat");
28535
28871
  }
28536
28872
  if (leaseLost)
28537
28873
  throw new Error("Worker lease lost; active computation was stopped");
@@ -28542,9 +28878,9 @@ var init_mcpWorker = __esm({
28542
28878
  // src/scripts/hyperliquidWhaleBackfill.ts
28543
28879
  var hyperliquidWhaleBackfill_exports = {};
28544
28880
  __export(hyperliquidWhaleBackfill_exports, {
28545
- main: () => main29
28881
+ main: () => main30
28546
28882
  });
28547
- var import_args20, flags18, parseTime, main29;
28883
+ var import_args20, flags18, parseTime, main30;
28548
28884
  var init_hyperliquidWhaleBackfill2 = __esm({
28549
28885
  "src/scripts/hyperliquidWhaleBackfill.ts"() {
28550
28886
  "use strict";
@@ -28564,7 +28900,7 @@ var init_hyperliquidWhaleBackfill2 = __esm({
28564
28900
  if (!Number.isFinite(parsed)) throw new Error(`Invalid timestamp: ${value}`);
28565
28901
  return parsed;
28566
28902
  };
28567
- main29 = async () => {
28903
+ main30 = async () => {
28568
28904
  const toMs = parseTime(flags18.to, Date.now());
28569
28905
  const days = Number(flags18.days);
28570
28906
  const lookbackMs = (Number.isFinite(days) && days > 0 ? days : 1) * 864e5;
@@ -28582,13 +28918,13 @@ var init_hyperliquidWhaleBackfill2 = __esm({
28582
28918
  });
28583
28919
 
28584
28920
  // src/lib/hyperliquidWhaleStream.ts
28585
- var import_ws2, import_hyperliquidWhales2, import_strategies11, DEFAULT_WS_URL, EVENT_BATCH_SIZE, FLUSH_INTERVAL_MS, FINALIZE_INTERVAL_MS, FINALIZE_LAG_MS, REBUILD_LOOKBACK_MS, RAW_EVENT_RETENTION_MS, sleep5, parseHyperliquidUserFillsMessage, runHyperliquidWhaleStream;
28921
+ var import_ws2, import_hyperliquidWhales2, import_strategies12, DEFAULT_WS_URL, EVENT_BATCH_SIZE, FLUSH_INTERVAL_MS, FINALIZE_INTERVAL_MS, FINALIZE_LAG_MS, REBUILD_LOOKBACK_MS, RAW_EVENT_RETENTION_MS, sleep5, parseHyperliquidUserFillsMessage, runHyperliquidWhaleStream;
28586
28922
  var init_hyperliquidWhaleStream = __esm({
28587
28923
  "src/lib/hyperliquidWhaleStream.ts"() {
28588
28924
  "use strict";
28589
28925
  import_ws2 = require("ws");
28590
28926
  import_hyperliquidWhales2 = require("@tradejs/infra/timescale/hyperliquidWhales");
28591
- import_strategies11 = require("@tradejs/node/strategies");
28927
+ import_strategies12 = require("@tradejs/node/strategies");
28592
28928
  init_hyperliquidWhaleData();
28593
28929
  DEFAULT_WS_URL = "wss://api.hyperliquid.xyz/ws";
28594
28930
  EVENT_BATCH_SIZE = 500;
@@ -28629,8 +28965,8 @@ var init_hyperliquidWhaleStream = __esm({
28629
28965
  }
28630
28966
  };
28631
28967
  runHyperliquidWhaleStream = async (params) => {
28632
- const universe = (0, import_strategies11.getHyperliquidPerpUniverseSnapshot)();
28633
- const whales = (0, import_strategies11.getHyperliquidWhaleRegistrySnapshot)();
28968
+ const universe = (0, import_strategies12.getHyperliquidPerpUniverseSnapshot)();
28969
+ const whales = (0, import_strategies12.getHyperliquidWhaleRegistrySnapshot)();
28634
28970
  const trackedSymbols = new Set(universe.symbols);
28635
28971
  const identity = {
28636
28972
  universeFingerprint: universe.fingerprint,
@@ -28773,14 +29109,14 @@ var init_hyperliquidWhaleStream = __esm({
28773
29109
  // src/scripts/hyperliquidWhaleIngest.ts
28774
29110
  var hyperliquidWhaleIngest_exports = {};
28775
29111
  __export(hyperliquidWhaleIngest_exports, {
28776
- main: () => main30
29112
+ main: () => main31
28777
29113
  });
28778
- var main30;
29114
+ var main31;
28779
29115
  var init_hyperliquidWhaleIngest = __esm({
28780
29116
  "src/scripts/hyperliquidWhaleIngest.ts"() {
28781
29117
  "use strict";
28782
29118
  init_hyperliquidWhaleStream();
28783
- main30 = async () => {
29119
+ main31 = async () => {
28784
29120
  const controller = new AbortController();
28785
29121
  const stop = () => controller.abort();
28786
29122
  process.once("SIGINT", stop);
@@ -28892,21 +29228,21 @@ var init_hyperliquidWhaleSelection = __esm({
28892
29228
  // src/scripts/hyperliquidWhalesUpdate.ts
28893
29229
  var hyperliquidWhalesUpdate_exports = {};
28894
29230
  __export(hyperliquidWhalesUpdate_exports, {
28895
- main: () => main31
29231
+ main: () => main32
28896
29232
  });
28897
- var import_config8, import_args21, import_node_crypto16, import_strategies12, LEADERBOARD_URL, DAY_MS11, CANDIDATE_LIMIT, flags19, fingerprint, runConcurrent2, main31;
29233
+ var import_config8, import_args21, import_node_crypto16, import_strategies13, LEADERBOARD_URL, DAY_MS12, CANDIDATE_LIMIT, flags19, fingerprint, runConcurrent2, main32;
28898
29234
  var init_hyperliquidWhalesUpdate = __esm({
28899
29235
  "src/scripts/hyperliquidWhalesUpdate.ts"() {
28900
29236
  "use strict";
28901
29237
  import_config8 = require("dotenv/config");
28902
29238
  import_args21 = __toESM(require("args"));
28903
29239
  import_node_crypto16 = require("crypto");
28904
- import_strategies12 = require("@tradejs/node/strategies");
29240
+ import_strategies13 = require("@tradejs/node/strategies");
28905
29241
  init_hyperliquidWhaleBackfill();
28906
29242
  init_hyperliquidRateLimiter();
28907
29243
  init_hyperliquidWhaleSelection();
28908
29244
  LEADERBOARD_URL = "https://stats-data.hyperliquid.xyz/Mainnet/leaderboard";
28909
- DAY_MS11 = 864e5;
29245
+ DAY_MS12 = 864e5;
28910
29246
  CANDIDATE_LIMIT = 400;
28911
29247
  import_args21.default.option(
28912
29248
  ["t", "to"],
@@ -28928,11 +29264,11 @@ var init_hyperliquidWhalesUpdate = __esm({
28928
29264
  })
28929
29265
  );
28930
29266
  };
28931
- main31 = async () => {
29267
+ main32 = async () => {
28932
29268
  const explicitTo = flags19.to == null ? Number.NaN : Date.parse(String(flags19.to));
28933
- const calibrationToMs = Number.isFinite(explicitTo) ? explicitTo : Math.floor(Date.now() / DAY_MS11) * DAY_MS11;
29269
+ const calibrationToMs = Number.isFinite(explicitTo) ? explicitTo : Math.floor(Date.now() / DAY_MS12) * DAY_MS12;
28934
29270
  const calibrationDays = Math.max(1, Number(flags19.days) || 7);
28935
- const calibrationFromMs = calibrationToMs - calibrationDays * DAY_MS11;
29271
+ const calibrationFromMs = calibrationToMs - calibrationDays * DAY_MS12;
28936
29272
  const response = await fetch(LEADERBOARD_URL);
28937
29273
  if (!response.ok) {
28938
29274
  throw new Error(`Hyperliquid leaderboard ${response.status}`);
@@ -28954,7 +29290,7 @@ var init_hyperliquidWhalesUpdate = __esm({
28954
29290
  ).sort(
28955
29291
  (left, right) => left.turnoverToEquity - right.turnoverToEquity || right.accountValueUsd - left.accountValueUsd || left.address.localeCompare(right.address)
28956
29292
  ).slice(0, CANDIDATE_LIMIT);
28957
- const top30Symbols = new Set((0, import_strategies12.getHyperliquidPerpUniverseSnapshot)().symbols);
29293
+ const top30Symbols = new Set((0, import_strategies13.getHyperliquidPerpUniverseSnapshot)().symbols);
28958
29294
  const limiter = new HyperliquidInfoRateLimiter();
28959
29295
  const metrics = [];
28960
29296
  let completed = 0;
@@ -29021,9 +29357,9 @@ var init_hyperliquidWhalesUpdate = __esm({
29021
29357
  // src/scripts/mlExport.ts
29022
29358
  var mlExport_exports = {};
29023
29359
  __export(mlExport_exports, {
29024
- main: () => main32
29360
+ main: () => main33
29025
29361
  });
29026
- var import_args22, import_chalk37, import_promises24, import_path8, import_ml, flags20, resolveRunScopedMlChunks, main32;
29362
+ var import_args22, import_chalk37, import_promises24, import_path8, import_ml, flags20, resolveRunScopedMlChunks, main33;
29027
29363
  var init_mlExport = __esm({
29028
29364
  "src/scripts/mlExport.ts"() {
29029
29365
  "use strict";
@@ -29078,7 +29414,7 @@ var init_mlExport = __esm({
29078
29414
  completedAttemptKeys: buildCompletedBacktestDatasetAttemptKeys(completed)
29079
29415
  };
29080
29416
  };
29081
- main32 = async () => {
29417
+ main33 = async () => {
29082
29418
  const outDir = String(flags20.outDir || "data/ml/export");
29083
29419
  await import_promises24.default.mkdir(outDir, { recursive: true });
29084
29420
  const strategyName = await resolveExportStrategy({
@@ -29144,9 +29480,9 @@ var init_mlExport = __esm({
29144
29480
  // src/scripts/mlInspect.ts
29145
29481
  var mlInspect_exports = {};
29146
29482
  __export(mlInspect_exports, {
29147
- main: () => main33
29483
+ main: () => main34
29148
29484
  });
29149
- var import_args23, import_chalk38, import_promises25, import_fs3, import_path9, import_readline2, import_child_process2, flags21, toMode, toInspectTool, selectInspectTool, asPositiveInt, readRowsHead, readRowsTail, readRowsSample, quantileSorted, mean2, std, findLatestDataset, buildNumericStats, formatNumber5, runQuickInspect, runYDataInspect, main33;
29485
+ var import_args23, import_chalk38, import_promises25, import_fs3, import_path9, import_readline2, import_child_process2, flags21, toMode, toInspectTool, selectInspectTool, asPositiveInt, readRowsHead, readRowsTail, readRowsSample, quantileSorted, mean2, std, findLatestDataset, buildNumericStats, formatNumber5, runQuickInspect, runYDataInspect, main34;
29150
29486
  var init_mlInspect = __esm({
29151
29487
  "src/scripts/mlInspect.ts"() {
29152
29488
  "use strict";
@@ -29638,7 +29974,7 @@ var init_mlInspect = __esm({
29638
29974
  }
29639
29975
  console.log(import_chalk38.default.green(`Profile report saved: ${reportPath}`));
29640
29976
  };
29641
- main33 = async () => {
29977
+ main34 = async () => {
29642
29978
  const dir = String(flags21.dir || "data/ml/export");
29643
29979
  const rowsToInspect = asPositiveInt(flags21.rows, 1e4);
29644
29980
  const mode = toMode(flags21.mode);
@@ -29680,9 +30016,9 @@ var init_mlInspect = __esm({
29680
30016
  // src/scripts/mlTrainLatestSelect.ts
29681
30017
  var mlTrainLatestSelect_exports = {};
29682
30018
  __export(mlTrainLatestSelect_exports, {
29683
- main: () => main34
30019
+ main: () => main35
29684
30020
  });
29685
- var import_path10, import_promises26, import_fs4, import_crypto2, import_child_process3, import_events, import_readline3, import_args24, import_chalk39, import_ml2, toFileToken6, asBool, asInt7, asNonNegativeInt, formatBytes, getMlContainerMemUsage, MODEL_TYPES, STRATEGIES, flags22, parseStrategy, parseModelType, selectModelType, listDatasetFiles, concatFiles, pipeNormalized, DAY_MS12, SPLIT_PROGRESS_EVERY, parseTimestampMs, scanMaxLabeledTimestampMs, scanMaxTrainTimestampMs, hashFileNameSha1, prepareTrainWindowFiles, main34;
30021
+ var import_path10, import_promises26, import_fs4, import_crypto2, import_child_process3, import_events, import_readline3, import_args24, import_chalk39, import_ml2, toFileToken6, asBool, asInt7, asNonNegativeInt, formatBytes, getMlContainerMemUsage, MODEL_TYPES, STRATEGIES, flags22, parseStrategy, parseModelType, selectModelType, listDatasetFiles, concatFiles, pipeNormalized, DAY_MS13, SPLIT_PROGRESS_EVERY, parseTimestampMs, scanMaxLabeledTimestampMs, scanMaxTrainTimestampMs, hashFileNameSha1, prepareTrainWindowFiles, main35;
29686
30022
  var init_mlTrainLatestSelect = __esm({
29687
30023
  "src/scripts/mlTrainLatestSelect.ts"() {
29688
30024
  "use strict";
@@ -29873,7 +30209,7 @@ var init_mlTrainLatestSelect = __esm({
29873
30209
  }
29874
30210
  };
29875
30211
  };
29876
- DAY_MS12 = 24 * 60 * 60 * 1e3;
30212
+ DAY_MS13 = 24 * 60 * 60 * 1e3;
29877
30213
  SPLIT_PROGRESS_EVERY = 2e5;
29878
30214
  parseTimestampMs = (value) => {
29879
30215
  const numeric = Number(value);
@@ -30090,7 +30426,7 @@ var init_mlTrainLatestSelect = __esm({
30090
30426
  }
30091
30427
  console.log("[split] phase 1/3: scanning max labeled timestamp...");
30092
30428
  const maxLabeledTs = await scanMaxLabeledTimestampMs(inputPath);
30093
- const holdoutCutoffMs = maxLabeledTs - testDays * DAY_MS12;
30429
+ const holdoutCutoffMs = maxLabeledTs - testDays * DAY_MS13;
30094
30430
  console.log("[split] phase 2/3: scanning max train timestamp...");
30095
30431
  const maxTrainTs = await scanMaxTrainTimestampMs(inputPath, holdoutCutoffMs);
30096
30432
  const {
@@ -30403,7 +30739,7 @@ var init_mlTrainLatestSelect = __esm({
30403
30739
  }
30404
30740
  };
30405
30741
  };
30406
- main34 = async () => {
30742
+ main35 = async () => {
30407
30743
  const selectedFromCli = parseStrategy(flags22.strategy);
30408
30744
  const selected = selectedFromCli ?? await selectStrategy();
30409
30745
  const envModelType = (process.env.ML_MODEL_TYPE ?? "random_forest").trim().toLowerCase();
@@ -30667,7 +31003,7 @@ __export(researchAuto_exports, {
30667
31003
  isProcessAlive: () => isProcessAlive,
30668
31004
  listMergedFiles: () => listMergedFiles3,
30669
31005
  listRuntimeStrategyNames: () => listRuntimeStrategyNames,
30670
- main: () => main35,
31006
+ main: () => main36,
30671
31007
  parseJsonOutput: () => parseJsonOutput,
30672
31008
  releaseResearchAutoLock: () => releaseResearchAutoLock,
30673
31009
  resolveHeapMbFromEnv: () => resolveHeapMbFromEnv,
@@ -30677,7 +31013,7 @@ __export(researchAuto_exports, {
30677
31013
  toStrategyConfigGrid: () => toStrategyConfigGrid2,
30678
31014
  trimTextTail: () => trimTextTail2
30679
31015
  });
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;
31016
+ 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, main36;
30681
31017
  var init_researchAuto = __esm({
30682
31018
  "src/scripts/researchAuto.ts"() {
30683
31019
  "use strict";
@@ -30687,10 +31023,10 @@ var init_researchAuto = __esm({
30687
31023
  import_promises27 = __toESM(require("fs/promises"));
30688
31024
  import_node_os2 = __toESM(require("os"));
30689
31025
  import_node_path20 = __toESM(require("path"));
30690
- import_constants18 = require("@tradejs/core/constants");
31026
+ import_constants19 = require("@tradejs/core/constants");
30691
31027
  import_ai8 = require("@tradejs/infra/ai");
30692
- import_logger6 = require("@tradejs/infra/logger");
30693
- import_redis16 = require("@tradejs/infra/redis");
31028
+ import_logger7 = require("@tradejs/infra/logger");
31029
+ import_redis17 = require("@tradejs/infra/redis");
30694
31030
  import_registry4 = require("@tradejs/node/registry");
30695
31031
  init_runtimeRedis();
30696
31032
  init_runtimeStrategyBacktest();
@@ -30892,11 +31228,11 @@ var init_researchAuto = __esm({
30892
31228
  }
30893
31229
  });
30894
31230
  saveRun = async (run) => {
30895
- await (0, import_redis16.setData)(import_redis16.redisKeys.researchRun(run.userName, run.runId), run, {
30896
- expire: import_constants18.TTL_1M
31231
+ await (0, import_redis17.setData)(import_redis17.redisKeys.researchRun(run.userName, run.runId), run, {
31232
+ expire: import_constants19.TTL_1M
30897
31233
  });
30898
- await (0, import_redis16.setData)(import_redis16.redisKeys.researchLatestRun(run.userName, run.strategy), run, {
30899
- expire: import_constants18.TTL_1M
31234
+ await (0, import_redis17.setData)(import_redis17.redisKeys.researchLatestRun(run.userName, run.strategy), run, {
31235
+ expire: import_constants19.TTL_1M
30900
31236
  });
30901
31237
  };
30902
31238
  listMergedFiles3 = async (outDir, strategyName) => {
@@ -31057,13 +31393,13 @@ var init_researchAuto = __esm({
31057
31393
  const emitLines = (source, text3) => {
31058
31394
  const prefix = params.liveLogPrefix ? `[research:auto:${params.liveLogPrefix}:${source}] ` : `[research:auto:${source}] `;
31059
31395
  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}`));
31396
+ import_logger7.logger.info(import_chalk40.default.gray(`${prefix}${line}`));
31061
31397
  }
31062
31398
  };
31063
31399
  if (params.heartbeatMs && params.heartbeatMs > 0) {
31064
31400
  heartbeatTimer = setInterval(() => {
31065
31401
  const elapsedMs = Date.now() - startedAt;
31066
- import_logger6.logger.info(
31402
+ import_logger7.logger.info(
31067
31403
  import_chalk40.default.gray(
31068
31404
  `[research:auto:${params.liveLogPrefix || params.command}] still running after ${Math.round(elapsedMs / 1e3)}s`
31069
31405
  )
@@ -31125,8 +31461,8 @@ var init_researchAuto = __esm({
31125
31461
  const candidates = [];
31126
31462
  for (const strategy of availableStrategies) {
31127
31463
  const config2 = `${strategy}:research`;
31128
- const latestRun = await (0, import_redis16.getData)(
31129
- import_redis16.redisKeys.researchLatestRun(userName3, strategy),
31464
+ const latestRun = await (0, import_redis17.getData)(
31465
+ import_redis17.redisKeys.researchLatestRun(userName3, strategy),
31130
31466
  null
31131
31467
  );
31132
31468
  const lastFinishedAt = latestRun?.finishedAt ? Date.parse(latestRun.finishedAt) : 0;
@@ -31163,7 +31499,7 @@ var init_researchAuto = __esm({
31163
31499
  return JSON.parse(trimmed);
31164
31500
  };
31165
31501
  logResearch = (message) => {
31166
- import_logger6.logger.info(import_chalk40.default.cyan(`[research:auto] ${message}`));
31502
+ import_logger7.logger.info(import_chalk40.default.cyan(`[research:auto] ${message}`));
31167
31503
  };
31168
31504
  executeNonBlockingStep = async (run, stepName, command, commandArgs, options = {}) => {
31169
31505
  logResearch(
@@ -31202,7 +31538,7 @@ var init_researchAuto = __esm({
31202
31538
  );
31203
31539
  return result;
31204
31540
  };
31205
- main35 = async () => {
31541
+ main36 = async () => {
31206
31542
  resolveRequiredResearchRoots({ projectRoot: projectRoot8 });
31207
31543
  const userName3 = String(flags23.user || "root").trim() || "root";
31208
31544
  const connector = String(flags23.connector || "bybit").trim() || "bybit";
@@ -31305,13 +31641,13 @@ var init_researchAuto = __esm({
31305
31641
  startedAt
31306
31642
  };
31307
31643
  await saveRun(run);
31308
- const strategyConfigKey = import_redis16.redisKeys.strategyConfig(
31644
+ const strategyConfigKey = import_redis17.redisKeys.strategyConfig(
31309
31645
  userName3,
31310
31646
  target.strategy
31311
31647
  );
31312
- const backtestConfigKey = import_redis16.redisKeys.backtestConfig(userName3, target.config);
31648
+ const backtestConfigKey = import_redis17.redisKeys.backtestConfig(userName3, target.config);
31313
31649
  const defaults = await (0, import_registry4.getStrategyDefaults)(target.strategy, projectRoot8) || {};
31314
- const userStrategyConfig = await (0, import_redis16.getData)(
31650
+ const userStrategyConfig = await (0, import_redis17.getData)(
31315
31651
  strategyConfigKey,
31316
31652
  {}
31317
31653
  );
@@ -31325,7 +31661,7 @@ var init_researchAuto = __esm({
31325
31661
  );
31326
31662
  }
31327
31663
  const backtestConfig = toStrategyConfigGrid2(strategyConfig);
31328
- await (0, import_redis16.setData)(backtestConfigKey, backtestConfig, { expire: 0 });
31664
+ await (0, import_redis17.setData)(backtestConfigKey, backtestConfig, { expire: 0 });
31329
31665
  logResearch(
31330
31666
  `stored backtest config at ${backtestConfigKey} with ${Object.keys(strategyConfig).length} top-level fields`
31331
31667
  );
@@ -31365,7 +31701,7 @@ var init_researchAuto = __esm({
31365
31701
  `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
31702
  );
31367
31703
  const backtestKeysBefore = new Set(
31368
- await (0, import_redis16.getKeys)(getBacktestResultsPrefix(userName3, target.config))
31704
+ await (0, import_redis17.getKeys)(getBacktestResultsPrefix(userName3, target.config))
31369
31705
  );
31370
31706
  const aiFilesBefore = new Set(
31371
31707
  await listMergedFiles3(outDir, target.strategy)
@@ -31427,14 +31763,14 @@ var init_researchAuto = __esm({
31427
31763
  captureMode: "full"
31428
31764
  }
31429
31765
  );
31430
- const backtestKeysAfter = await (0, import_redis16.getKeys)(
31766
+ const backtestKeysAfter = await (0, import_redis17.getKeys)(
31431
31767
  getBacktestResultsPrefix(userName3, target.config)
31432
31768
  );
31433
31769
  const newBacktestKeys = backtestKeysAfter.filter((key2) => !backtestKeysBefore.has(key2)).sort();
31434
31770
  const backtestResultKey = newBacktestKeys[newBacktestKeys.length - 1] || backtestKeysAfter.sort().at(-1);
31435
31771
  if (backtestResultKey) {
31436
31772
  logResearch(`detected backtest result key ${backtestResultKey}`);
31437
- const backtestResult = await (0, import_redis16.getData)(backtestResultKey, null);
31773
+ const backtestResult = await (0, import_redis17.getData)(backtestResultKey, null);
31438
31774
  run.artifacts.backtestResultKey = backtestResultKey;
31439
31775
  run.artifacts.backtestResult = backtestResult ? {
31440
31776
  finishedAt: backtestResult.finishedAt,
@@ -32134,8 +32470,8 @@ var init_dataset2 = __esm({
32134
32470
  for (const inputPath of variant.files) {
32135
32471
  const filePath = import_node_path22.default.resolve(inputPath);
32136
32472
  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));
32473
+ const hash2 = (0, import_node_crypto17.createHash)("sha256");
32474
+ input.on("data", (chunk) => hash2.update(chunk));
32139
32475
  const lines = import_node_readline3.default.createInterface({ input, crlfDelay: Infinity });
32140
32476
  const fileTrades = [];
32141
32477
  let lineNumber = 0;
@@ -32185,7 +32521,7 @@ var init_dataset2 = __esm({
32185
32521
  trades.push(trade);
32186
32522
  fileTrades.push(trade);
32187
32523
  }
32188
- const fileSha2562 = hash3.digest("hex");
32524
+ const fileSha2562 = hash2.digest("hex");
32189
32525
  for (const trade of fileTrades) trade.sourceSha256 = fileSha2562;
32190
32526
  sources.push({
32191
32527
  path: filePath,
@@ -33373,9 +33709,9 @@ var init_orchestrator = __esm({
33373
33709
  // src/scripts/coreResearch.ts
33374
33710
  var coreResearch_exports = {};
33375
33711
  __export(coreResearch_exports, {
33376
- main: () => main36
33712
+ main: () => main37
33377
33713
  });
33378
- var import_promises30, import_node_path24, import_chalk41, valueAfter, required, parseTimestamp, readSymbols, printUsage, main36;
33714
+ var import_promises30, import_node_path24, import_chalk41, valueAfter, required, parseTimestamp, readSymbols, printUsage, main37;
33379
33715
  var init_coreResearch = __esm({
33380
33716
  "src/scripts/coreResearch.ts"() {
33381
33717
  "use strict";
@@ -33424,7 +33760,7 @@ var init_coreResearch = __esm({
33424
33760
 
33425
33761
  The run command executes only variants with an explicit command[] in the preregistered spec. Variants with files[] are analyzed without starting a backtest.`);
33426
33762
  };
33427
- main36 = async () => {
33763
+ main37 = async () => {
33428
33764
  const roots = resolveResearchRoots();
33429
33765
  process.chdir(roots.projectRoot);
33430
33766
  const argv2 = process.argv.slice(2);
@@ -33744,55 +34080,6 @@ var init_specification = __esm({
33744
34080
  }
33745
34081
  });
33746
34082
 
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
34083
  // src/lib/strategyResearch/io.ts
33797
34084
  var io_exports = {};
33798
34085
  __export(io_exports, {
@@ -33805,14 +34092,14 @@ __export(io_exports, {
33805
34092
  verifyResearchState: () => verifyResearchState,
33806
34093
  withResearchLock: () => withResearchLock
33807
34094
  });
33808
- var import_promises31, import_node_path25, import_node_os3, import_node_crypto20, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
34095
+ var import_promises31, import_node_path25, import_node_os3, import_node_crypto19, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
33809
34096
  var init_io2 = __esm({
33810
34097
  "src/lib/strategyResearch/io.ts"() {
33811
34098
  "use strict";
33812
34099
  import_promises31 = __toESM(require("fs/promises"));
33813
34100
  import_node_path25 = __toESM(require("path"));
33814
34101
  import_node_os3 = __toESM(require("os"));
33815
- import_node_crypto20 = require("crypto");
34102
+ import_node_crypto19 = require("crypto");
33816
34103
  init_io();
33817
34104
  researchDirectory = (projectRoot18, spec) => import_node_path25.default.join(projectRoot18, "data/research/strategy", spec.core.researchId);
33818
34105
  readJson = async (file) => JSON.parse(await import_promises31.default.readFile(file, "utf8"));
@@ -33841,7 +34128,7 @@ var init_io2 = __esm({
33841
34128
  "data/research/strategy/.lock"
33842
34129
  );
33843
34130
  await import_promises31.default.mkdir(import_node_path25.default.dirname(file), { recursive: true });
33844
- const token = (0, import_node_crypto20.randomUUID)();
34131
+ const token = (0, import_node_crypto19.randomUUID)();
33845
34132
  const acquire = () => import_promises31.default.writeFile(
33846
34133
  file,
33847
34134
  JSON.stringify({ pid: process.pid, host: import_node_os3.default.hostname(), token }),
@@ -33937,15 +34224,15 @@ var init_io2 = __esm({
33937
34224
  await writeJsonAtomic(file, state);
33938
34225
  return state;
33939
34226
  };
33940
- isRetainedDeletion = async (directory, file, hash3) => {
34227
+ isRetainedDeletion = async (directory, file, hash2) => {
33941
34228
  try {
33942
34229
  const inventory = await readJson(import_node_path25.default.join(directory, "retention.json"));
33943
34230
  const index = inventory.entries.findIndex(
33944
- (entry) => entry.path === file && entry.sha256 === hash3
34231
+ (entry) => entry.path === file && entry.sha256 === hash2
33945
34232
  );
33946
34233
  if (index < 0) return false;
33947
34234
  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;
34235
+ return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 === hash2;
33949
34236
  } catch (error) {
33950
34237
  if (error.code === "ENOENT") return false;
33951
34238
  throw error;
@@ -35116,11 +35403,11 @@ print(json.dumps(sorted(opened)))
35116
35403
  });
35117
35404
 
35118
35405
  // src/lib/strategyRelease/evidenceRetention.ts
35119
- var DAY_MS13, isResearchRetired, planStrategyEvidenceRetention;
35406
+ var DAY_MS14, isResearchRetired, planStrategyEvidenceRetention;
35120
35407
  var init_evidenceRetention = __esm({
35121
35408
  "src/lib/strategyRelease/evidenceRetention.ts"() {
35122
35409
  "use strict";
35123
- DAY_MS13 = 864e5;
35410
+ DAY_MS14 = 864e5;
35124
35411
  isResearchRetired = (research) => research?.status === "retired" && research.retirement?.policy === "discard-unrecoverable-without-rerun" && Boolean(research.retirement.reason.trim()) && Boolean(research.retirement.missingEvidence.length) && research.retirement.missingEvidence.every((item) => Boolean(item.trim()));
35125
35412
  planStrategyEvidenceRetention = ({
35126
35413
  now: now2,
@@ -35152,7 +35439,7 @@ var init_evidenceRetention = __esm({
35152
35439
  const completedResearch = Boolean(
35153
35440
  terminalResearch && research?.researchId === entry.researchId && /^[a-f0-9]{64}$/.test(entry.sha256 ?? "")
35154
35441
  );
35155
- if (isResearch && !completedResearch || days == null || !entry.verified || !entry.aggregated && !(isResearch && retired) || !isResearch && now2 - entry.createdAt <= days * DAY_MS13) {
35442
+ if (isResearch && !completedResearch || days == null || !entry.verified || !entry.aggregated && !(isResearch && retired) || !isResearch && now2 - entry.createdAt <= days * DAY_MS14) {
35156
35443
  keep.push(entry);
35157
35444
  } else {
35158
35445
  remove.push(entry);
@@ -35168,14 +35455,14 @@ var init_evidenceRetention = __esm({
35168
35455
  });
35169
35456
 
35170
35457
  // src/lib/strategyRelease/researchRetention.ts
35171
- var import_promises32, import_node_path27, import_node_crypto21, import_strategyReleaseEvidence2, SHA256_RE2, mapFiles, fileSha256, inside, applyResearchRetention;
35458
+ var import_promises32, import_researchMetricSnapshot, import_node_path27, import_node_crypto20, import_strategyReleaseEvidence2, SHA256_RE2, mapFiles, fileSha256, inside, applyResearchRetention;
35172
35459
  var init_researchRetention = __esm({
35173
35460
  "src/lib/strategyRelease/researchRetention.ts"() {
35174
35461
  "use strict";
35175
35462
  import_promises32 = __toESM(require("fs/promises"));
35176
- init_researchMetricSnapshot();
35463
+ import_researchMetricSnapshot = require("@tradejs/infra/researchMetricSnapshot");
35177
35464
  import_node_path27 = __toESM(require("path"));
35178
- import_node_crypto21 = require("crypto");
35465
+ import_node_crypto20 = require("crypto");
35179
35466
  import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
35180
35467
  init_researchFileConsumers();
35181
35468
  init_evidenceRetention();
@@ -35195,7 +35482,7 @@ var init_researchRetention = __esm({
35195
35482
  if (worker.status === "rejected") throw worker.reason;
35196
35483
  return results2;
35197
35484
  };
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);
35485
+ 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
35486
  inside = (root, file) => {
35200
35487
  const relative = import_node_path27.default.relative(root, file);
35201
35488
  return relative !== "" && !relative.startsWith(`..${import_node_path27.default.sep}`) && relative !== ".." && !import_node_path27.default.isAbsolute(relative);
@@ -35258,7 +35545,7 @@ var init_researchRetention = __esm({
35258
35545
  throw new Error(
35259
35546
  "Complete v2 note needs one verified metric snapshot"
35260
35547
  );
35261
- decodeResearchMetricSnapshot(JSON.parse(blocks[0][1]));
35548
+ (0, import_researchMetricSnapshot.decodeResearchMetricSnapshot)(JSON.parse(blocks[0][1]));
35262
35549
  }
35263
35550
  } finally {
35264
35551
  await handle.close();
@@ -35382,11 +35669,11 @@ var init_retention = __esm({
35382
35669
  }
35383
35670
  const files = /* @__PURE__ */ new Map();
35384
35671
  for (const stage of Object.values(state.stages)) {
35385
- for (const [relative, hash3] of Object.entries(stage.artifacts)) {
35672
+ for (const [relative, hash2] of Object.entries(stage.artifacts)) {
35386
35673
  const file = await boundResearchPath(directory, relative);
35387
35674
  if (relative.endsWith("/result.json")) {
35388
35675
  const result = await readJson(file);
35389
- if (result?.dataset) files.set(file, hash3);
35676
+ if (result?.dataset) files.set(file, hash2);
35390
35677
  }
35391
35678
  if (relative.endsWith("/sources.json") || relative.endsWith("/payloads.json")) {
35392
35679
  const sources = await readJson(file);
@@ -35403,13 +35690,13 @@ var init_retention = __esm({
35403
35690
  }
35404
35691
  }
35405
35692
  const entries = [];
35406
- for (const [file, hash3] of files) {
35693
+ for (const [file, hash2] of files) {
35407
35694
  const stat = await import_promises33.default.stat(file);
35408
35695
  entries.push({
35409
35696
  path: file,
35410
35697
  kind: "research_payload",
35411
35698
  researchId: spec.core.researchId,
35412
- sha256: hash3,
35699
+ sha256: hash2,
35413
35700
  bytes: stat.size,
35414
35701
  createdAt: stat.birthtimeMs,
35415
35702
  verified: true,
@@ -35493,12 +35780,12 @@ var init_retention = __esm({
35493
35780
  });
35494
35781
 
35495
35782
  // src/lib/strategyResearch/orchestrator.ts
35496
- var import_promises34, import_node_path29, runStrategyResearch;
35783
+ var import_promises34, import_researchMetricSnapshot2, import_node_path29, runStrategyResearch;
35497
35784
  var init_orchestrator2 = __esm({
35498
35785
  "src/lib/strategyResearch/orchestrator.ts"() {
35499
35786
  "use strict";
35500
35787
  import_promises34 = __toESM(require("fs/promises"));
35501
- init_researchMetricSnapshot();
35788
+ import_researchMetricSnapshot2 = require("@tradejs/infra/researchMetricSnapshot");
35502
35789
  import_node_path29 = __toESM(require("path"));
35503
35790
  init_metrics();
35504
35791
  init_io();
@@ -35689,7 +35976,7 @@ var init_orchestrator2 = __esm({
35689
35976
  });
35690
35977
  let partitionControl;
35691
35978
  if (spec.testSince === 0) {
35692
- const control2 = spec.core.variants.find(
35979
+ const control = spec.core.variants.find(
35693
35980
  (variant) => variant.role === "control"
35694
35981
  );
35695
35982
  partitionControl = await stage(
@@ -35706,7 +35993,7 @@ var init_orchestrator2 = __esm({
35706
35993
  }
35707
35994
  return backend.runVariant(
35708
35995
  spec,
35709
- control2,
35996
+ control,
35710
35997
  folder,
35711
35998
  async (runId) => writeJsonAtomic(import_node_path29.default.join(folder, "native-run.json"), {
35712
35999
  runId
@@ -35728,9 +36015,6 @@ var init_orchestrator2 = __esm({
35728
36015
  let frozenSelection;
35729
36016
  const raw = {};
35730
36017
  const discovered = [];
35731
- const control = spec.core.variants.find(
35732
- (variant) => variant.role === "control"
35733
- );
35734
36018
  const currentPolicy = {
35735
36019
  schema: "tradejs-research-entry-policy/v1",
35736
36020
  strategy: spec.core.strategy,
@@ -36206,7 +36490,7 @@ ${JSON.stringify(spec, null, 2)}
36206
36490
  ## Metrics snapshot (machine-readable)
36207
36491
 
36208
36492
  \`\`\`json
36209
- ${JSON.stringify(encodeResearchMetricSnapshot(compact))}
36493
+ ${JSON.stringify((0, import_researchMetricSnapshot2.encodeResearchMetricSnapshot)(compact))}
36210
36494
  \`\`\`
36211
36495
 
36212
36496
  ## Reported metrics
@@ -36324,7 +36608,7 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
36324
36608
  });
36325
36609
 
36326
36610
  // 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;
36611
+ 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_connectors15, import_data9, import_coreResearch2, import_jev6, validateResearchJevTraining, nativeConfig, runResearchCommand, createNativeStrategyResearchBackend;
36328
36612
  var init_native = __esm({
36329
36613
  "src/lib/strategyResearch/native.ts"() {
36330
36614
  "use strict";
@@ -36335,11 +36619,11 @@ var init_native = __esm({
36335
36619
  import_node_readline4 = __toESM(require("readline"));
36336
36620
  import_node_child_process8 = require("child_process");
36337
36621
  import_node_module3 = require("module");
36338
- import_redis17 = require("@tradejs/infra/redis");
36622
+ import_redis18 = require("@tradejs/infra/redis");
36339
36623
  import_ai9 = require("@tradejs/node/ai");
36340
36624
  import_backtest7 = require("@tradejs/node/backtest");
36341
36625
  import_registry5 = require("@tradejs/node/registry");
36342
- import_connectors14 = require("@tradejs/node/connectors");
36626
+ import_connectors15 = require("@tradejs/node/connectors");
36343
36627
  init_dataset2();
36344
36628
  init_reconciliation();
36345
36629
  init_metrics();
@@ -36500,7 +36784,7 @@ var init_native = __esm({
36500
36784
  let connector;
36501
36785
  const getConnector = async (spec) => {
36502
36786
  if (connector) return connector;
36503
- const creator = await (0, import_connectors14.getConnectorCreatorByName)(
36787
+ const creator = await (0, import_connectors15.getConnectorCreatorByName)(
36504
36788
  spec.core.execution.connector,
36505
36789
  projectRoot18
36506
36790
  );
@@ -36799,11 +37083,11 @@ var init_native = __esm({
36799
37083
  const grid = Object.fromEntries(
36800
37084
  Object.entries(config2).map(([key3, value]) => [key3, [value]])
36801
37085
  );
36802
- const key2 = import_redis17.redisKeys.backtestConfig("root", configName);
36803
- const existing = await (0, import_redis17.getData)(key2, null);
37086
+ const key2 = import_redis18.redisKeys.backtestConfig("root", configName);
37087
+ const existing = await (0, import_redis18.getData)(key2, null);
36804
37088
  if (existing != null && sha256Json(existing) !== sha256Json(grid))
36805
37089
  throw new Error(`Frozen research config changed: ${configName}`);
36806
- if (existing == null) await (0, import_redis17.setData)(key2, grid, { expire: 0 });
37090
+ if (existing == null) await (0, import_redis18.setData)(key2, grid, { expire: 0 });
36807
37091
  let runId = previousRunId ?? "";
36808
37092
  const common = {
36809
37093
  executable: process.execPath,
@@ -37235,9 +37519,9 @@ var init_strategyResearch = __esm({
37235
37519
  // src/scripts/strategyResearch.ts
37236
37520
  var strategyResearch_exports = {};
37237
37521
  __export(strategyResearch_exports, {
37238
- main: () => main37
37522
+ main: () => main38
37239
37523
  });
37240
- var import_promises36, import_node_path31, import_redis18, usage, main37;
37524
+ var import_promises36, import_node_path31, import_redis19, usage, main38;
37241
37525
  var init_strategyResearch2 = __esm({
37242
37526
  "src/scripts/strategyResearch.ts"() {
37243
37527
  "use strict";
@@ -37247,7 +37531,7 @@ var init_strategyResearch2 = __esm({
37247
37531
  init_researchRoots();
37248
37532
  init_io();
37249
37533
  init_orchestrator();
37250
- import_redis18 = require("@tradejs/infra/redis");
37534
+ import_redis19 = require("@tradejs/infra/redis");
37251
37535
  init_io2();
37252
37536
  usage = `Usage:
37253
37537
  tradejs research:strategy init --coreSpec <core-spec.json> --out <workflow.json>
@@ -37262,7 +37546,7 @@ frozen rules, actual gated entries, non-fast and delayed-entry confirmation.
37262
37546
  Resume with the same run command. No notifications, publication or live orders.
37263
37547
  Revalidate keeps the frozen rule and evaluates a new period without fitting.
37264
37548
  `;
37265
- main37 = async () => {
37549
+ main38 = async () => {
37266
37550
  const argv2 = process.argv.slice(2);
37267
37551
  const command = argv2.shift();
37268
37552
  if (!command || command === "--help") {
@@ -37335,8 +37619,8 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
37335
37619
  throw new Error(
37336
37620
  "Every config must belong to the selected strategy"
37337
37621
  );
37338
- const grid = await (0, import_redis18.getData)(
37339
- import_redis18.redisKeys.backtestConfig("root", configName),
37622
+ const grid = await (0, import_redis19.getData)(
37623
+ import_redis19.redisKeys.backtestConfig("root", configName),
37340
37624
  null
37341
37625
  );
37342
37626
  if (!grid || typeof grid !== "object" || Array.isArray(grid) || !Object.keys(grid).length)
@@ -37473,18 +37757,18 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
37473
37757
  // src/scripts/results.ts
37474
37758
  var results_exports = {};
37475
37759
  __export(results_exports, {
37476
- main: () => main38,
37760
+ main: () => main39,
37477
37761
  results: () => results
37478
37762
  });
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;
37763
+ var import_args26, import_chalk42, import_connectors16, 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, main39;
37480
37764
  var init_results = __esm({
37481
37765
  "src/scripts/results.ts"() {
37482
37766
  "use strict";
37483
37767
  import_args26 = __toESM(require("args"));
37484
37768
  import_chalk42 = __toESM(require("chalk"));
37485
- import_connectors15 = require("@tradejs/connectors");
37769
+ import_connectors16 = require("@tradejs/connectors");
37486
37770
  import_cli11 = require("@tradejs/node/cli");
37487
- import_redis19 = require("@tradejs/infra/redis");
37771
+ import_redis20 = require("@tradejs/infra/redis");
37488
37772
  ListIt4 = require("list-it");
37489
37773
  import_args26.default.example(
37490
37774
  "yarn results --strategy TrendLine --coverage",
@@ -37524,8 +37808,8 @@ var init_results = __esm({
37524
37808
  [...rows].map((row) => [row.symbol, toStrategyResultEntry(row)])
37525
37809
  );
37526
37810
  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;
37811
+ const testSummariesKey = typeof import_redis20.redisKeys.testSummaries === "function" ? import_redis20.redisKeys.testSummaries(userName3) : null;
37812
+ const indexedItems = testSummariesKey ? await (0, import_redis20.getData)(testSummariesKey, null) : null;
37529
37813
  if (Array.isArray(indexedItems) && indexedItems.length) {
37530
37814
  return indexedItems.map((item) => {
37531
37815
  const testName = typeof item?.value === "string" ? item.value : null;
@@ -37536,8 +37820,8 @@ var init_results = __esm({
37536
37820
  return { strategyName, testName };
37537
37821
  }).filter(Boolean);
37538
37822
  }
37539
- const testsPrefix = import_redis19.redisKeys.tests(userName3);
37540
- const keys = await (0, import_redis19.getKeys)(testsPrefix);
37823
+ const testsPrefix = import_redis20.redisKeys.tests(userName3);
37824
+ const keys = await (0, import_redis20.getKeys)(testsPrefix);
37541
37825
  const configKeys = keys.filter((key2) => key2.endsWith(":config"));
37542
37826
  return configKeys.map((key2) => {
37543
37827
  const parts = key2.split(":");
@@ -37556,15 +37840,15 @@ var init_results = __esm({
37556
37840
  testName,
37557
37841
  strategyName: strategyFromIndex
37558
37842
  } of testConfigs) {
37559
- const config2 = await (0, import_redis19.getData)(
37560
- import_redis19.redisKeys.testConfig(userName3, strategyFromIndex, testName),
37843
+ const config2 = await (0, import_redis20.getData)(
37844
+ import_redis20.redisKeys.testConfig(userName3, strategyFromIndex, testName),
37561
37845
  null
37562
37846
  );
37563
37847
  if (!config2 || config2.strategyName !== strategyName) {
37564
37848
  continue;
37565
37849
  }
37566
- const stat = await (0, import_redis19.getData)(
37567
- import_redis19.redisKeys.testStat(userName3, strategyFromIndex, testName),
37850
+ const stat = await (0, import_redis20.getData)(
37851
+ import_redis20.redisKeys.testStat(userName3, strategyFromIndex, testName),
37568
37852
  null
37569
37853
  );
37570
37854
  if (!stat) {
@@ -37609,8 +37893,8 @@ var init_results = __esm({
37609
37893
  return savedProfitBySymbol;
37610
37894
  };
37611
37895
  getCoverageRow = async (strategyName, userName3, goodSymbols) => {
37612
- const currentResults = await (0, import_redis19.getData)(
37613
- import_redis19.redisKeys.strategyResults(userName3, strategyName),
37896
+ const currentResults = await (0, import_redis20.getData)(
37897
+ import_redis20.redisKeys.strategyResults(userName3, strategyName),
37614
37898
  {}
37615
37899
  );
37616
37900
  const existingSymbols = new Set(Object.keys(currentResults));
@@ -37623,7 +37907,7 @@ var init_results = __esm({
37623
37907
  goodMissing += 1;
37624
37908
  }
37625
37909
  }
37626
- const byBitConnector = await import_connectors15.connectors.ByBit({
37910
+ const byBitConnector = await import_connectors16.connectors.ByBit({
37627
37911
  userName: userName3
37628
37912
  });
37629
37913
  const tickers = await (0, import_cli11.getTickers)(byBitConnector);
@@ -37644,8 +37928,8 @@ var init_results = __esm({
37644
37928
  const strategyName = flags24.strategy;
37645
37929
  const userName3 = flags24.user;
37646
37930
  if (flags24.clear) {
37647
- const cleared = await (0, import_redis19.delKey)(
37648
- import_redis19.redisKeys.strategyResults(userName3, strategyName)
37931
+ const cleared = await (0, import_redis20.delKey)(
37932
+ import_redis20.redisKeys.strategyResults(userName3, strategyName)
37649
37933
  );
37650
37934
  console.log(
37651
37935
  cleared ? import_chalk42.default.green(`Cleared results:${strategyName}`) : import_chalk42.default.yellow(`No results to clear for ${strategyName}`)
@@ -37693,8 +37977,8 @@ var init_results = __esm({
37693
37977
  console.log(import_chalk42.default.yellow("No good results to merge."));
37694
37978
  process.exit(0);
37695
37979
  }
37696
- const current = await (0, import_redis19.getData)(
37697
- import_redis19.redisKeys.strategyResults(userName3, strategyName),
37980
+ const current = await (0, import_redis20.getData)(
37981
+ import_redis20.redisKeys.strategyResults(userName3, strategyName),
37698
37982
  {}
37699
37983
  );
37700
37984
  const savedProfitBySymbol = await getSavedProfitsBySymbol(current);
@@ -37716,7 +38000,7 @@ var init_results = __esm({
37716
38000
  ...current,
37717
38001
  ...toStrategyResults(updates)
37718
38002
  };
37719
- await (0, import_redis19.setData)(import_redis19.redisKeys.strategyResults(userName3, strategyName), merged, {
38003
+ await (0, import_redis20.setData)(import_redis20.redisKeys.strategyResults(userName3, strategyName), merged, {
37720
38004
  expire: 0
37721
38005
  });
37722
38006
  if (flags24.verbose) {
@@ -37757,8 +38041,8 @@ var init_results = __esm({
37757
38041
  );
37758
38042
  process.exit(0);
37759
38043
  }
37760
- await (0, import_redis19.setData)(
37761
- import_redis19.redisKeys.strategyResults(userName3, strategyName),
38044
+ await (0, import_redis20.setData)(
38045
+ import_redis20.redisKeys.strategyResults(userName3, strategyName),
37762
38046
  resultsConfig,
37763
38047
  {
37764
38048
  expire: 0
@@ -37772,16 +38056,16 @@ var init_results = __esm({
37772
38056
  }
37773
38057
  process.exit();
37774
38058
  };
37775
- main38 = results;
38059
+ main39 = results;
37776
38060
  }
37777
38061
  });
37778
38062
 
37779
38063
  // src/lib/runtimeDebugEvidence.ts
37780
- var import_redis20, RUNTIME_DEBUG_TIMEZONE, RUNTIME_DEBUG_TIMEZONE_LABEL, formatRuntimeDebugDateTime, getRuntimeDebugDateParts, formatRuntimeDebugIsoDayKey, buildRuntimeDebugEvaluationId, filterByStrategies, collectRuntimeDebugEvidence, buildRuntimeDebugReportPayload, buildRuntimeEvidenceReportPayload, buildRuntimeDebugReportAttachment;
38064
+ var import_redis21, RUNTIME_DEBUG_TIMEZONE, RUNTIME_DEBUG_TIMEZONE_LABEL, formatRuntimeDebugDateTime, getRuntimeDebugDateParts, formatRuntimeDebugIsoDayKey, buildRuntimeDebugEvaluationId, filterByStrategies, collectRuntimeDebugEvidence, buildRuntimeDebugReportPayload, buildRuntimeEvidenceReportPayload, buildRuntimeDebugReportAttachment;
37781
38065
  var init_runtimeDebugEvidence = __esm({
37782
38066
  "src/lib/runtimeDebugEvidence.ts"() {
37783
38067
  "use strict";
37784
- import_redis20 = require("@tradejs/infra/redis");
38068
+ import_redis21 = require("@tradejs/infra/redis");
37785
38069
  init_runtimeRedis();
37786
38070
  init_runtimeSignalsLoader();
37787
38071
  init_runtimeSignalsStorage();
@@ -37888,24 +38172,24 @@ var init_runtimeDebugEvidence = __esm({
37888
38172
  const tradeDayKey = (0, import_time5.getRuntimeStorageDayKey)(trade.entryTimestamp);
37889
38173
  const signalDayKey = signal != null ? (0, import_time5.getRuntimeStorageDayKey)(signal.timestamp) : tradeDayKey;
37890
38174
  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(
38175
+ const tradeKey = import_redis21.redisKeys.runtimeTrade(userName3, trade.orderId);
38176
+ const tradeBucketKey = import_redis21.redisKeys.runtimeTradeBucket(
37893
38177
  userName3,
37894
38178
  tradeDayKey
37895
38179
  );
37896
- const activeTradeKey = import_redis20.redisKeys.runtimeActiveTrade(
38180
+ const activeTradeKey = import_redis21.redisKeys.runtimeActiveTrade(
37897
38181
  userName3,
37898
38182
  trade.symbol,
37899
38183
  trade.deploymentId ?? trade.accountId
37900
38184
  );
37901
- const signalKey = trade.signalId != null ? import_redis20.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
37902
- const evaluationBucketKey = import_redis20.redisKeys.runtimeSignalEvaluationBucket(
38185
+ const signalKey = trade.signalId != null ? import_redis21.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
38186
+ const evaluationBucketKey = import_redis21.redisKeys.runtimeSignalEvaluationBucket(
37903
38187
  userName3,
37904
38188
  evaluationDayKey,
37905
38189
  knownEvaluation?.strategy ?? trade.strategy
37906
38190
  );
37907
38191
  const evaluationField = knownEvaluation?.evaluationId ?? evaluationId;
37908
- const evaluationKey = import_redis20.redisKeys.runtimeSignalEvaluation(
38192
+ const evaluationKey = import_redis21.redisKeys.runtimeSignalEvaluation(
37909
38193
  userName3,
37910
38194
  evaluationField
37911
38195
  );
@@ -37916,11 +38200,11 @@ var init_runtimeDebugEvidence = __esm({
37916
38200
  directEvaluationValue,
37917
38201
  bucketEvaluationValue
37918
38202
  ] = 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)(
38203
+ (0, import_redis21.getData)(tradeKey, null),
38204
+ (0, import_redis21.getData)(activeTradeKey, null),
38205
+ signalKey ? (0, import_redis21.getData)(signalKey, null) : Promise.resolve(null),
38206
+ (0, import_redis21.getData)(evaluationKey, null),
38207
+ knownEvaluation ? Promise.resolve(knownEvaluation) : (0, import_redis21.getHashJsonField)(
37924
38208
  evaluationBucketKey,
37925
38209
  evaluationField,
37926
38210
  null
@@ -37977,12 +38261,12 @@ var init_runtimeDebugEvidence = __esm({
37977
38261
  dayKeys
37978
38262
  },
37979
38263
  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)
38264
+ runtimeTrades: import_redis21.redisKeys.runtimeTrades(userName3),
38265
+ runtimeTradeBuckets: import_redis21.redisKeys.runtimeTradeBuckets(userName3),
38266
+ runtimeActiveTrades: import_redis21.redisKeys.runtimeActiveTrades(userName3),
38267
+ runtimeSignals: import_redis21.redisKeys.runtimeSignalBuckets(userName3),
38268
+ runtimeSignalEvaluations: import_redis21.redisKeys.runtimeSignalEvaluationBuckets(userName3),
38269
+ runtimeSignalEvaluationStats: import_redis21.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3)
37986
38270
  },
37987
38271
  counts: {
37988
38272
  trades: trades.length,
@@ -37993,18 +38277,18 @@ var init_runtimeDebugEvidence = __esm({
37993
38277
  },
37994
38278
  trades: debugTrades,
37995
38279
  signals: signals2.map((signal) => ({
37996
- redisKey: import_redis20.redisKeys.storeSignal(signal.symbol, signal.signalId),
38280
+ redisKey: import_redis21.redisKeys.storeSignal(signal.symbol, signal.signalId),
37997
38281
  signal
37998
38282
  })),
37999
38283
  evaluations: reportEvaluations.map((evaluation) => ({
38000
38284
  redisDebug: {
38001
- key: import_redis20.redisKeys.runtimeSignalEvaluationBucket(
38285
+ key: import_redis21.redisKeys.runtimeSignalEvaluationBucket(
38002
38286
  userName3,
38003
38287
  (0, import_time5.getRuntimeStorageDayKey)(evaluation.timestamp),
38004
38288
  evaluation.strategy
38005
38289
  ),
38006
38290
  field: evaluation.evaluationId,
38007
- directKey: import_redis20.redisKeys.runtimeSignalEvaluation(
38291
+ directKey: import_redis21.redisKeys.runtimeSignalEvaluation(
38008
38292
  userName3,
38009
38293
  evaluation.evaluationId
38010
38294
  )
@@ -38065,11 +38349,11 @@ var init_runtimeDebugEvidence = __esm({
38065
38349
  // src/scripts/replayRuntimeEvidence.ts
38066
38350
  var replayRuntimeEvidence_exports = {};
38067
38351
  __export(replayRuntimeEvidence_exports, {
38068
- main: () => main39,
38352
+ main: () => main40,
38069
38353
  replayRuntimeEvidence: () => replayRuntimeEvidence,
38070
38354
  summarizeReplayComparison: () => summarizeReplayComparison
38071
38355
  });
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;
38356
+ 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, main40;
38073
38357
  var init_replayRuntimeEvidence = __esm({
38074
38358
  "src/scripts/replayRuntimeEvidence.ts"() {
38075
38359
  "use strict";
@@ -38079,7 +38363,7 @@ var init_replayRuntimeEvidence = __esm({
38079
38363
  import_node_path32 = __toESM(require("path"));
38080
38364
  import_args27 = __toESM(require("args"));
38081
38365
  import_chalk43 = __toESM(require("chalk"));
38082
- import_redis21 = require("@tradejs/infra/redis");
38366
+ import_redis22 = require("@tradejs/infra/redis");
38083
38367
  init_runtimeDebugEvidence();
38084
38368
  init_support2();
38085
38369
  import_args27.default.option(["u", "user"], "Use user config", "root");
@@ -38168,6 +38452,8 @@ var init_replayRuntimeEvidence = __esm({
38168
38452
  timestampDiffMs: item.timestampDiffMs ?? null,
38169
38453
  backtestPrice: backtest2.price ?? null,
38170
38454
  runtimePrice: runtime.price ?? null,
38455
+ backtestQty: backtest2.qty ?? null,
38456
+ runtimeQty: runtime.qty ?? null,
38171
38457
  backtestExitPrice: backtest2.exitPrice ?? null,
38172
38458
  runtimeExitPrice: runtime.exitPrice ?? null,
38173
38459
  expectedPnl: pnl.expectedPnl ?? null,
@@ -38178,7 +38464,8 @@ var init_replayRuntimeEvidence = __esm({
38178
38464
  totalSlippageCost: slippage.totalCost ?? null,
38179
38465
  orderId: runtime.orderId ?? backtest2.orderId ?? null,
38180
38466
  orderLinkId: runtime.orderLinkId ?? null,
38181
- signalId: backtest2.signalId ?? null
38467
+ signalId: backtest2.signalId ?? null,
38468
+ runtimeSignalId: runtime.signalId ?? null
38182
38469
  };
38183
38470
  };
38184
38471
  resolveItemStrategy = (item) => asRecord5(item.backtest).strategy ?? asRecord5(item.runtime).inferredStrategy ?? item.strategy ?? item.inferredStrategy ?? null;
@@ -38299,18 +38586,18 @@ var init_replayRuntimeEvidence = __esm({
38299
38586
  return {
38300
38587
  key: replayKey,
38301
38588
  availableKeys: void 0,
38302
- value: await (0, import_redis21.getData)(replayKey, null)
38589
+ value: await (0, import_redis22.getData)(replayKey, null)
38303
38590
  };
38304
38591
  }
38305
- const prefix = import_redis21.redisKeys.backtestResults(userName3, REPLAY_RESULTS_CONFIG, "");
38306
- const keys = (await (0, import_redis21.getKeys)(prefix)).sort(
38592
+ const prefix = import_redis22.redisKeys.backtestResults(userName3, REPLAY_RESULTS_CONFIG, "");
38593
+ const keys = (await (0, import_redis22.getKeys)(prefix)).sort(
38307
38594
  (left, right) => left.localeCompare(right)
38308
38595
  );
38309
38596
  const key2 = keys[keys.length - 1] ?? null;
38310
38597
  return {
38311
38598
  key: key2,
38312
38599
  availableKeys: keys.slice(-10),
38313
- value: key2 ? await (0, import_redis21.getData)(key2, null) : null
38600
+ value: key2 ? await (0, import_redis22.getData)(key2, null) : null
38314
38601
  };
38315
38602
  };
38316
38603
  getReplayStrategies = (replayValue) => {
@@ -38446,7 +38733,7 @@ var init_replayRuntimeEvidence = __esm({
38446
38733
  )
38447
38734
  );
38448
38735
  };
38449
- main39 = replayRuntimeEvidence;
38736
+ main40 = replayRuntimeEvidence;
38450
38737
  }
38451
38738
  });
38452
38739
 
@@ -38754,10 +39041,10 @@ var init_runtimeFeedbackReplay = __esm({
38754
39041
  // src/scripts/runtimeFeedbackReplay.ts
38755
39042
  var runtimeFeedbackReplay_exports = {};
38756
39043
  __export(runtimeFeedbackReplay_exports, {
38757
- main: () => main40,
39044
+ main: () => main41,
38758
39045
  runtimeFeedbackReplay: () => runtimeFeedbackReplay
38759
39046
  });
38760
- var import_node_path34, import_args28, import_chalk44, flags25, projectRoot9, runtimeFeedbackReplay, main40;
39047
+ var import_node_path34, import_args28, import_chalk44, flags25, projectRoot9, runtimeFeedbackReplay, main41;
38761
39048
  var init_runtimeFeedbackReplay2 = __esm({
38762
39049
  "src/scripts/runtimeFeedbackReplay.ts"() {
38763
39050
  "use strict";
@@ -38801,7 +39088,7 @@ var init_runtimeFeedbackReplay2 = __esm({
38801
39088
  )
38802
39089
  );
38803
39090
  };
38804
- main40 = runtimeFeedbackReplay;
39091
+ main41 = runtimeFeedbackReplay;
38805
39092
  }
38806
39093
  });
38807
39094
 
@@ -38939,10 +39226,10 @@ var init_runtimeFeedbackNotification = __esm({
38939
39226
  // src/scripts/runtimeFeedbackNotify.ts
38940
39227
  var runtimeFeedbackNotify_exports = {};
38941
39228
  __export(runtimeFeedbackNotify_exports, {
38942
- main: () => main41,
39229
+ main: () => main42,
38943
39230
  runtimeFeedbackNotify: () => runtimeFeedbackNotify
38944
39231
  });
38945
- var import_node_path35, import_args29, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify, main41;
39232
+ var import_node_path35, import_args29, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify, main42;
38946
39233
  var init_runtimeFeedbackNotify = __esm({
38947
39234
  "src/scripts/runtimeFeedbackNotify.ts"() {
38948
39235
  "use strict";
@@ -38973,7 +39260,7 @@ var init_runtimeFeedbackNotify = __esm({
38973
39260
  )
38974
39261
  );
38975
39262
  };
38976
- main41 = runtimeFeedbackNotify;
39263
+ main42 = runtimeFeedbackNotify;
38977
39264
  }
38978
39265
  });
38979
39266
 
@@ -39945,13 +40232,13 @@ var init_runtimeEvidenceSync = __esm({
39945
40232
  });
39946
40233
 
39947
40234
  // src/lib/runtimeFeedbackProcess.ts
39948
- var import_promises40, import_node_path37, import_node_crypto22, import_diagnostics2, processRuntimeFeedbackPair;
40235
+ var import_promises40, import_node_path37, import_node_crypto21, import_diagnostics2, processRuntimeFeedbackPair;
39949
40236
  var init_runtimeFeedbackProcess = __esm({
39950
40237
  "src/lib/runtimeFeedbackProcess.ts"() {
39951
40238
  "use strict";
39952
40239
  import_promises40 = __toESM(require("fs/promises"));
39953
40240
  import_node_path37 = __toESM(require("path"));
39954
- import_node_crypto22 = require("crypto");
40241
+ import_node_crypto21 = require("crypto");
39955
40242
  import_diagnostics2 = require("@tradejs/node/diagnostics");
39956
40243
  init_executionCalibration();
39957
40244
  init_runtimeScorecard();
@@ -40010,7 +40297,7 @@ var init_runtimeFeedbackProcess = __esm({
40010
40297
  if (historyDir)
40011
40298
  for (const directory of await (0, import_diagnostics2.discoverRuntimeEvidenceBundles)(historyDir))
40012
40299
  history.push((await (0, import_diagnostics2.verifyRuntimeEvidenceBundle)(directory)).artifact);
40013
- const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "") + "-" + (0, import_node_crypto22.randomUUID)();
40300
+ const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "") + "-" + (0, import_node_crypto21.randomUUID)();
40014
40301
  const runDir = import_node_path37.default.join(outputRoot, artifactId, runId);
40015
40302
  await import_promises40.default.mkdir(runDir, { recursive: true });
40016
40303
  const calibration = buildExecutionCalibrationReport({
@@ -40065,9 +40352,9 @@ var init_runtimeFeedbackProcess = __esm({
40065
40352
  // src/scripts/runtimeFeedbackProcess.ts
40066
40353
  var runtimeFeedbackProcess_exports = {};
40067
40354
  __export(runtimeFeedbackProcess_exports, {
40068
- main: () => main42
40355
+ main: () => main43
40069
40356
  });
40070
- var import_args30, import_node_path38, flags27, main42;
40357
+ var import_args30, import_node_path38, flags27, main43;
40071
40358
  var init_runtimeFeedbackProcess2 = __esm({
40072
40359
  "src/scripts/runtimeFeedbackProcess.ts"() {
40073
40360
  "use strict";
@@ -40088,7 +40375,7 @@ var init_runtimeFeedbackProcess2 = __esm({
40088
40375
  "data/runtime-evidence/artifacts/production"
40089
40376
  );
40090
40377
  flags27 = import_args30.default.parse(process.argv);
40091
- main42 = async () => {
40378
+ main43 = async () => {
40092
40379
  if (!flags27.runtimeDir || !flags27.replayDir)
40093
40380
  throw new Error("Provide --runtimeDir and --replayDir");
40094
40381
  const root = process.env.PROJECT_CWD || process.cwd();
@@ -40201,10 +40488,10 @@ var init_runtimeFeedbackSync = __esm({
40201
40488
  // src/scripts/runtimeFeedbackSync.ts
40202
40489
  var runtimeFeedbackSync_exports = {};
40203
40490
  __export(runtimeFeedbackSync_exports, {
40204
- main: () => main43,
40491
+ main: () => main44,
40205
40492
  runtimeFeedbackSync: () => runtimeFeedbackSync
40206
40493
  });
40207
- var import_node_path40, import_args31, import_chalk46, flags28, projectRoot11, runtimeFeedbackSync, main43;
40494
+ var import_node_path40, import_args31, import_chalk46, flags28, projectRoot11, runtimeFeedbackSync, main44;
40208
40495
  var init_runtimeFeedbackSync2 = __esm({
40209
40496
  "src/scripts/runtimeFeedbackSync.ts"() {
40210
40497
  "use strict";
@@ -40263,16 +40550,16 @@ var init_runtimeFeedbackSync2 = __esm({
40263
40550
  )
40264
40551
  );
40265
40552
  };
40266
- main43 = runtimeFeedbackSync;
40553
+ main44 = runtimeFeedbackSync;
40267
40554
  }
40268
40555
  });
40269
40556
 
40270
40557
  // 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;
40558
+ 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
40559
  var init_runtimeEvidenceCompositionSnapshots = __esm({
40273
40560
  "src/lib/runtimeEvidenceCompositionSnapshots.ts"() {
40274
40561
  "use strict";
40275
- import_node_crypto23 = require("crypto");
40562
+ import_node_crypto22 = require("crypto");
40276
40563
  import_promises42 = __toESM(require("fs/promises"));
40277
40564
  import_node_path41 = __toESM(require("path"));
40278
40565
  init_runtimeEvidenceDeployment();
@@ -40295,7 +40582,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
40295
40582
  };
40296
40583
  };
40297
40584
  isRecord2 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
40298
- sha256 = (value) => (0, import_node_crypto23.createHash)("sha256").update(value).digest("hex");
40585
+ sha256 = (value) => (0, import_node_crypto22.createHash)("sha256").update(value).digest("hex");
40299
40586
  safeSegment4 = (value, label) => {
40300
40587
  const normalized = value.trim();
40301
40588
  if (!normalized || !/^[a-zA-Z0-9._:-]+$/.test(normalized)) {
@@ -40387,7 +40674,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
40387
40674
  const temporaryDir = import_node_path41.default.join(
40388
40675
  evidenceRoot,
40389
40676
  "incoming",
40390
- `snapshot-${compositionId}.tmp-${(0, import_node_crypto23.randomUUID)()}`
40677
+ `snapshot-${compositionId}.tmp-${(0, import_node_crypto22.randomUUID)()}`
40391
40678
  );
40392
40679
  await import_promises42.default.mkdir(temporaryDir, { recursive: true });
40393
40680
  try {
@@ -40670,10 +40957,10 @@ var init_runtimeEvidenceCompositions = __esm({
40670
40957
  // src/scripts/runtimeEvidence.ts
40671
40958
  var runtimeEvidence_exports = {};
40672
40959
  __export(runtimeEvidence_exports, {
40673
- main: () => main44,
40960
+ main: () => main45,
40674
40961
  runtimeEvidence: () => runtimeEvidence
40675
40962
  });
40676
- var import_promises43, import_node_path42, import_args32, import_chalk47, flags29, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main44;
40963
+ var import_promises43, import_node_path42, import_args32, import_chalk47, flags29, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main45;
40677
40964
  var init_runtimeEvidence = __esm({
40678
40965
  "src/scripts/runtimeEvidence.ts"() {
40679
40966
  "use strict";
@@ -40902,17 +41189,17 @@ var init_runtimeEvidence = __esm({
40902
41189
  )
40903
41190
  );
40904
41191
  };
40905
- main44 = runtimeEvidence;
41192
+ main45 = runtimeEvidence;
40906
41193
  }
40907
41194
  });
40908
41195
 
40909
41196
  // src/scripts/runtimeEvidenceSync.ts
40910
41197
  var runtimeEvidenceSync_exports = {};
40911
41198
  __export(runtimeEvidenceSync_exports, {
40912
- main: () => main45,
41199
+ main: () => main46,
40913
41200
  runtimeEvidenceSync: () => runtimeEvidenceSync
40914
41201
  });
40915
- var import_node_path43, import_args33, import_chalk48, flags30, projectRoot13, runtimeEvidenceSync, main45;
41202
+ var import_node_path43, import_args33, import_chalk48, flags30, projectRoot13, runtimeEvidenceSync, main46;
40916
41203
  var init_runtimeEvidenceSync2 = __esm({
40917
41204
  "src/scripts/runtimeEvidenceSync.ts"() {
40918
41205
  "use strict";
@@ -40976,7 +41263,7 @@ var init_runtimeEvidenceSync2 = __esm({
40976
41263
  )
40977
41264
  );
40978
41265
  };
40979
- main45 = runtimeEvidenceSync;
41266
+ main46 = runtimeEvidenceSync;
40980
41267
  }
40981
41268
  });
40982
41269
 
@@ -41093,11 +41380,11 @@ var init_liveDiagnosis = __esm({
41093
41380
  function assert2(condition, message) {
41094
41381
  if (!condition) throw new Error(`Invalid strategy release: ${message}`);
41095
41382
  }
41096
- var DAY_MS14, realizedDrawdown, lowerBoundExitTimestamp, percentile2, buildStrategyMonitoringProfile;
41383
+ var DAY_MS15, realizedDrawdown, lowerBoundExitTimestamp, percentile2, buildStrategyMonitoringProfile;
41097
41384
  var init_monitoringProfile = __esm({
41098
41385
  "src/lib/strategyRelease/monitoringProfile.ts"() {
41099
41386
  "use strict";
41100
- DAY_MS14 = 864e5;
41387
+ DAY_MS15 = 864e5;
41101
41388
  realizedDrawdown = (trades, startIndex = 0, endIndex = trades.length) => {
41102
41389
  let equity = 0;
41103
41390
  let peak = 0;
@@ -41150,13 +41437,13 @@ var init_monitoringProfile = __esm({
41150
41437
  Number.isInteger(windowDays) && windowDays > 0,
41151
41438
  "monitoring profile days must be positive integers"
41152
41439
  );
41153
- const duration = windowDays * DAY_MS14;
41440
+ const duration = windowDays * DAY_MS15;
41154
41441
  assert2(
41155
41442
  endTime - startTime >= duration,
41156
41443
  `${windowDays}d monitoring window exceeds historical coverage`
41157
41444
  );
41158
41445
  const drawdowns = [];
41159
- for (let windowStart = startTime; windowStart + duration <= endTime; windowStart += DAY_MS14) {
41446
+ for (let windowStart = startTime; windowStart + duration <= endTime; windowStart += DAY_MS15) {
41160
41447
  const windowEnd = windowStart + duration;
41161
41448
  drawdowns.push(
41162
41449
  realizedDrawdown(
@@ -41354,11 +41641,11 @@ async function collectReleaseEvidenceReferences(references) {
41354
41641
  })
41355
41642
  );
41356
41643
  }
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;
41644
+ 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
41645
  var init_strategyRelease = __esm({
41359
41646
  "src/lib/strategyRelease.ts"() {
41360
41647
  "use strict";
41361
- import_node_crypto24 = require("crypto");
41648
+ import_node_crypto23 = require("crypto");
41362
41649
  import_promises44 = __toESM(require("fs/promises"));
41363
41650
  import_node_path44 = __toESM(require("path"));
41364
41651
  import_types9 = require("@tradejs/types");
@@ -42376,7 +42663,7 @@ var init_strategyRelease = __esm({
42376
42663
  const artifactHashes = manifest.artifactHashes != null && typeof manifest.artifactHashes === "object" && !Array.isArray(manifest.artifactHashes) ? manifest.artifactHashes : null;
42377
42664
  const parsedSpec = JSON.parse(specBytes.toString("utf8"));
42378
42665
  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,
42666
+ 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
42667
  "core result is not bound by its completed core research manifest"
42381
42668
  );
42382
42669
  for (const [relativePath, expectedSha256] of Object.entries(
@@ -42405,15 +42692,15 @@ var init_strategyRelease = __esm({
42405
42692
  // src/scripts/runtimeScorecard.ts
42406
42693
  var runtimeScorecard_exports = {};
42407
42694
  __export(runtimeScorecard_exports, {
42408
- main: () => main46,
42695
+ main: () => main47,
42409
42696
  runtimeScorecard: () => runtimeScorecard
42410
42697
  });
42411
- var import_promises45, import_node_crypto25, import_node_path45, import_args34, import_chalk49, flags31, projectRoot14, resolveOptionalPath, readJson2, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main46;
42698
+ var import_promises45, import_node_crypto24, import_node_path45, import_args34, import_chalk49, flags31, projectRoot14, resolveOptionalPath, readJson2, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main47;
42412
42699
  var init_runtimeScorecard2 = __esm({
42413
42700
  "src/scripts/runtimeScorecard.ts"() {
42414
42701
  "use strict";
42415
42702
  import_promises45 = __toESM(require("fs/promises"));
42416
- import_node_crypto25 = require("crypto");
42703
+ import_node_crypto24 = require("crypto");
42417
42704
  import_node_path45 = __toESM(require("path"));
42418
42705
  import_args34 = __toESM(require("args"));
42419
42706
  import_chalk49 = __toESM(require("chalk"));
@@ -42492,7 +42779,7 @@ var init_runtimeScorecard2 = __esm({
42492
42779
  throw new Error(`${label} must be a ${expected} artifact`);
42493
42780
  }
42494
42781
  };
42495
- sha256File2 = async (filePath) => (0, import_node_crypto25.createHash)("sha256").update(await import_promises45.default.readFile(filePath)).digest("hex");
42782
+ sha256File2 = async (filePath) => (0, import_node_crypto24.createHash)("sha256").update(await import_promises45.default.readFile(filePath)).digest("hex");
42496
42783
  loadHistoryArtifacts = async (historyDir) => {
42497
42784
  if (!historyDir) return [];
42498
42785
  const bundleDirs = await (0, runtimeEvidenceArtifacts_exports.discoverRuntimeEvidenceBundles)(historyDir);
@@ -42660,7 +42947,7 @@ var init_runtimeScorecard2 = __esm({
42660
42947
  )
42661
42948
  );
42662
42949
  };
42663
- main46 = runtimeScorecard;
42950
+ main47 = runtimeScorecard;
42664
42951
  }
42665
42952
  });
42666
42953
 
@@ -42668,10 +42955,10 @@ var init_runtimeScorecard2 = __esm({
42668
42955
  var runtimeControl_exports = {};
42669
42956
  __export(runtimeControl_exports, {
42670
42957
  RUNTIME_CONTROL_ACTIONS: () => RUNTIME_CONTROL_ACTIONS,
42671
- main: () => main47,
42958
+ main: () => main48,
42672
42959
  runtimeControl: () => runtimeControl
42673
42960
  });
42674
- var import_config9, import_runtimeControls, import_runtimeStrategies5, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot15, userName2, verify, inspect, updateControlState, runtimeControl, main47;
42961
+ var import_config9, import_runtimeControls, import_runtimeStrategies5, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot15, userName2, verify, inspect, updateControlState, runtimeControl, main48;
42675
42962
  var init_runtimeControl = __esm({
42676
42963
  "src/scripts/runtimeControl.ts"() {
42677
42964
  "use strict";
@@ -42819,17 +43106,17 @@ var init_runtimeControl = __esm({
42819
43106
  `Usage: tradejs runtime-control ${RUNTIME_CONTROL_ACTIONS.join("|")}`
42820
43107
  );
42821
43108
  };
42822
- main47 = runtimeControl;
43109
+ main48 = runtimeControl;
42823
43110
  }
42824
43111
  });
42825
43112
 
42826
43113
  // src/scripts/strategyRelease.ts
42827
43114
  var strategyRelease_exports = {};
42828
43115
  __export(strategyRelease_exports, {
42829
- main: () => main48,
43116
+ main: () => main49,
42830
43117
  runStrategyReleaseCommand: () => runStrategyReleaseCommand
42831
43118
  });
42832
- var import_promises46, import_node_fs10, import_node_readline5, import_node_path46, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main48;
43119
+ var import_promises46, import_node_fs10, import_node_readline5, import_node_path46, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main49;
42833
43120
  var init_strategyRelease2 = __esm({
42834
43121
  "src/scripts/strategyRelease.ts"() {
42835
43122
  "use strict";
@@ -42996,7 +43283,7 @@ var init_strategyRelease2 = __esm({
42996
43283
  yarn strategy:release profile --input <trades.jsonl> --variant <id> --startTime <ms> --endTime <ms> [--days 7,30,90] [--out <profile.json>]
42997
43284
  yarn strategy:release diagnose --input <diagnosis-input.json> [--out output/diagnosis.json]
42998
43285
  yarn strategy:release retention --input <inventory.json> [--apply]`);
42999
- main48 = async () => {
43286
+ main49 = async () => {
43000
43287
  const argv2 = process.argv.slice(2);
43001
43288
  const command = argv2[0];
43002
43289
  if (!command || ![
@@ -43035,10 +43322,10 @@ __export(serverHealth_exports, {
43035
43322
  buildServerHealthDiagnostics: () => buildServerHealthDiagnostics,
43036
43323
  collectServerHealthSnapshot: () => collectServerHealthSnapshot,
43037
43324
  evaluateServerHealth: () => evaluateServerHealth,
43038
- main: () => main49,
43325
+ main: () => main50,
43039
43326
  resolveServerHealthThresholds: () => resolveServerHealthThresholds
43040
43327
  });
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;
43328
+ 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, main50;
43042
43329
  var init_serverHealth = __esm({
43043
43330
  "src/scripts/serverHealth.ts"() {
43044
43331
  "use strict";
@@ -43047,7 +43334,7 @@ var init_serverHealth = __esm({
43047
43334
  import_node_os5 = __toESM(require("os"));
43048
43335
  import_node_fs11 = require("fs");
43049
43336
  import_args35 = __toESM(require("args"));
43050
- import_redis22 = require("@tradejs/infra/redis");
43337
+ import_redis23 = require("@tradejs/infra/redis");
43051
43338
  init_telegramReports();
43052
43339
  DEFAULT_STATE = {
43053
43340
  status: "healthy",
@@ -43451,13 +43738,13 @@ var init_serverHealth = __esm({
43451
43738
  "Recovery threshold for disk used percent",
43452
43739
  String(DEFAULT_THRESHOLDS.diskRecoverPct)
43453
43740
  );
43454
- main49 = async () => {
43741
+ main50 = async () => {
43455
43742
  const flags36 = import_args35.default.parse(process.argv);
43456
43743
  const thresholds = resolveServerHealthThresholds(flags36);
43457
43744
  const diskPath = String(flags36.diskPath || "/");
43458
43745
  const snapshot = collectServerHealthSnapshot(diskPath);
43459
43746
  const stateKey = getStateKey(String(flags36.user), snapshot.hostname);
43460
- const prevState = await (0, import_redis22.getData)(stateKey, DEFAULT_STATE) ?? DEFAULT_STATE;
43747
+ const prevState = await (0, import_redis23.getData)(stateKey, DEFAULT_STATE) ?? DEFAULT_STATE;
43461
43748
  const evaluation = evaluateServerHealth(snapshot, thresholds);
43462
43749
  const cooldownMs = Math.max(60, Number(flags36.cooldownSec)) * 1e3;
43463
43750
  const now2 = snapshot.timestamp;
@@ -43470,7 +43757,7 @@ var init_serverHealth = __esm({
43470
43757
  lastOkAt: prevState.lastOkAt,
43471
43758
  activeIssueCodes: evaluation.issues.map((issue) => issue.code)
43472
43759
  };
43473
- await (0, import_redis22.setData)(stateKey, nextState2, { expire: 0 });
43760
+ await (0, import_redis23.setData)(stateKey, nextState2, { expire: 0 });
43474
43761
  if (shouldSend) {
43475
43762
  const message = buildAlertMessage({
43476
43763
  evaluation,
@@ -43499,7 +43786,7 @@ var init_serverHealth = __esm({
43499
43786
  lastOkAt: now2,
43500
43787
  activeIssueCodes: []
43501
43788
  };
43502
- await (0, import_redis22.setData)(stateKey, nextState, { expire: 0 });
43789
+ await (0, import_redis23.setData)(stateKey, nextState, { expire: 0 });
43503
43790
  if (recovered) {
43504
43791
  const message = buildRecoveryMessage({ snapshot, prevState });
43505
43792
  if (flags36.printOnly) {
@@ -44843,24 +45130,24 @@ var init_reporting = __esm({
44843
45130
  var runtimeParity_exports = {};
44844
45131
  __export(runtimeParity_exports, {
44845
45132
  buildRuntimeParityMessage: () => buildRuntimeParityMessage,
44846
- main: () => main50,
45133
+ main: () => main51,
44847
45134
  runtimeParity: () => runtimeParity
44848
45135
  });
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;
45136
+ var import_config11, import_node_crypto25, import_args36, import_chalk52, import_constants20, import_time13, import_logger8, import_redis24, import_cli12, import_backtest8, import_connectors17, flags32, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main51;
44850
45137
  var init_runtimeParity2 = __esm({
44851
45138
  "src/scripts/runtimeParity.ts"() {
44852
45139
  "use strict";
44853
45140
  import_config11 = require("dotenv/config");
44854
- import_node_crypto26 = require("crypto");
45141
+ import_node_crypto25 = require("crypto");
44855
45142
  import_args36 = __toESM(require("args"));
44856
45143
  import_chalk52 = __toESM(require("chalk"));
44857
- import_constants19 = require("@tradejs/core/constants");
45144
+ import_constants20 = require("@tradejs/core/constants");
44858
45145
  import_time13 = require("@tradejs/core/time");
44859
- import_logger7 = require("@tradejs/infra/logger");
44860
- import_redis23 = require("@tradejs/infra/redis");
45146
+ import_logger8 = require("@tradejs/infra/logger");
45147
+ import_redis24 = require("@tradejs/infra/redis");
44861
45148
  import_cli12 = require("@tradejs/node/cli");
44862
45149
  import_backtest8 = require("@tradejs/node/backtest");
44863
- import_connectors16 = require("@tradejs/node/connectors");
45150
+ import_connectors17 = require("@tradejs/node/connectors");
44864
45151
  init_runtimeParity();
44865
45152
  init_cliArgs();
44866
45153
  init_runtimeRedis();
@@ -44930,22 +45217,22 @@ var init_runtimeParity2 = __esm({
44930
45217
  DETAIL_LIMIT2 = 10;
44931
45218
  DEFAULT_REPLAY_ENV = flags32.runtimeGates ? "PARITY" : "BACKTEST";
44932
45219
  resolveParityConnectorName = async (value) => {
44933
- const connectorName = await (0, import_connectors16.resolveConnectorName)(value, projectRoot16);
45220
+ const connectorName = await (0, import_connectors17.resolveConnectorName)(value, projectRoot16);
44934
45221
  if (connectorName) {
44935
45222
  return connectorName;
44936
45223
  }
44937
- import_logger7.logger.warn(
45224
+ import_logger8.logger.warn(
44938
45225
  'Unknown connector "%s". Fallback to %s.',
44939
45226
  String(value || "").trim() || String(value),
44940
- import_connectors16.DEFAULT_CONNECTOR_NAME
45227
+ import_connectors17.DEFAULT_CONNECTOR_NAME
44941
45228
  );
44942
- return import_connectors16.DEFAULT_CONNECTOR_NAME;
45229
+ return import_connectors17.DEFAULT_CONNECTOR_NAME;
44943
45230
  };
44944
45231
  createConnector = async ({
44945
45232
  userName: userName3,
44946
45233
  connectorName
44947
45234
  }) => {
44948
- const connectorFactory = await (0, import_connectors16.getConnectorCreatorByName)(
45235
+ const connectorFactory = await (0, import_connectors17.getConnectorCreatorByName)(
44949
45236
  connectorName,
44950
45237
  projectRoot16
44951
45238
  );
@@ -45017,8 +45304,8 @@ var init_runtimeParity2 = __esm({
45017
45304
  toleranceMs
45018
45305
  }) => {
45019
45306
  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), {})
45307
+ (0, import_redis24.getData)(import_redis24.redisKeys.strategyConfig(userName3, strategy), {}),
45308
+ (0, import_redis24.getData)(import_redis24.redisKeys.strategyResults(userName3, strategy), {})
45022
45309
  ]);
45023
45310
  const typedResults = strategyResults ?? {};
45024
45311
  const symbolResult = typedResults?.[symbol];
@@ -45068,7 +45355,7 @@ var init_runtimeParity2 = __esm({
45068
45355
  userName: userName3,
45069
45356
  projectRoot: projectRoot16,
45070
45357
  shouldUseDedicatedReferences: true,
45071
- warn: (message) => import_logger7.logger.warn(message)
45358
+ warn: (message) => import_logger8.logger.warn(message)
45072
45359
  });
45073
45360
  await updateMarketHistoryWithBtcReferences({
45074
45361
  marketConnector: connector,
@@ -45155,7 +45442,7 @@ var init_runtimeParity2 = __esm({
45155
45442
  const sourceCounts = countReplayTargetSources(replayTargets);
45156
45443
  const preloadStart = (0, import_time13.getBacktestPreloadStart)(
45157
45444
  window.start,
45158
- import_constants19.BACKTEST_PRELOAD_DAYS
45445
+ import_constants20.BACKTEST_PRELOAD_DAYS
45159
45446
  );
45160
45447
  const replayStartedAt = Date.now();
45161
45448
  const replaySymbolsCount = new Set(
@@ -45234,9 +45521,9 @@ var init_runtimeParity2 = __esm({
45234
45521
  start: window.start,
45235
45522
  end: window.end
45236
45523
  },
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),
45524
+ name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto25.randomUUID)().slice(0, 8)}`,
45525
+ testId: (0, import_node_crypto25.randomUUID)().slice(0, 8),
45526
+ testSuiteId: (0, import_node_crypto25.randomUUID)().slice(0, 8),
45240
45527
  strategyName: target.strategy,
45241
45528
  strategyConfig: replayConfig,
45242
45529
  connectorName,
@@ -45385,7 +45672,7 @@ var init_runtimeParity2 = __esm({
45385
45672
  (0, import_backtest8.resetTestingKlineCache)(projectRoot16);
45386
45673
  }
45387
45674
  };
45388
- main50 = runtimeParity;
45675
+ main51 = runtimeParity;
45389
45676
  }
45390
45677
  });
45391
45678
 
@@ -45399,12 +45686,12 @@ var init_runtimeStrategies = __esm({
45399
45686
  });
45400
45687
 
45401
45688
  // src/lib/signals/skipStats.ts
45402
- var import_chalk53, import_logger8, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
45689
+ var import_chalk53, import_logger9, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
45403
45690
  var init_skipStats = __esm({
45404
45691
  "src/lib/signals/skipStats.ts"() {
45405
45692
  "use strict";
45406
45693
  import_chalk53 = __toESM(require("chalk"));
45407
- import_logger8 = require("@tradejs/infra/logger");
45694
+ import_logger9 = require("@tradejs/infra/logger");
45408
45695
  init_runtimeSignalsStorage();
45409
45696
  createStrategySkipStats = (runtimeStrategies) => new Map(
45410
45697
  runtimeStrategies.map(({ strategyName }) => [
@@ -45429,24 +45716,24 @@ var init_skipStats = __esm({
45429
45716
  );
45430
45717
  };
45431
45718
  logStrategySkipStats = (runtimeStrategies, strategyStats) => {
45432
- import_logger8.logger.info(import_chalk53.default.yellow("skip stats:"));
45719
+ import_logger9.logger.info(import_chalk53.default.yellow("skip stats:"));
45433
45720
  for (const { strategyName } of runtimeStrategies) {
45434
45721
  const stats = strategyStats.get(strategyName);
45435
45722
  if (!stats) {
45436
45723
  continue;
45437
45724
  }
45438
- import_logger8.logger.info(
45725
+ import_logger9.logger.info(
45439
45726
  `${strategyName}: evaluated=${stats.evaluated}, signals=${stats.signals}`
45440
45727
  );
45441
45728
  const sortedReasons = [...stats.reasons.entries()].sort(
45442
45729
  (left, right) => right[1] - left[1] || left[0].localeCompare(right[0])
45443
45730
  );
45444
45731
  if (!sortedReasons.length) {
45445
- import_logger8.logger.info(" none");
45732
+ import_logger9.logger.info(" none");
45446
45733
  continue;
45447
45734
  }
45448
45735
  for (const [reason, count] of sortedReasons) {
45449
- import_logger8.logger.info(` ${reason}: ${count}`);
45736
+ import_logger9.logger.info(` ${reason}: ${count}`);
45450
45737
  }
45451
45738
  }
45452
45739
  };
@@ -45454,11 +45741,11 @@ var init_skipStats = __esm({
45454
45741
  });
45455
45742
 
45456
45743
  // src/lib/signals/evaluations.ts
45457
- var import_redis24, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, runtimeLineageScopeCacheLoaded, buildRuntimeSignalEvaluationId, buildLineageField, flushRuntimeSignalEvaluations, createRuntimeSignalEvaluationBuffer;
45744
+ var import_redis25, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, runtimeLineageScopeCacheLoaded, buildRuntimeSignalEvaluationId, buildLineageField, flushRuntimeSignalEvaluations, createRuntimeSignalEvaluationBuffer;
45458
45745
  var init_evaluations = __esm({
45459
45746
  "src/lib/signals/evaluations.ts"() {
45460
45747
  "use strict";
45461
- import_redis24 = require("@tradejs/infra/redis");
45748
+ import_redis25 = require("@tradejs/infra/redis");
45462
45749
  init_runtimeSignalsStorage();
45463
45750
  init_runtimeLineage();
45464
45751
  runtimeLineageScopeCache = /* @__PURE__ */ new Map();
@@ -45509,7 +45796,7 @@ var init_evaluations = __esm({
45509
45796
  runtimeLineageScopeCacheDayKey = dayKey;
45510
45797
  runtimeLineageScopeCacheLoaded = false;
45511
45798
  }
45512
- const lineageBucket = import_redis24.redisKeys.runtimeLineageScopeBucket(
45799
+ const lineageBucket = import_redis25.redisKeys.runtimeLineageScopeBucket(
45513
45800
  dayEvaluations[0].userName,
45514
45801
  dayKey
45515
45802
  );
@@ -45517,7 +45804,7 @@ var init_evaluations = __esm({
45517
45804
  (evaluation) => evaluation.runtimeLineage != null
45518
45805
  );
45519
45806
  if (lineageEvaluations.length > 0 && !runtimeLineageScopeCacheLoaded) {
45520
- const storedScopes = await (0, import_redis24.getHashJsonValues)(lineageBucket);
45807
+ const storedScopes = await (0, import_redis25.getHashJsonValues)(lineageBucket);
45521
45808
  for (const scope of storedScopes) {
45522
45809
  const lineageField = buildLineageField(scope);
45523
45810
  runtimeLineageScopeCache.set(`${lineageBucket}:${lineageField}`, scope);
@@ -45562,7 +45849,7 @@ var init_evaluations = __esm({
45562
45849
  lineageWrites.set(lineageField, scope);
45563
45850
  }
45564
45851
  if (lineageWrites.size > 0) {
45565
- await (0, import_redis24.setHashJsonFields)(
45852
+ await (0, import_redis25.setHashJsonFields)(
45566
45853
  lineageBucket,
45567
45854
  [...lineageWrites].map(([field, data]) => ({ field, data })),
45568
45855
  {
@@ -45574,7 +45861,7 @@ var init_evaluations = __esm({
45574
45861
  const statsIncrements = /* @__PURE__ */ new Map();
45575
45862
  for (const evaluation of dayEvaluations) {
45576
45863
  if (shouldStoreDetailedRuntimeSignalEvaluation(evaluation)) {
45577
- const bucket = import_redis24.redisKeys.runtimeSignalEvaluationBucket(
45864
+ const bucket = import_redis25.redisKeys.runtimeSignalEvaluationBucket(
45578
45865
  evaluation.userName,
45579
45866
  dayKey,
45580
45867
  evaluation.strategy
@@ -45586,7 +45873,7 @@ var init_evaluations = __esm({
45586
45873
  });
45587
45874
  detailedWrites.set(bucket, entries);
45588
45875
  }
45589
- const statsBucket = import_redis24.redisKeys.runtimeSignalEvaluationStatsBucket(
45876
+ const statsBucket = import_redis25.redisKeys.runtimeSignalEvaluationStatsBucket(
45590
45877
  evaluation.userName,
45591
45878
  dayKey,
45592
45879
  evaluation.strategy,
@@ -45602,12 +45889,12 @@ var init_evaluations = __esm({
45602
45889
  }
45603
45890
  await Promise.all([
45604
45891
  ...[...detailedWrites].map(
45605
- ([bucket, entries]) => (0, import_redis24.setHashJsonFields)(bucket, entries, {
45892
+ ([bucket, entries]) => (0, import_redis25.setHashJsonFields)(bucket, entries, {
45606
45893
  expire: runtimeSignalRetentionTtl
45607
45894
  })
45608
45895
  ),
45609
45896
  ...[...statsIncrements].map(
45610
- ([bucket, increments]) => (0, import_redis24.incrHashFields)(bucket, increments, {
45897
+ ([bucket, increments]) => (0, import_redis25.incrHashFields)(bucket, increments, {
45611
45898
  expire: runtimeSignalRetentionTtl
45612
45899
  })
45613
45900
  )
@@ -45623,7 +45910,7 @@ var init_evaluations = __esm({
45623
45910
  const runtimeSignalRetentionTtl = getRuntimeSignalRetentionTtlSeconds();
45624
45911
  const signalRefsByBucket = /* @__PURE__ */ new Map();
45625
45912
  for (const { userName: userName3, signal } of pendingSignals) {
45626
- const bucket = import_redis24.redisKeys.runtimeSignalBucket(
45913
+ const bucket = import_redis25.redisKeys.runtimeSignalBucket(
45627
45914
  userName3,
45628
45915
  (0, import_time5.getRuntimeStorageDayKey)(signal.timestamp),
45629
45916
  signal.strategy
@@ -45637,14 +45924,14 @@ var init_evaluations = __esm({
45637
45924
  }
45638
45925
  await Promise.all([
45639
45926
  ...pendingSignals.map(
45640
- ({ signal }) => (0, import_redis24.setData)(
45641
- import_redis24.redisKeys.storeSignal(signal.symbol, signal.signalId),
45927
+ ({ signal }) => (0, import_redis25.setData)(
45928
+ import_redis25.redisKeys.storeSignal(signal.symbol, signal.signalId),
45642
45929
  toStoredRuntimeSignal(signal),
45643
45930
  { expire: runtimeSignalRetentionTtl }
45644
45931
  )
45645
45932
  ),
45646
45933
  ...[...signalRefsByBucket].map(
45647
- ([bucket, entries]) => (0, import_redis24.setHashJsonFields)(bucket, entries, {
45934
+ ([bucket, entries]) => (0, import_redis25.setHashJsonFields)(bucket, entries, {
45648
45935
  expire: runtimeSignalRetentionTtl
45649
45936
  })
45650
45937
  )
@@ -45897,13 +46184,13 @@ var init_daemon = __esm({
45897
46184
  });
45898
46185
 
45899
46186
  // src/lib/signals/klineFeed.ts
45900
- var import_connectors17, import_logger9, import_candles5, FLUSH_DELAY_MS, normalizeSymbols2, createSignalsKlineFeed;
46187
+ var import_connectors18, import_logger10, import_candles6, FLUSH_DELAY_MS, normalizeSymbols2, createSignalsKlineFeed;
45901
46188
  var init_klineFeed = __esm({
45902
46189
  "src/lib/signals/klineFeed.ts"() {
45903
46190
  "use strict";
45904
- import_connectors17 = require("@tradejs/connectors");
45905
- import_logger9 = require("@tradejs/infra/logger");
45906
- import_candles5 = require("@tradejs/infra/timescale/candles");
46191
+ import_connectors18 = require("@tradejs/connectors");
46192
+ import_logger10 = require("@tradejs/infra/logger");
46193
+ import_candles6 = require("@tradejs/infra/timescale/candles");
45907
46194
  init_klineEvents();
45908
46195
  FLUSH_DELAY_MS = 100;
45909
46196
  normalizeSymbols2 = (symbols) => [...new Set(symbols.map((symbol) => symbol.trim().toUpperCase()))].filter(
@@ -45916,13 +46203,13 @@ var init_klineFeed = __esm({
45916
46203
  publish = publishMarketKlineEvent,
45917
46204
  persist = async (rows) => {
45918
46205
  const intervalMinutes = Number(interval4);
45919
- await (0, import_candles5.upsertCandles)(
46206
+ await (0, import_candles6.upsertCandles)(
45920
46207
  rows.flatMap(
45921
- ({ symbol, candle }) => (0, import_candles5.toRows)("bybit", symbol, intervalMinutes, [candle])
46208
+ ({ symbol, candle }) => (0, import_candles6.toRows)("bybit", symbol, intervalMinutes, [candle])
45922
46209
  )
45923
46210
  );
45924
46211
  },
45925
- streamFactory = import_connectors17.createBybitKlineStream
46212
+ streamFactory = import_connectors18.createBybitKlineStream
45926
46213
  }) => {
45927
46214
  const pending = /* @__PURE__ */ new Map();
45928
46215
  const lastClosedTimestamp = /* @__PURE__ */ new Map();
@@ -45956,7 +46243,7 @@ var init_klineFeed = __esm({
45956
46243
  if (flushTimer || closed) return;
45957
46244
  flushTimer = setTimeout(() => {
45958
46245
  void flush().catch(
45959
- (error) => import_logger9.logger.error("websocket candle batch flush failed: %s", String(error))
46246
+ (error) => import_logger10.logger.error("websocket candle batch flush failed: %s", String(error))
45960
46247
  );
45961
46248
  }, FLUSH_DELAY_MS);
45962
46249
  };
@@ -45973,7 +46260,7 @@ var init_klineFeed = __esm({
45973
46260
  confirm: event.confirm,
45974
46261
  receivedAt: event.receivedAt
45975
46262
  }).catch(
45976
- (error) => import_logger9.logger.warn("websocket candle publish failed: %s", String(error))
46263
+ (error) => import_logger10.logger.warn("websocket candle publish failed: %s", String(error))
45977
46264
  );
45978
46265
  if (!event.confirm) return;
45979
46266
  pending.set(`${event.symbol}:${event.candle.timestamp}`, {
@@ -46028,12 +46315,12 @@ var init_klineFeed = __esm({
46028
46315
  });
46029
46316
 
46030
46317
  // src/lib/signals/tickerEvaluator.ts
46031
- var import_strategies13, import_logger10, createSignalsTickerEvaluator;
46318
+ var import_strategies14, import_logger11, createSignalsTickerEvaluator;
46032
46319
  var init_tickerEvaluator = __esm({
46033
46320
  "src/lib/signals/tickerEvaluator.ts"() {
46034
46321
  "use strict";
46035
- import_strategies13 = require("@tradejs/node/strategies");
46036
- import_logger10 = require("@tradejs/infra/logger");
46322
+ import_strategies14 = require("@tradejs/node/strategies");
46323
+ import_logger11 = require("@tradejs/infra/logger");
46037
46324
  init_windows();
46038
46325
  init_runtimeLineage();
46039
46326
  init_runtimeModeConfig();
@@ -46193,7 +46480,7 @@ var init_tickerEvaluator = __esm({
46193
46480
  continue;
46194
46481
  }
46195
46482
  if (evaluation.action.startsWith("rebuilt_")) {
46196
- import_logger10.logger.info(
46483
+ import_logger11.logger.info(
46197
46484
  "Rebuilt signals strategy state (%s): %s %s",
46198
46485
  evaluation.action.slice("rebuilt_".length),
46199
46486
  strategyName,
@@ -46249,7 +46536,7 @@ var init_tickerEvaluator = __esm({
46249
46536
  if (signalRuntimeIdentity && !signal.signalId.endsWith(`:${signalRuntimeIdentity}`)) {
46250
46537
  signal.signalId = `${signal.signalId}:${signalRuntimeIdentity}`;
46251
46538
  }
46252
- await (0, import_strategies13.enrichSignalWithBinanceMarketContext)({ signal, env: "CRON" });
46539
+ await (0, import_strategies14.enrichSignalWithBinanceMarketContext)({ signal, env: "CRON" });
46253
46540
  if (signal.orderStatus === "skipped" && typeof signal.orderSkipReason === "string" && signal.orderSkipReason.trim()) {
46254
46541
  recordStrategyReason(
46255
46542
  strategyStats,
@@ -46296,7 +46583,7 @@ var init_tickerEvaluator = __esm({
46296
46583
  ...signal.riskDecision ? { riskDecision: signal.riskDecision } : {},
46297
46584
  ...signal.ml ? { ml: signal.ml } : {}
46298
46585
  });
46299
- import_logger10.logger.info("Signal found %s by strategy %s", symbol, strategyName);
46586
+ import_logger11.logger.info("Signal found %s by strategy %s", symbol, strategyName);
46300
46587
  }
46301
46588
  return strategySignals;
46302
46589
  };
@@ -46445,19 +46732,19 @@ var init_configuredScopes = __esm({
46445
46732
  });
46446
46733
 
46447
46734
  // 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;
46735
+ var import_progress12, import_chalk54, import_connectors19, import_cli13, import_async5, import_strategies15, import_constants21, import_time14, import_logger12, import_runtimeDeploymentEvents, import_runtimeHeartbeats, import_runtimeStrategies7, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
46449
46736
  var init_runner = __esm({
46450
46737
  "src/lib/signals/runner.ts"() {
46451
46738
  "use strict";
46452
46739
  import_progress12 = __toESM(require("progress"));
46453
46740
  import_chalk54 = __toESM(require("chalk"));
46454
- import_connectors18 = require("@tradejs/node/connectors");
46741
+ import_connectors19 = require("@tradejs/node/connectors");
46455
46742
  import_cli13 = require("@tradejs/node/cli");
46456
46743
  import_async5 = require("@tradejs/core/async");
46457
- import_strategies14 = require("@tradejs/core/strategies");
46458
- import_constants20 = require("@tradejs/core/constants");
46744
+ import_strategies15 = require("@tradejs/core/strategies");
46745
+ import_constants21 = require("@tradejs/core/constants");
46459
46746
  import_time14 = require("@tradejs/core/time");
46460
- import_logger11 = require("@tradejs/infra/logger");
46747
+ import_logger12 = require("@tradejs/infra/logger");
46461
46748
  import_runtimeDeploymentEvents = require("@tradejs/infra/runtimeDeploymentEvents");
46462
46749
  import_runtimeHeartbeats = require("@tradejs/infra/runtimeHeartbeats");
46463
46750
  import_runtimeStrategies7 = require("@tradejs/node/runtimeStrategies");
@@ -46504,7 +46791,7 @@ var init_runner = __esm({
46504
46791
  deploymentId: config2.deploymentId,
46505
46792
  expectedCompositionId: compositionId
46506
46793
  }),
46507
- onError: (compositionId, error) => import_logger11.logger.warn(
46794
+ onError: (compositionId, error) => import_logger12.logger.warn(
46508
46795
  "runtime evidence snapshot unavailable; trading continues and the next cycle will retry (composition=%s): %s",
46509
46796
  compositionId,
46510
46797
  error instanceof Error ? error.message : String(error)
@@ -46513,7 +46800,7 @@ var init_runner = __esm({
46513
46800
  const resolveSignalsDaemonMaxLiveBars = (runtimeInterval = interval4) => {
46514
46801
  const intervalMinutes = Number(runtimeInterval);
46515
46802
  const preloadBars = Math.ceil(
46516
- import_constants20.SIGNALS_CLI_PRELOAD_DAYS * 24 * 60 / intervalMinutes
46803
+ import_constants21.SIGNALS_CLI_PRELOAD_DAYS * 24 * 60 / intervalMinutes
46517
46804
  );
46518
46805
  return resolvePositiveInteger2(
46519
46806
  process.env.SIGNALS_DAEMON_MAX_LIVE_BARS,
@@ -46527,12 +46814,12 @@ var init_runner = __esm({
46527
46814
  const createDefaultSignalsLifecycle = (runtimeInterval = interval4) => createSignalsStrategyLifecycle({
46528
46815
  intervalMs: Number(runtimeInterval) * 6e4,
46529
46816
  maxLiveBars: resolveSignalsDaemonMaxLiveBars(runtimeInterval),
46530
- releaseState: import_strategies14.releaseStrategyReplayCache
46817
+ releaseState: import_strategies15.releaseStrategyReplayCache
46531
46818
  });
46532
46819
  const timeOperation3 = (label, operation) => timeOperation(
46533
46820
  label,
46534
46821
  operation,
46535
- (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
46822
+ (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46536
46823
  );
46537
46824
  const formatSlowSignalsWarning = (params) => [
46538
46825
  "<b>Slow yarn signals run</b>",
@@ -46542,7 +46829,7 @@ var init_runner = __esm({
46542
46829
  `Found signals: <b>${params.found}</b>`
46543
46830
  ].join("\n");
46544
46831
  const resolveSignalsConnectorName = async (value) => {
46545
- const connectorName = await (0, import_connectors18.resolveConnectorName)(value, projectRoot18);
46832
+ const connectorName = await (0, import_connectors19.resolveConnectorName)(value, projectRoot18);
46546
46833
  if (!connectorName) {
46547
46834
  throw new Error(
46548
46835
  `Unknown runtime connector: ${String(value || "").trim() || String(value)}`
@@ -46570,7 +46857,7 @@ var init_runner = __esm({
46570
46857
  );
46571
46858
  const universe = scope.universe ?? config2.universe;
46572
46859
  const requestedAccountId = deployment?.accountId ?? scope.accountId ?? config2.accountId;
46573
- const connectorFactory = await (0, import_connectors18.getConnectorCreatorByName)(
46860
+ const connectorFactory = await (0, import_connectors19.getConnectorCreatorByName)(
46574
46861
  connectorName,
46575
46862
  projectRoot18
46576
46863
  );
@@ -46588,8 +46875,8 @@ var init_runner = __esm({
46588
46875
  marketConnector,
46589
46876
  userName: config2.userName,
46590
46877
  projectRoot: projectRoot18,
46591
- shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors18.DEFAULT_CONNECTOR_NAME.toLowerCase(),
46592
- warn: (message) => import_logger11.logger.warn(message)
46878
+ shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors19.DEFAULT_CONNECTOR_NAME.toLowerCase(),
46879
+ warn: (message) => import_logger12.logger.warn(message)
46593
46880
  });
46594
46881
  return {
46595
46882
  connectorName,
@@ -46649,7 +46936,7 @@ var init_runner = __esm({
46649
46936
  }) : [];
46650
46937
  const selectedTickers = selection?.tickers ? [.../* @__PURE__ */ new Set([...selection.tickers, ...selectedActiveSymbols])] : void 0;
46651
46938
  if (selectedActiveSymbols.length) {
46652
- import_logger11.logger.info(
46939
+ import_logger12.logger.info(
46653
46940
  import_chalk54.default.gray(
46654
46941
  `runtime scope retained active symbols: ${selectedActiveSymbols.join(", ")}`
46655
46942
  )
@@ -46687,7 +46974,7 @@ var init_runner = __esm({
46687
46974
  const projectConfig = await (0, import_cli13.loadTradejsConfig)(projectRoot18);
46688
46975
  projectHooks = projectConfig.hooks;
46689
46976
  const currentTimestamp = (0, import_time14.getTimestamp)();
46690
- const preloadStart = (0, import_time14.getTimestamp)(import_constants20.SIGNALS_CLI_PRELOAD_DAYS);
46977
+ const preloadStart = (0, import_time14.getTimestamp)(import_constants21.SIGNALS_CLI_PRELOAD_DAYS);
46691
46978
  if (!config2.cacheOnly && session.klineFeed) {
46692
46979
  const expectedSymbols = universe === "crypto" ? [.../* @__PURE__ */ new Set([...tickers, "BTCUSDT", "ETHUSDT"])] : tickers;
46693
46980
  session.klineFeed.setSubscriptions(expectedSymbols);
@@ -46701,7 +46988,7 @@ var init_runner = __esm({
46701
46988
  })
46702
46989
  );
46703
46990
  await session.klineFeed.flush();
46704
- import_logger11.logger.info(
46991
+ import_logger12.logger.info(
46705
46992
  import_chalk54.default.gray(
46706
46993
  `websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
46707
46994
  )
@@ -46711,17 +46998,17 @@ var init_runner = __esm({
46711
46998
  connectorName,
46712
46999
  interval: interval5,
46713
47000
  symbols: missingSymbols,
46714
- preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
47001
+ preloadDays: import_constants21.SIGNALS_CLI_PRELOAD_DAYS,
46715
47002
  universe,
46716
- log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
47003
+ log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46717
47004
  });
46718
47005
  await updateBtcReferenceHistory({
46719
47006
  marketConnector,
46720
47007
  btcReferences,
46721
47008
  interval: interval5,
46722
- preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
47009
+ preloadDays: import_constants21.SIGNALS_CLI_PRELOAD_DAYS,
46723
47010
  universe,
46724
- log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
47011
+ log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46725
47012
  });
46726
47013
  } else if (!config2.cacheOnly) {
46727
47014
  await updateMarketHistoryWithBtcReferences({
@@ -46730,9 +47017,9 @@ var init_runner = __esm({
46730
47017
  btcReferences,
46731
47018
  interval: interval5,
46732
47019
  symbols: tickers,
46733
- preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
47020
+ preloadDays: import_constants21.SIGNALS_CLI_PRELOAD_DAYS,
46734
47021
  universe,
46735
- log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
47022
+ log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46736
47023
  });
46737
47024
  }
46738
47025
  await prepareMarketContextForRun({
@@ -46746,7 +47033,7 @@ var init_runner = __esm({
46746
47033
  endMs: currentTimestamp,
46747
47034
  preloadStartMs: preloadStart,
46748
47035
  cacheOnly: config2.cacheOnly,
46749
- log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
47036
+ log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
46750
47037
  });
46751
47038
  if (config2.updateOnly) {
46752
47039
  return;
@@ -46816,7 +47103,7 @@ var init_runner = __esm({
46816
47103
  ) : configuredRuntimeStrategies;
46817
47104
  if (!runtimeStrategies.length) {
46818
47105
  lifecycle.clear();
46819
- import_logger11.logger.warn(
47106
+ import_logger12.logger.warn(
46820
47107
  "No strategy releases are bound to deployment %s",
46821
47108
  deployment?.id
46822
47109
  );
@@ -46849,7 +47136,7 @@ var init_runner = __esm({
46849
47136
  )
46850
47137
  )
46851
47138
  );
46852
- import_logger11.logger.info(
47139
+ import_logger12.logger.info(
46853
47140
  import_chalk54.default.yellow(
46854
47141
  `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
46855
47142
  )
@@ -46872,7 +47159,7 @@ var init_runner = __esm({
46872
47159
  afterSignalsHookContext
46873
47160
  );
46874
47161
  if (beforeSignalsResult?.abort === true) {
46875
- import_logger11.logger.info(
47162
+ import_logger12.logger.info(
46876
47163
  "signals aborted before ticker evaluation: %s",
46877
47164
  beforeSignalsResult.reason ?? "PROJECT_BEFORE_SIGNALS_ABORTED"
46878
47165
  );
@@ -46886,9 +47173,9 @@ var init_runner = __esm({
46886
47173
  width: 30
46887
47174
  }
46888
47175
  );
46889
- import_logger11.logger.info(import_chalk54.default.yellow(`tickers: ${tickers.length}`));
47176
+ import_logger12.logger.info(import_chalk54.default.yellow(`tickers: ${tickers.length}`));
46890
47177
  const signalsParallel = resolvePositiveInteger2(config2.parallel, 4);
46891
- import_logger11.logger.info(import_chalk54.default.yellow(`signal workers: ${signalsParallel}`));
47178
+ import_logger12.logger.info(import_chalk54.default.yellow(`signal workers: ${signalsParallel}`));
46892
47179
  const evaluateTicker = createSignalsTickerEvaluator({
46893
47180
  userName: config2.userName,
46894
47181
  makeOrders: config2.makeOrders,
@@ -46946,7 +47233,7 @@ var init_runner = __esm({
46946
47233
  new Map(
46947
47234
  runtimeStrategies.map(({ strategyName, strategyConfig }) => [
46948
47235
  strategyName,
46949
- (0, import_strategies14.mapAiRuntimeFromConfig)({
47236
+ (0, import_strategies15.mapAiRuntimeFromConfig)({
46950
47237
  AI_ENABLED: strategyConfig.AI_ENABLED,
46951
47238
  AI_MODE: strategyConfig.AI_MODE,
46952
47239
  MIN_AI_QUALITY: strategyConfig.MIN_AI_QUALITY
@@ -46959,7 +47246,7 @@ var init_runner = __esm({
46959
47246
  config2.userName
46960
47247
  );
46961
47248
  }
46962
- import_logger11.logger.info(
47249
+ import_logger12.logger.info(
46963
47250
  JSON.stringify(
46964
47251
  signals3.map((s) => s.symbol),
46965
47252
  null,
@@ -46972,7 +47259,7 @@ var init_runner = __esm({
46972
47259
  } catch (error) {
46973
47260
  status = "failed";
46974
47261
  failureMessage = error?.message || String(error);
46975
- import_logger11.logger.error(
47262
+ import_logger12.logger.error(
46976
47263
  "signals failed: %s",
46977
47264
  error?.message || String(error)
46978
47265
  );
@@ -46982,7 +47269,7 @@ var init_runner = __esm({
46982
47269
  await runtimeSignalEvaluations.flush();
46983
47270
  } catch (error) {
46984
47271
  telemetryPersistence = "failed";
46985
- import_logger11.logger.error(
47272
+ import_logger12.logger.error(
46986
47273
  "runtime signal evaluation flush failed: %s",
46987
47274
  error?.message || String(error)
46988
47275
  );
@@ -47013,7 +47300,7 @@ var init_runner = __esm({
47013
47300
  durationMs
47014
47301
  });
47015
47302
  } catch (error) {
47016
- import_logger11.logger.error(
47303
+ import_logger12.logger.error(
47017
47304
  "afterSignals hook failed: %s",
47018
47305
  error?.message || String(error)
47019
47306
  );
@@ -47030,20 +47317,20 @@ var init_runner = __esm({
47030
47317
  { userName: config2.userName }
47031
47318
  );
47032
47319
  } catch (error) {
47033
- import_logger11.logger.error(
47320
+ import_logger12.logger.error(
47034
47321
  "slow signals warning failed: %s",
47035
47322
  error?.message || String(error)
47036
47323
  );
47037
47324
  }
47038
47325
  }
47039
- import_logger11.logger.info(
47326
+ import_logger12.logger.info(
47040
47327
  import_chalk54.default.yellow(
47041
47328
  `signals ${status} in ${formatDuration3(durationMs)} (found=${signals3.length})`
47042
47329
  )
47043
47330
  );
47044
- import_logger11.logger.info("");
47045
- import_logger11.logger.info("");
47046
- import_logger11.logger.info("");
47331
+ import_logger12.logger.info("");
47332
+ import_logger12.logger.info("");
47333
+ import_logger12.logger.info("");
47047
47334
  }
47048
47335
  };
47049
47336
  const loadConfiguredSignalsScopes = async (deployment) => {
@@ -47118,14 +47405,14 @@ var init_runner = __esm({
47118
47405
  const sessions = /* @__PURE__ */ new Map();
47119
47406
  const lastBoundaryByScope = /* @__PURE__ */ new Map();
47120
47407
  const stop = (signalName) => {
47121
- import_logger11.logger.info("signals daemon stopping by %s", signalName);
47408
+ import_logger12.logger.info("signals daemon stopping by %s", signalName);
47122
47409
  abortController.abort();
47123
47410
  };
47124
47411
  const stopOnSigint = () => stop("SIGINT");
47125
47412
  const stopOnSigterm = () => stop("SIGTERM");
47126
47413
  process.once("SIGINT", stopOnSigint);
47127
47414
  process.once("SIGTERM", stopOnSigterm);
47128
- import_logger11.logger.info("signals daemon started (deployment-driven scopes)");
47415
+ import_logger12.logger.info("signals daemon started (deployment-driven scopes)");
47129
47416
  try {
47130
47417
  await runSignalsDaemon({
47131
47418
  intervalMs: 6e4,
@@ -47151,7 +47438,7 @@ var init_runner = __esm({
47151
47438
  strategies
47152
47439
  });
47153
47440
  } catch (error) {
47154
- import_logger11.logger.warn(
47441
+ import_logger12.logger.warn(
47155
47442
  "runtime deployment composition event unavailable; trading continues and the next cycle will retry (composition=%s): %s",
47156
47443
  currentDeployment.deploymentCompositionId,
47157
47444
  error instanceof Error ? error.message : String(error)
@@ -47187,7 +47474,7 @@ var init_runner = __esm({
47187
47474
  interval: session.interval,
47188
47475
  universe: session.universe
47189
47476
  });
47190
- import_logger11.logger.info(
47477
+ import_logger12.logger.info(
47191
47478
  "Bybit websocket candle feed enabled (account=%s, universe=%s, interval=%s)",
47192
47479
  session.accountId ?? "default",
47193
47480
  session.universe,
@@ -47209,7 +47496,7 @@ var init_runner = __esm({
47209
47496
  (sum3, session) => sum3 + session.lifecycle.size(),
47210
47497
  0
47211
47498
  );
47212
- import_logger11.logger.info(
47499
+ import_logger12.logger.info(
47213
47500
  "signals daemon resources: rss=%sMB heapUsed=%sMB heapTotal=%sMB stateKeys=%s scopes=%s",
47214
47501
  (memory.rss / 1024 / 1024).toFixed(1),
47215
47502
  (memory.heapUsed / 1024 / 1024).toFixed(1),
@@ -47219,7 +47506,7 @@ var init_runner = __esm({
47219
47506
  );
47220
47507
  },
47221
47508
  onCycleError: (error) => {
47222
- import_logger11.logger.error(
47509
+ import_logger12.logger.error(
47223
47510
  "signals daemon cycle failed: %s",
47224
47511
  error?.message || String(error)
47225
47512
  );
@@ -47258,12 +47545,12 @@ var init_runner = __esm({
47258
47545
  var signals_exports = {};
47259
47546
  __export(signals_exports, {
47260
47547
  createSignalsSession: () => createSignalsSession,
47261
- main: () => main51,
47548
+ main: () => main52,
47262
47549
  signals: () => signals,
47263
47550
  signalsConfiguredScopesOnce: () => signalsConfiguredScopesOnce,
47264
47551
  signalsDaemon: () => signalsDaemon
47265
47552
  });
47266
- var import_config12, import_args37, flags33, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon, main51;
47553
+ var import_config12, import_args37, flags33, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon, main52;
47267
47554
  var init_signals = __esm({
47268
47555
  "src/scripts/signals.ts"() {
47269
47556
  "use strict";
@@ -47335,39 +47622,39 @@ var init_signals = __esm({
47335
47622
  signals = runner.runCycle;
47336
47623
  signalsConfiguredScopesOnce = runner.runConfiguredScopesOnce;
47337
47624
  signalsDaemon = runner.runDaemon;
47338
- main51 = () => config.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
47625
+ main52 = () => config.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
47339
47626
  }
47340
47627
  });
47341
47628
 
47342
47629
  // src/scripts/signalsDaemon.ts
47343
47630
  var signalsDaemon_exports = {};
47344
47631
  __export(signalsDaemon_exports, {
47345
- main: () => main52
47632
+ main: () => main53
47346
47633
  });
47347
- var main52;
47634
+ var main53;
47348
47635
  var init_signalsDaemon = __esm({
47349
47636
  "src/scripts/signalsDaemon.ts"() {
47350
47637
  "use strict";
47351
47638
  init_signals();
47352
- main52 = signalsDaemon;
47639
+ main53 = signalsDaemon;
47353
47640
  }
47354
47641
  });
47355
47642
 
47356
47643
  // src/scripts/signalsSummary.ts
47357
47644
  var signalsSummary_exports = {};
47358
47645
  __export(signalsSummary_exports, {
47359
- main: () => main53,
47646
+ main: () => main54,
47360
47647
  signalsSummary: () => signalsSummary
47361
47648
  });
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;
47649
+ var import_config13, import_userSettings8, import_args38, import_logger13, import_connectors20, 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, main54;
47363
47650
  var init_signalsSummary = __esm({
47364
47651
  "src/scripts/signalsSummary.ts"() {
47365
47652
  "use strict";
47366
47653
  import_config13 = require("dotenv/config");
47367
47654
  import_userSettings8 = require("@tradejs/infra/userSettings");
47368
47655
  import_args38 = __toESM(require("args"));
47369
- import_logger12 = require("@tradejs/infra/logger");
47370
- import_connectors19 = require("@tradejs/node/connectors");
47656
+ import_logger13 = require("@tradejs/infra/logger");
47657
+ import_connectors20 = require("@tradejs/node/connectors");
47371
47658
  init_runtimeRedis();
47372
47659
  init_runtimeTradeSync();
47373
47660
  init_telegramReports();
@@ -47478,16 +47765,16 @@ var init_signalsSummary = __esm({
47478
47765
  return lines.join("\n");
47479
47766
  };
47480
47767
  resolveSummaryConnectorName = async (value) => {
47481
- const connectorName = await (0, import_connectors19.resolveConnectorName)(value, projectRoot17);
47768
+ const connectorName = await (0, import_connectors20.resolveConnectorName)(value, projectRoot17);
47482
47769
  if (connectorName) {
47483
47770
  return connectorName;
47484
47771
  }
47485
- import_logger12.logger.warn(
47772
+ import_logger13.logger.warn(
47486
47773
  'Unknown connector "%s". Fallback to %s.',
47487
47774
  String(value || "").trim() || String(value),
47488
- import_connectors19.DEFAULT_CONNECTOR_NAME
47775
+ import_connectors20.DEFAULT_CONNECTOR_NAME
47489
47776
  );
47490
- return import_connectors19.DEFAULT_CONNECTOR_NAME;
47777
+ return import_connectors20.DEFAULT_CONNECTOR_NAME;
47491
47778
  };
47492
47779
  groupRuntimeTradesByConnectorScope = ({
47493
47780
  trades,
@@ -47541,7 +47828,7 @@ var init_signalsSummary = __esm({
47541
47828
  const connectorName = await resolveSummaryConnectorName(
47542
47829
  scope.connectorName
47543
47830
  );
47544
- const connectorFactory = await (0, import_connectors19.getConnectorCreatorByName)(
47831
+ const connectorFactory = await (0, import_connectors20.getConnectorCreatorByName)(
47545
47832
  connectorName,
47546
47833
  projectRoot17
47547
47834
  );
@@ -47564,7 +47851,7 @@ var init_signalsSummary = __esm({
47564
47851
  endTime,
47565
47852
  openPositionCallbacks: {
47566
47853
  onError: (error) => {
47567
- import_logger12.logger.warn(
47854
+ import_logger13.logger.warn(
47568
47855
  "signals summary: getOpenPositionPnl failed for scope account=%s deployment=%s: %s",
47569
47856
  scope.accountId ?? "default",
47570
47857
  scope.deploymentId ?? "default",
@@ -47574,7 +47861,7 @@ var init_signalsSummary = __esm({
47574
47861
  },
47575
47862
  closedPnlCallbacks: {
47576
47863
  onError: (error) => {
47577
- import_logger12.logger.warn(
47864
+ import_logger13.logger.warn(
47578
47865
  "signals summary: getClosedPnl failed for scope account=%s deployment=%s: %s",
47579
47866
  scope.accountId ?? "default",
47580
47867
  scope.deploymentId ?? "default",
@@ -47988,7 +48275,7 @@ none`
47988
48275
  (sum3, stats) => sum3 + stats.evaluated,
47989
48276
  0
47990
48277
  );
47991
- import_logger12.logger.info(
48278
+ import_logger13.logger.info(
47992
48279
  "signals summary deployment=%s window=%sh signals=%s evaluations=%s trades=%s connectors=%s scopes=%s user=%s",
47993
48280
  scope.deploymentId ?? "legacy",
47994
48281
  hours,
@@ -48046,26 +48333,26 @@ none`
48046
48333
  });
48047
48334
  }
48048
48335
  };
48049
- main53 = signalsSummary;
48336
+ main54 = signalsSummary;
48050
48337
  }
48051
48338
  });
48052
48339
 
48053
48340
  // src/scripts/test-ml.ts
48054
48341
  var test_ml_exports = {};
48055
48342
  __export(test_ml_exports, {
48056
- main: () => main54
48343
+ main: () => main55
48057
48344
  });
48058
- var import_config14, import_constants21, import_ml3, import_registry6, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main54;
48345
+ var import_config14, import_constants22, import_ml3, import_registry6, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main55;
48059
48346
  var init_test_ml = __esm({
48060
48347
  "src/scripts/test-ml.ts"() {
48061
48348
  "use strict";
48062
48349
  import_config14 = require("dotenv/config");
48063
- import_constants21 = require("@tradejs/core/constants");
48350
+ import_constants22 = require("@tradejs/core/constants");
48064
48351
  import_ml3 = require("@tradejs/infra/ml");
48065
48352
  import_registry6 = require("@tradejs/node/registry");
48066
48353
  now = Date.now();
48067
48354
  INTERVAL_MIN = 15;
48068
- CANDLES = import_constants21.ML_BASE_CANDLES_WINDOW;
48355
+ CANDLES = import_constants22.ML_BASE_CANDLES_WINDOW;
48069
48356
  makeSeries = (len, base, step = 0.1) => Array.from({ length: len }, (_3, i) => base + i * step);
48070
48357
  makeCandles = (startPrice, startTs) => {
48071
48358
  const candles = [];
@@ -48105,7 +48392,7 @@ var init_test_ml = __esm({
48105
48392
  { timestamp: entryTs - 2 * INTERVAL_MIN * 6e4, value: price * 0.995 }
48106
48393
  ]
48107
48394
  });
48108
- main54 = async () => {
48395
+ main55 = async () => {
48109
48396
  const defaultConfig = await (0, import_registry6.getStrategyDefaults)("TrendLine", process.cwd());
48110
48397
  if (!defaultConfig) {
48111
48398
  throw new Error(
@@ -48137,8 +48424,8 @@ var init_test_ml = __esm({
48137
48424
  correlation: 0.18,
48138
48425
  touches: 6,
48139
48426
  distance: 0.7,
48140
- candles15m: candles.slice(-import_constants21.ML_BASE_CANDLES_WINDOW),
48141
- btcCandles15m: btcCandles.slice(-import_constants21.ML_BASE_CANDLES_WINDOW),
48427
+ candles15m: candles.slice(-import_constants22.ML_BASE_CANDLES_WINDOW),
48428
+ btcCandles15m: btcCandles.slice(-import_constants22.ML_BASE_CANDLES_WINDOW),
48142
48429
  atr: makeSeries(10, 1.2, 0.02),
48143
48430
  atrPct: makeSeries(10, 1.05, 5e-3),
48144
48431
  maFast: makeSeries(10, currentPrice * 0.995, 0.01),
@@ -48198,20 +48485,20 @@ var init_test_ml = __esm({
48198
48485
  // src/scripts/test.ts
48199
48486
  var test_exports = {};
48200
48487
  __export(test_exports, {
48201
- main: () => main55
48488
+ main: () => main56
48202
48489
  });
48203
- var import_config15, import_connectors20, getPositions, main55;
48490
+ var import_config15, import_connectors21, getPositions, main56;
48204
48491
  var init_test = __esm({
48205
48492
  "src/scripts/test.ts"() {
48206
48493
  "use strict";
48207
48494
  import_config15 = require("dotenv/config");
48208
- import_connectors20 = require("@tradejs/connectors");
48495
+ import_connectors21 = require("@tradejs/connectors");
48209
48496
  getPositions = async (connector) => {
48210
48497
  const res = await connector.getPositions();
48211
48498
  console.log("res", res);
48212
48499
  };
48213
- main55 = async () => {
48214
- const byBitConnector = await import_connectors20.connectors.ByBit({
48500
+ main56 = async () => {
48501
+ const byBitConnector = await import_connectors21.connectors.ByBit({
48215
48502
  userName: "root"
48216
48503
  });
48217
48504
  await getPositions(byBitConnector);
@@ -48222,21 +48509,21 @@ var init_test = __esm({
48222
48509
  // src/scripts/user-add.ts
48223
48510
  var user_add_exports = {};
48224
48511
  __export(user_add_exports, {
48225
- main: () => main56
48512
+ main: () => main57
48226
48513
  });
48227
- var import_args39, import_chalk55, import_bcryptjs, import_redis25, flags35, main56;
48514
+ var import_args39, import_chalk55, import_bcryptjs, import_redis26, flags35, main57;
48228
48515
  var init_user_add = __esm({
48229
48516
  "src/scripts/user-add.ts"() {
48230
48517
  "use strict";
48231
48518
  import_args39 = __toESM(require("args"));
48232
48519
  import_chalk55 = __toESM(require("chalk"));
48233
48520
  import_bcryptjs = __toESM(require("bcryptjs"));
48234
- import_redis25 = require("@tradejs/infra/redis");
48521
+ import_redis26 = require("@tradejs/infra/redis");
48235
48522
  import_args39.default.example("yarn user-add -u myname -p 123456", "Create or update user");
48236
48523
  import_args39.default.option(["u", "user"], "Username", "");
48237
48524
  import_args39.default.option(["p", "password"], "Password (plain text)", "");
48238
48525
  flags35 = import_args39.default.parse(process.argv);
48239
- main56 = async () => {
48526
+ main57 = async () => {
48240
48527
  const userName3 = String(flags35.user || "").trim();
48241
48528
  const password = String(flags35.password || "");
48242
48529
  if (!userName3 || !password) {
@@ -48244,14 +48531,14 @@ var init_user_add = __esm({
48244
48531
  process.exit(1);
48245
48532
  }
48246
48533
  const passwordHash = await import_bcryptjs.default.hash(password, 10);
48247
- const existing = await (0, import_redis25.getData)(import_redis25.redisKeys.user(userName3), null);
48534
+ const existing = await (0, import_redis26.getData)(import_redis26.redisKeys.user(userName3), null);
48248
48535
  const next = {
48249
48536
  ...existing ?? {},
48250
48537
  passwordHash,
48251
48538
  userName: userName3,
48252
48539
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
48253
48540
  };
48254
- await (0, import_redis25.setData)(import_redis25.redisKeys.user(userName3), next, {
48541
+ await (0, import_redis26.setData)(import_redis26.redisKeys.user(userName3), next, {
48255
48542
  expire: 0
48256
48543
  });
48257
48544
  console.log(import_chalk55.default.green(`User ${userName3} updated`));
@@ -48264,14 +48551,14 @@ var init_user_add = __esm({
48264
48551
  var cli_exports = {};
48265
48552
  __export(cli_exports, {
48266
48553
  cleanupCliResources: () => cleanupCliResources,
48267
- main: () => main57,
48554
+ main: () => main58,
48268
48555
  printUsage: () => printUsage3,
48269
48556
  runLoadedModule: () => runLoadedModule
48270
48557
  });
48271
48558
  module.exports = __toCommonJS(cli_exports);
48272
48559
  var import_config16 = require("dotenv/config");
48273
- var import_redis26 = require("@tradejs/infra/redis");
48274
- var import_client9 = require("@tradejs/infra/timescale/client");
48560
+ var import_redis27 = require("@tradejs/infra/redis");
48561
+ var import_client10 = require("@tradejs/infra/timescale/client");
48275
48562
  var scriptLoaders = {
48276
48563
  "research-visuals": () => Promise.resolve().then(() => (init_researchVisuals2(), researchVisuals_exports)),
48277
48564
  "agent-run": () => Promise.resolve().then(() => (init_agentRun(), agentRun_exports)),
@@ -48289,6 +48576,7 @@ var scriptLoaders = {
48289
48576
  "clean-dir": () => Promise.resolve().then(() => (init_cleanDir(), cleanDir_exports)),
48290
48577
  "clean-redis": () => Promise.resolve().then(() => (init_cleanRedis(), cleanRedis_exports)),
48291
48578
  "clean-tests": () => Promise.resolve().then(() => (init_cleanTests(), cleanTests_exports)),
48579
+ "coverage:backfill": () => Promise.resolve().then(() => (init_coverageBackfill(), coverageBackfill_exports)),
48292
48580
  continuity: () => Promise.resolve().then(() => (init_continuity2(), continuity_exports)),
48293
48581
  "derivatives:ingest": () => Promise.resolve().then(() => (init_derivativesIngest(), derivativesIngest_exports)),
48294
48582
  "derivatives:ingest:coinalyze:all": () => Promise.resolve().then(() => (init_derivativesIngestCoinalyzeAll(), derivativesIngestCoinalyzeAll_exports)),
@@ -48345,9 +48633,9 @@ var runLoadedModule = async (loaded) => {
48345
48633
  }
48346
48634
  };
48347
48635
  var cleanupCliResources = async () => {
48348
- await Promise.allSettled([(0, import_redis26.closeRedisConnection)(), (0, import_client9.closeTimescalePool)()]);
48636
+ await Promise.allSettled([(0, import_redis27.closeRedisConnection)(), (0, import_client10.closeTimescalePool)()]);
48349
48637
  };
48350
- var main57 = async () => {
48638
+ var main58 = async () => {
48351
48639
  const [, scriptPath, command = "", ...args40] = process.argv;
48352
48640
  const loader = scriptLoaders[command];
48353
48641
  if (!loader) {
@@ -48378,7 +48666,7 @@ var main57 = async () => {
48378
48666
  }
48379
48667
  };
48380
48668
  if (require.main === module) {
48381
- main57().catch((error) => {
48669
+ main58().catch((error) => {
48382
48670
  console.error(error);
48383
48671
  process.exit(1);
48384
48672
  });