@tradejs/cli 3.1.6 → 3.1.8-beta.204

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
@@ -6611,13 +6611,13 @@ var init_aiTrainCharts = __esm({
6611
6611
  if (!evaluations.length) {
6612
6612
  return [];
6613
6613
  }
6614
- const sorted = [...evaluations].sort(
6614
+ const sorted2 = [...evaluations].sort(
6615
6615
  (left, right) => (left.timestamp ?? 0) - (right.timestamp ?? 0) || left.symbol.localeCompare(right.symbol) || left.signalId.localeCompare(right.signalId)
6616
6616
  );
6617
6617
  let amount = 100;
6618
- const firstTimestamp = sorted[0]?.timestamp ?? Date.now();
6618
+ const firstTimestamp = sorted2[0]?.timestamp ?? Date.now();
6619
6619
  const orderLog = [[firstTimestamp, amount]];
6620
- for (const evaluation of sorted) {
6620
+ for (const evaluation of sorted2) {
6621
6621
  amount += evaluation.profit;
6622
6622
  orderLog.push([
6623
6623
  evaluation.timestamp ?? firstTimestamp,
@@ -16388,12 +16388,12 @@ var init_executionCalibration = __esm({
16388
16388
  if (!values.length) {
16389
16389
  return null;
16390
16390
  }
16391
- const sorted = [...values].sort((left, right) => left - right);
16392
- const index = (sorted.length - 1) * probability;
16391
+ const sorted2 = [...values].sort((left, right) => left - right);
16392
+ const index = (sorted2.length - 1) * probability;
16393
16393
  const lowerIndex = Math.floor(index);
16394
16394
  const upperIndex = Math.ceil(index);
16395
- const lower = sorted[lowerIndex];
16396
- const upper = sorted[upperIndex];
16395
+ const lower = sorted2[lowerIndex];
16396
+ const upper = sorted2[upperIndex];
16397
16397
  if (lower == null || upper == null) {
16398
16398
  return null;
16399
16399
  }
@@ -17905,9 +17905,9 @@ var init_hyperliquidWhaleSelection = __esm({
17905
17905
  };
17906
17906
  median = (values) => {
17907
17907
  if (!values.length) return 0;
17908
- const sorted = [...values].sort((left, right) => left - right);
17909
- const middle = Math.floor(sorted.length / 2);
17910
- return sorted.length % 2 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
17908
+ const sorted2 = [...values].sort((left, right) => left - right);
17909
+ const middle = Math.floor(sorted2.length / 2);
17910
+ return sorted2.length % 2 ? sorted2[middle] : (sorted2[middle - 1] + sorted2[middle]) / 2;
17911
17911
  };
17912
17912
  evaluateHyperliquidWhaleStructure = (params) => {
17913
17913
  const fills = params.fills.filter((fill) => {
@@ -18387,14 +18387,14 @@ var init_mlInspect = __esm({
18387
18387
  }
18388
18388
  return sample;
18389
18389
  };
18390
- quantileSorted = (sorted, q) => {
18391
- if (!sorted.length) return 0;
18392
- if (sorted.length === 1) return sorted[0];
18393
- const pos = (sorted.length - 1) * q;
18390
+ quantileSorted = (sorted2, q) => {
18391
+ if (!sorted2.length) return 0;
18392
+ if (sorted2.length === 1) return sorted2[0];
18393
+ const pos = (sorted2.length - 1) * q;
18394
18394
  const base = Math.floor(pos);
18395
18395
  const rest = pos - base;
18396
- const left = sorted[base];
18397
- const right = sorted[Math.min(base + 1, sorted.length - 1)];
18396
+ const left = sorted2[base];
18397
+ const right = sorted2[Math.min(base + 1, sorted2.length - 1)];
18398
18398
  return left + (right - left) * rest;
18399
18399
  };
18400
18400
  mean2 = (values) => {
@@ -18469,12 +18469,12 @@ var init_mlInspect = __esm({
18469
18469
  if (values.length < minFieldValues) {
18470
18470
  continue;
18471
18471
  }
18472
- const sorted = [...values].sort((a, b) => a - b);
18473
- const q1 = quantileSorted(sorted, 0.25);
18474
- const median2 = quantileSorted(sorted, 0.5);
18475
- const q3 = quantileSorted(sorted, 0.75);
18476
- const p95 = quantileSorted(sorted, 0.95);
18477
- const p99 = quantileSorted(sorted, 0.99);
18472
+ const sorted2 = [...values].sort((a, b) => a - b);
18473
+ const q1 = quantileSorted(sorted2, 0.25);
18474
+ const median2 = quantileSorted(sorted2, 0.5);
18475
+ const q3 = quantileSorted(sorted2, 0.75);
18476
+ const p95 = quantileSorted(sorted2, 0.95);
18477
+ const p99 = quantileSorted(sorted2, 0.99);
18478
18478
  const valuesMean = mean2(values);
18479
18479
  const valuesStd = std(values, valuesMean);
18480
18480
  const iqr = q3 - q1;
@@ -18490,8 +18490,8 @@ var init_mlInspect = __esm({
18490
18490
  nonFiniteRate: nonFinite / Math.max(present, 1),
18491
18491
  zeroRate: zeros / Math.max(values.length, 1),
18492
18492
  uniqueCount,
18493
- min: sorted[0],
18494
- max: sorted[sorted.length - 1],
18493
+ min: sorted2[0],
18494
+ max: sorted2[sorted2.length - 1],
18495
18495
  mean: valuesMean,
18496
18496
  std: valuesStd,
18497
18497
  median: median2,
@@ -21339,14 +21339,14 @@ var init_metrics = __esm({
21339
21339
  "SHORT"
21340
21340
  ];
21341
21341
  selectCohort = (trades, cohort) => cohort === "ALL" ? trades : trades.filter((trade) => trade.direction === cohort);
21342
- quantile2 = (sorted, probability) => {
21343
- if (!sorted.length) return null;
21344
- const position = (sorted.length - 1) * probability;
21342
+ quantile2 = (sorted2, probability) => {
21343
+ if (!sorted2.length) return null;
21344
+ const position = (sorted2.length - 1) * probability;
21345
21345
  const lower = Math.floor(position);
21346
21346
  const upper = Math.ceil(position);
21347
- if (lower === upper) return sorted[lower];
21347
+ if (lower === upper) return sorted2[lower];
21348
21348
  const weight = position - lower;
21349
- return sorted[lower] * (1 - weight) + sorted[upper] * weight;
21349
+ return sorted2[lower] * (1 - weight) + sorted2[upper] * weight;
21350
21350
  };
21351
21351
  compareChronologicalTrades = (left, right) => left.exitTimestamp - right.exitTimestamp || (left.signalId < right.signalId ? -1 : left.signalId > right.signalId ? 1 : 0);
21352
21352
  orderCoreResearchTrades = (trades) => {
@@ -21358,7 +21358,7 @@ var init_metrics = __esm({
21358
21358
  return trades;
21359
21359
  };
21360
21360
  summarizeCoreResearchTrades = (trades, periodDays) => {
21361
- const sorted = orderCoreResearchTrades(trades);
21361
+ const sorted2 = orderCoreResearchTrades(trades);
21362
21362
  let pnl = 0;
21363
21363
  let grossProfit = 0;
21364
21364
  let grossLoss = 0;
@@ -21370,7 +21370,7 @@ var init_metrics = __esm({
21370
21370
  let realizedMaxDrawdown = 0;
21371
21371
  let consecutiveLosses = 0;
21372
21372
  let maximumConsecutiveLosses = 0;
21373
- for (const trade of sorted) {
21373
+ for (const trade of sorted2) {
21374
21374
  pnl += trade.netProfit;
21375
21375
  if (trade.netProfit > 0) {
21376
21376
  wins += 1;
@@ -21392,9 +21392,9 @@ var init_metrics = __esm({
21392
21392
  peak = Math.max(peak, equity);
21393
21393
  realizedMaxDrawdown = Math.max(realizedMaxDrawdown, peak - equity);
21394
21394
  }
21395
- const count = sorted.length;
21396
- const pnlDistribution = sorted.map((trade) => trade.netProfit).sort((left, right) => left - right);
21397
- const holdingHours = sorted.map((trade) => (trade.exitTimestamp - trade.entryTimestamp) / 36e5).sort((left, right) => left - right);
21395
+ const count = sorted2.length;
21396
+ const pnlDistribution = sorted2.map((trade) => trade.netProfit).sort((left, right) => left - right);
21397
+ const holdingHours = sorted2.map((trade) => (trade.exitTimestamp - trade.entryTimestamp) / 36e5).sort((left, right) => left - right);
21398
21398
  const averageWin = wins > 0 ? grossProfit / wins : null;
21399
21399
  const strictLosses = losses - breakeven;
21400
21400
  const averageLoss = strictLosses > 0 ? grossLoss / strictLosses : null;
@@ -21567,13 +21567,13 @@ var init_statistics = __esm({
21567
21567
  return (state >>> 0) / 4294967296;
21568
21568
  };
21569
21569
  };
21570
- percentile = (sorted, probability) => {
21571
- if (!sorted.length) return Number.NaN;
21570
+ percentile = (sorted2, probability) => {
21571
+ if (!sorted2.length) return Number.NaN;
21572
21572
  const index = Math.min(
21573
- sorted.length - 1,
21574
- Math.max(0, Math.floor(probability * sorted.length))
21573
+ sorted2.length - 1,
21574
+ Math.max(0, Math.floor(probability * sorted2.length))
21575
21575
  );
21576
- return sorted[index];
21576
+ return sorted2[index];
21577
21577
  };
21578
21578
  calendarClusterBootstrap = (params) => {
21579
21579
  const clusterMs = params.clusterDays * DAY_MS11;
@@ -21787,8 +21787,8 @@ var init_statistics = __esm({
21787
21787
  const outScores = performanceByVariant.map(
21788
21788
  (performance) => outSample.reduce((sum3, index) => sum3 + performance[index], 0)
21789
21789
  );
21790
- const sorted = [...outScores].sort((left, right) => left - right);
21791
- const rankAscending = sorted.indexOf(outScores[selected]);
21790
+ const sorted2 = [...outScores].sort((left, right) => left - right);
21791
+ const rankAscending = sorted2.indexOf(outScores[selected]);
21792
21792
  const omega = (rankAscending + 1) / (outScores.length + 1);
21793
21793
  if (Math.log(omega / (1 - omega)) < 0) belowMedian += 1;
21794
21794
  }
@@ -26584,12 +26584,12 @@ var init_monitoringProfile = __esm({
26584
26584
  return left;
26585
26585
  };
26586
26586
  percentile2 = (values, probability) => {
26587
- const sorted = [...values].sort((left, right) => left - right);
26588
- const position = (sorted.length - 1) * probability;
26587
+ const sorted2 = [...values].sort((left, right) => left - right);
26588
+ const position = (sorted2.length - 1) * probability;
26589
26589
  const lower = Math.floor(position);
26590
26590
  const upper = Math.ceil(position);
26591
- if (lower === upper) return sorted[lower];
26592
- return sorted[lower] * (upper - position) + sorted[upper] * (position - lower);
26591
+ if (lower === upper) return sorted2[lower];
26592
+ return sorted2[lower] * (upper - position) + sorted2[upper] * (position - lower);
26593
26593
  };
26594
26594
  buildStrategyMonitoringProfile = ({
26595
26595
  trades,
@@ -32262,6 +32262,57 @@ var init_tickerEvaluator = __esm({
32262
32262
  }
32263
32263
  });
32264
32264
 
32265
+ // src/lib/signals/configuredScopes.ts
32266
+ var sorted, formatConfiguredStrategyIdentity, buildConfiguredSignalsScopes;
32267
+ var init_configuredScopes = __esm({
32268
+ "src/lib/signals/configuredScopes.ts"() {
32269
+ "use strict";
32270
+ sorted = (values) => values ? [...values].sort() : [];
32271
+ formatConfiguredStrategyIdentity = (strategy) => `${strategy.strategyName}@v${strategy.releaseVersion}[${strategy.controlState}]`;
32272
+ buildConfiguredSignalsScopes = ({
32273
+ connectorName,
32274
+ deployment,
32275
+ strategies
32276
+ }) => {
32277
+ const deploymentIdentity = JSON.stringify({
32278
+ id: deployment.id,
32279
+ enabled: deployment.enabled,
32280
+ connectorName: deployment.connectorName,
32281
+ provider: deployment.provider,
32282
+ accountId: deployment.accountId,
32283
+ tickers: sorted(deployment.tickers),
32284
+ assetClasses: sorted(deployment.assetClasses)
32285
+ });
32286
+ const groups = /* @__PURE__ */ new Map();
32287
+ for (const strategy of strategies) {
32288
+ const baseKey = [
32289
+ connectorName,
32290
+ strategy.universe,
32291
+ strategy.accountId ?? "default",
32292
+ strategy.interval
32293
+ ].join(":");
32294
+ const group = groups.get(baseKey) ?? {
32295
+ scope: {
32296
+ connectorName,
32297
+ universe: strategy.universe,
32298
+ accountId: strategy.accountId,
32299
+ interval: strategy.interval
32300
+ },
32301
+ strategyIdentities: []
32302
+ };
32303
+ group.strategyIdentities.push(formatConfiguredStrategyIdentity(strategy));
32304
+ groups.set(baseKey, group);
32305
+ }
32306
+ return [...groups.entries()].map(([baseKey, group]) => ({
32307
+ key: [baseKey, deploymentIdentity, ...group.strategyIdentities.sort()].join(
32308
+ ":"
32309
+ ),
32310
+ scope: group.scope
32311
+ }));
32312
+ };
32313
+ }
32314
+ });
32315
+
32265
32316
  // src/lib/signals/runner.ts
32266
32317
  var import_progress11, import_chalk45, import_connectors16, import_cli12, import_async5, import_strategies13, import_constants16, import_time8, import_logger10, import_runtimeDeployments3, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
32267
32318
  var init_runner = __esm({
@@ -32290,6 +32341,7 @@ var init_runner = __esm({
32290
32341
  init_daemon();
32291
32342
  init_klineFeed();
32292
32343
  init_tickerEvaluator();
32344
+ init_configuredScopes();
32293
32345
  SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
32294
32346
  formatDuration3 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
32295
32347
  resolvePositiveInteger2 = (value, fallback) => {
@@ -32611,7 +32663,7 @@ var init_runner = __esm({
32611
32663
  );
32612
32664
  import_logger10.logger.info(
32613
32665
  import_chalk45.default.yellow(
32614
- `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
32666
+ `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
32615
32667
  )
32616
32668
  );
32617
32669
  afterSignalsHookContext = {
@@ -32797,22 +32849,13 @@ var init_runner = __esm({
32797
32849
  const connectorName = await resolveSignalsConnectorName(
32798
32850
  deployment.connectorName
32799
32851
  );
32800
- const scopes = /* @__PURE__ */ new Map();
32801
- for (const strategy of configuredStrategies) {
32802
- const key = [
32803
- connectorName,
32804
- strategy.universe,
32805
- strategy.accountId ?? "default",
32806
- strategy.interval
32807
- ].join(":");
32808
- scopes.set(key, {
32852
+ return new Map(
32853
+ buildConfiguredSignalsScopes({
32809
32854
  connectorName,
32810
- universe: strategy.universe,
32811
- accountId: strategy.accountId,
32812
- interval: strategy.interval
32813
- });
32814
- }
32815
- return scopes;
32855
+ deployment,
32856
+ strategies: configuredStrategies
32857
+ }).map(({ key, scope }) => [key, scope])
32858
+ );
32816
32859
  };
32817
32860
  const signalsConfiguredScopesOnce2 = async () => {
32818
32861
  if (config2.updateOnly || config2.showTickersList) {
@@ -32853,12 +32896,13 @@ var init_runner = __esm({
32853
32896
  if (!config2.deploymentId) {
32854
32897
  throw new Error("Runtime deployment id is required");
32855
32898
  }
32856
- const daemonDeployment = await (0, import_runtimeDeployments3.getRuntimeDeployment)(
32899
+ const deploymentId = config2.deploymentId;
32900
+ const initialDeployment = await (0, import_runtimeDeployments3.getRuntimeDeployment)(
32857
32901
  config2.userName,
32858
- config2.deploymentId
32902
+ deploymentId
32859
32903
  );
32860
- if (!daemonDeployment) {
32861
- throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
32904
+ if (!initialDeployment) {
32905
+ throw new Error(`Runtime deployment not found: ${deploymentId}`);
32862
32906
  }
32863
32907
  const sessions = /* @__PURE__ */ new Map();
32864
32908
  const lastBoundaryByScope = /* @__PURE__ */ new Map();
@@ -32877,7 +32921,14 @@ var init_runner = __esm({
32877
32921
  settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
32878
32922
  signal: abortController.signal,
32879
32923
  runCycle: async () => {
32880
- const scopes = await loadConfiguredSignalsScopes(daemonDeployment);
32924
+ const currentDeployment = await (0, import_runtimeDeployments3.getRuntimeDeployment)(
32925
+ config2.userName,
32926
+ deploymentId
32927
+ );
32928
+ if (!currentDeployment) {
32929
+ throw new Error(`Runtime deployment not found: ${deploymentId}`);
32930
+ }
32931
+ const scopes = await loadConfiguredSignalsScopes(currentDeployment);
32881
32932
  for (const [key, staleSession] of sessions) {
32882
32933
  if (scopes.has(key)) continue;
32883
32934
  await staleSession.klineFeed?.close();
@@ -36599,8 +36650,8 @@ var init_outputReport = __esm({
36599
36650
  grouped.set(record.strategy, existing);
36600
36651
  }
36601
36652
  const formatSet = (values) => {
36602
- const sorted = [...values].sort();
36603
- return sorted.length <= 3 ? sorted.join(", ") : `${sorted.slice(0, 3).join(", ")} \u2026 (+${sorted.length - 3})`;
36653
+ const sorted2 = [...values].sort();
36654
+ return sorted2.length <= 3 ? sorted2.join(", ") : `${sorted2.slice(0, 3).join(", ")} \u2026 (+${sorted2.length - 3})`;
36604
36655
  };
36605
36656
  return grouped.size ? createMarkdownTable2(
36606
36657
  [
@@ -4994,6 +4994,51 @@ var createSignalsTickerEvaluator = ({
4994
4994
  return strategySignals;
4995
4995
  };
4996
4996
 
4997
+ // src/lib/signals/configuredScopes.ts
4998
+ var sorted = (values) => values ? [...values].sort() : [];
4999
+ var formatConfiguredStrategyIdentity = (strategy) => `${strategy.strategyName}@v${strategy.releaseVersion}[${strategy.controlState}]`;
5000
+ var buildConfiguredSignalsScopes = ({
5001
+ connectorName,
5002
+ deployment,
5003
+ strategies
5004
+ }) => {
5005
+ const deploymentIdentity = JSON.stringify({
5006
+ id: deployment.id,
5007
+ enabled: deployment.enabled,
5008
+ connectorName: deployment.connectorName,
5009
+ provider: deployment.provider,
5010
+ accountId: deployment.accountId,
5011
+ tickers: sorted(deployment.tickers),
5012
+ assetClasses: sorted(deployment.assetClasses)
5013
+ });
5014
+ const groups = /* @__PURE__ */ new Map();
5015
+ for (const strategy of strategies) {
5016
+ const baseKey = [
5017
+ connectorName,
5018
+ strategy.universe,
5019
+ strategy.accountId ?? "default",
5020
+ strategy.interval
5021
+ ].join(":");
5022
+ const group = groups.get(baseKey) ?? {
5023
+ scope: {
5024
+ connectorName,
5025
+ universe: strategy.universe,
5026
+ accountId: strategy.accountId,
5027
+ interval: strategy.interval
5028
+ },
5029
+ strategyIdentities: []
5030
+ };
5031
+ group.strategyIdentities.push(formatConfiguredStrategyIdentity(strategy));
5032
+ groups.set(baseKey, group);
5033
+ }
5034
+ return [...groups.entries()].map(([baseKey, group]) => ({
5035
+ key: [baseKey, deploymentIdentity, ...group.strategyIdentities.sort()].join(
5036
+ ":"
5037
+ ),
5038
+ scope: group.scope
5039
+ }));
5040
+ };
5041
+
4997
5042
  // src/lib/signals/runner.ts
4998
5043
  var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
4999
5044
  var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
@@ -5316,7 +5361,7 @@ var createSignalsRunner = (config2) => {
5316
5361
  );
5317
5362
  import_logger4.logger.info(
5318
5363
  import_chalk7.default.yellow(
5319
- `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
5364
+ `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
5320
5365
  )
5321
5366
  );
5322
5367
  afterSignalsHookContext = {
@@ -5502,22 +5547,13 @@ var createSignalsRunner = (config2) => {
5502
5547
  const connectorName = await resolveSignalsConnectorName(
5503
5548
  deployment.connectorName
5504
5549
  );
5505
- const scopes = /* @__PURE__ */ new Map();
5506
- for (const strategy of configuredStrategies) {
5507
- const key = [
5508
- connectorName,
5509
- strategy.universe,
5510
- strategy.accountId ?? "default",
5511
- strategy.interval
5512
- ].join(":");
5513
- scopes.set(key, {
5550
+ return new Map(
5551
+ buildConfiguredSignalsScopes({
5514
5552
  connectorName,
5515
- universe: strategy.universe,
5516
- accountId: strategy.accountId,
5517
- interval: strategy.interval
5518
- });
5519
- }
5520
- return scopes;
5553
+ deployment,
5554
+ strategies: configuredStrategies
5555
+ }).map(({ key, scope }) => [key, scope])
5556
+ );
5521
5557
  };
5522
5558
  const signalsConfiguredScopesOnce2 = async () => {
5523
5559
  if (config2.updateOnly || config2.showTickersList) {
@@ -5558,12 +5594,13 @@ var createSignalsRunner = (config2) => {
5558
5594
  if (!config2.deploymentId) {
5559
5595
  throw new Error("Runtime deployment id is required");
5560
5596
  }
5561
- const daemonDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
5597
+ const deploymentId = config2.deploymentId;
5598
+ const initialDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
5562
5599
  config2.userName,
5563
- config2.deploymentId
5600
+ deploymentId
5564
5601
  );
5565
- if (!daemonDeployment) {
5566
- throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
5602
+ if (!initialDeployment) {
5603
+ throw new Error(`Runtime deployment not found: ${deploymentId}`);
5567
5604
  }
5568
5605
  const sessions = /* @__PURE__ */ new Map();
5569
5606
  const lastBoundaryByScope = /* @__PURE__ */ new Map();
@@ -5582,7 +5619,14 @@ var createSignalsRunner = (config2) => {
5582
5619
  settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
5583
5620
  signal: abortController.signal,
5584
5621
  runCycle: async () => {
5585
- const scopes = await loadConfiguredSignalsScopes(daemonDeployment);
5622
+ const currentDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
5623
+ config2.userName,
5624
+ deploymentId
5625
+ );
5626
+ if (!currentDeployment) {
5627
+ throw new Error(`Runtime deployment not found: ${deploymentId}`);
5628
+ }
5629
+ const scopes = await loadConfiguredSignalsScopes(currentDeployment);
5586
5630
  for (const [key, staleSession] of sessions) {
5587
5631
  if (scopes.has(key)) continue;
5588
5632
  await staleSession.klineFeed?.close();
@@ -4992,6 +4992,51 @@ var createSignalsTickerEvaluator = ({
4992
4992
  return strategySignals;
4993
4993
  };
4994
4994
 
4995
+ // src/lib/signals/configuredScopes.ts
4996
+ var sorted = (values) => values ? [...values].sort() : [];
4997
+ var formatConfiguredStrategyIdentity = (strategy) => `${strategy.strategyName}@v${strategy.releaseVersion}[${strategy.controlState}]`;
4998
+ var buildConfiguredSignalsScopes = ({
4999
+ connectorName,
5000
+ deployment,
5001
+ strategies
5002
+ }) => {
5003
+ const deploymentIdentity = JSON.stringify({
5004
+ id: deployment.id,
5005
+ enabled: deployment.enabled,
5006
+ connectorName: deployment.connectorName,
5007
+ provider: deployment.provider,
5008
+ accountId: deployment.accountId,
5009
+ tickers: sorted(deployment.tickers),
5010
+ assetClasses: sorted(deployment.assetClasses)
5011
+ });
5012
+ const groups = /* @__PURE__ */ new Map();
5013
+ for (const strategy of strategies) {
5014
+ const baseKey = [
5015
+ connectorName,
5016
+ strategy.universe,
5017
+ strategy.accountId ?? "default",
5018
+ strategy.interval
5019
+ ].join(":");
5020
+ const group = groups.get(baseKey) ?? {
5021
+ scope: {
5022
+ connectorName,
5023
+ universe: strategy.universe,
5024
+ accountId: strategy.accountId,
5025
+ interval: strategy.interval
5026
+ },
5027
+ strategyIdentities: []
5028
+ };
5029
+ group.strategyIdentities.push(formatConfiguredStrategyIdentity(strategy));
5030
+ groups.set(baseKey, group);
5031
+ }
5032
+ return [...groups.entries()].map(([baseKey, group]) => ({
5033
+ key: [baseKey, deploymentIdentity, ...group.strategyIdentities.sort()].join(
5034
+ ":"
5035
+ ),
5036
+ scope: group.scope
5037
+ }));
5038
+ };
5039
+
4995
5040
  // src/lib/signals/runner.ts
4996
5041
  var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
4997
5042
  var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
@@ -5314,7 +5359,7 @@ var createSignalsRunner = (config2) => {
5314
5359
  );
5315
5360
  import_logger4.logger.info(
5316
5361
  import_chalk7.default.yellow(
5317
- `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
5362
+ `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
5318
5363
  )
5319
5364
  );
5320
5365
  afterSignalsHookContext = {
@@ -5500,22 +5545,13 @@ var createSignalsRunner = (config2) => {
5500
5545
  const connectorName = await resolveSignalsConnectorName(
5501
5546
  deployment.connectorName
5502
5547
  );
5503
- const scopes = /* @__PURE__ */ new Map();
5504
- for (const strategy of configuredStrategies) {
5505
- const key = [
5506
- connectorName,
5507
- strategy.universe,
5508
- strategy.accountId ?? "default",
5509
- strategy.interval
5510
- ].join(":");
5511
- scopes.set(key, {
5548
+ return new Map(
5549
+ buildConfiguredSignalsScopes({
5512
5550
  connectorName,
5513
- universe: strategy.universe,
5514
- accountId: strategy.accountId,
5515
- interval: strategy.interval
5516
- });
5517
- }
5518
- return scopes;
5551
+ deployment,
5552
+ strategies: configuredStrategies
5553
+ }).map(({ key, scope }) => [key, scope])
5554
+ );
5519
5555
  };
5520
5556
  const signalsConfiguredScopesOnce2 = async () => {
5521
5557
  if (config2.updateOnly || config2.showTickersList) {
@@ -5556,12 +5592,13 @@ var createSignalsRunner = (config2) => {
5556
5592
  if (!config2.deploymentId) {
5557
5593
  throw new Error("Runtime deployment id is required");
5558
5594
  }
5559
- const daemonDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
5595
+ const deploymentId = config2.deploymentId;
5596
+ const initialDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
5560
5597
  config2.userName,
5561
- config2.deploymentId
5598
+ deploymentId
5562
5599
  );
5563
- if (!daemonDeployment) {
5564
- throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
5600
+ if (!initialDeployment) {
5601
+ throw new Error(`Runtime deployment not found: ${deploymentId}`);
5565
5602
  }
5566
5603
  const sessions = /* @__PURE__ */ new Map();
5567
5604
  const lastBoundaryByScope = /* @__PURE__ */ new Map();
@@ -5580,7 +5617,14 @@ var createSignalsRunner = (config2) => {
5580
5617
  settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
5581
5618
  signal: abortController.signal,
5582
5619
  runCycle: async () => {
5583
- const scopes = await loadConfiguredSignalsScopes(daemonDeployment);
5620
+ const currentDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
5621
+ config2.userName,
5622
+ deploymentId
5623
+ );
5624
+ if (!currentDeployment) {
5625
+ throw new Error(`Runtime deployment not found: ${deploymentId}`);
5626
+ }
5627
+ const scopes = await loadConfiguredSignalsScopes(currentDeployment);
5584
5628
  for (const [key, staleSession] of sessions) {
5585
5629
  if (scopes.has(key)) continue;
5586
5630
  await staleSession.klineFeed?.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/cli",
3
- "version": "3.1.6",
3
+ "version": "3.1.8-beta.204",
4
4
  "description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
5
5
  "keywords": [
6
6
  "tradejs",
@@ -32,13 +32,13 @@
32
32
  "tradejs": "dist/cli.js"
33
33
  },
34
34
  "dependencies": {
35
- "@tradejs/connectors": "^3.1.6",
36
- "@tradejs/core": "^3.1.6",
37
- "@tradejs/indicators": "^3.1.6",
38
- "@tradejs/infra": "^3.1.6",
39
- "@tradejs/node": "^3.1.6",
35
+ "@tradejs/connectors": "^3.1.8-beta.204",
36
+ "@tradejs/core": "^3.1.8-beta.204",
37
+ "@tradejs/indicators": "^3.1.8-beta.204",
38
+ "@tradejs/infra": "^3.1.8-beta.204",
39
+ "@tradejs/node": "^3.1.8-beta.204",
40
40
  "@tradejs/strategy-kit": "^3.0.0",
41
- "@tradejs/types": "^3.1.6",
41
+ "@tradejs/types": "^3.1.8-beta.204",
42
42
  "args": "^5.0.3",
43
43
  "bcryptjs": "^2.4.3",
44
44
  "chalk": "4.1.2",