@tradejs/cli 2.0.16 → 2.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -11865,10 +11865,11 @@ var init_hyperliquidRateLimiter = __esm({
11865
11865
  });
11866
11866
 
11867
11867
  // src/lib/hyperliquidWhaleBackfill.ts
11868
- var import_timescale4, import_strategies4, DEFAULT_BASE_URL, DEFAULT_CONCURRENCY, DEFAULT_RATE_LIMIT_WEIGHT, MAX_PAGE_SIZE, MAX_PAGES_PER_WHALE, REQUEST_WEIGHT, sleep3, positiveInt, minuteCeil, nextMinute, fetchHyperliquidUserFillsByTime, runConcurrent, backfillHyperliquidWhaleContext;
11868
+ var import_progress6, import_timescale4, import_strategies4, DEFAULT_BASE_URL, DEFAULT_CONCURRENCY, DEFAULT_RATE_LIMIT_WEIGHT, MAX_PAGE_SIZE, MAX_PAGES_PER_WHALE, REQUEST_WEIGHT, sleep3, positiveInt, minuteCeil, nextMinute, fetchHyperliquidUserFillsByTime, runConcurrent, backfillHyperliquidWhaleContext;
11869
11869
  var init_hyperliquidWhaleBackfill = __esm({
11870
11870
  "src/lib/hyperliquidWhaleBackfill.ts"() {
11871
11871
  "use strict";
11872
+ import_progress6 = __toESM(require("progress"));
11872
11873
  import_timescale4 = require("@tradejs/infra/timescale");
11873
11874
  import_strategies4 = require("@tradejs/node/strategies");
11874
11875
  init_hyperliquidWhaleData();
@@ -12094,11 +12095,36 @@ var init_hyperliquidWhaleBackfill = __esm({
12094
12095
  toMs,
12095
12096
  ...identity
12096
12097
  });
12098
+ const totalCoverageBuckets = Math.ceil(
12099
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
12100
+ );
12101
+ const coverageBar = new import_progress6.default(
12102
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
12103
+ {
12104
+ total: Math.max(1, totalCoverageBuckets),
12105
+ width: 24
12106
+ }
12107
+ );
12108
+ let displayedCoverageBuckets = 0;
12097
12109
  const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
12098
12110
  fromMs,
12099
12111
  toMs,
12100
12112
  expectedWhales: whales.addresses.length,
12101
- ...identity
12113
+ ...identity,
12114
+ onProgress: (progress) => {
12115
+ const next = Math.max(
12116
+ displayedCoverageBuckets,
12117
+ Math.min(progress.completedBuckets, coverageBar.total)
12118
+ );
12119
+ const delta = next - displayedCoverageBuckets;
12120
+ if (delta > 0) {
12121
+ coverageBar.tick(delta, {
12122
+ rows: progress.rows,
12123
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
12124
+ });
12125
+ displayedCoverageBuckets = next;
12126
+ }
12127
+ }
12102
12128
  });
12103
12129
  const result = {
12104
12130
  cached: false,
@@ -13490,14 +13516,31 @@ var init_runState = __esm({
13490
13516
  });
13491
13517
 
13492
13518
  // src/lib/backtest/workerPool.ts
13493
- var import_progress6, import_child_process, import_chalk13, import_node_crypto3, executeBacktestWorkerPool;
13519
+ var import_progress7, import_child_process, import_chalk13, import_node_crypto3, DEFAULT_PG_POOL_MAX, FAST_AI_PG_CONNECTION_BUDGET, MIN_FAST_AI_WORKER_PG_POOL_MAX, resolveFastAiWorkerPgPoolMax, executeBacktestWorkerPool;
13494
13520
  var init_workerPool = __esm({
13495
13521
  "src/lib/backtest/workerPool.ts"() {
13496
13522
  "use strict";
13497
- import_progress6 = __toESM(require("progress"));
13523
+ import_progress7 = __toESM(require("progress"));
13498
13524
  import_child_process = require("child_process");
13499
13525
  import_chalk13 = __toESM(require("chalk"));
13500
13526
  import_node_crypto3 = require("crypto");
13527
+ DEFAULT_PG_POOL_MAX = 10;
13528
+ FAST_AI_PG_CONNECTION_BUDGET = 18;
13529
+ MIN_FAST_AI_WORKER_PG_POOL_MAX = 3;
13530
+ resolveFastAiWorkerPgPoolMax = (testSuite, workerCount, configuredPoolMax) => {
13531
+ if (configuredPoolMax?.trim() || workerCount <= 1 || testSuite.length === 0 || testSuite.some((test) => !test.fast || !test.ai)) {
13532
+ return void 0;
13533
+ }
13534
+ return String(
13535
+ Math.min(
13536
+ DEFAULT_PG_POOL_MAX,
13537
+ Math.max(
13538
+ MIN_FAST_AI_WORKER_PG_POOL_MAX,
13539
+ Math.floor(FAST_AI_PG_CONNECTION_BUDGET / workerCount)
13540
+ )
13541
+ )
13542
+ );
13543
+ };
13501
13544
  executeBacktestWorkerPool = async ({
13502
13545
  testSuite,
13503
13546
  userName: userName2,
@@ -13516,6 +13559,12 @@ var init_workerPool = __esm({
13516
13559
  totalTests
13517
13560
  }) => {
13518
13561
  const chunks = chunkTestSuite(testSuite);
13562
+ const fastAiWorkerPgPoolMax = resolveFastAiWorkerPgPoolMax(
13563
+ testSuite,
13564
+ chunks.length,
13565
+ process.env.PG_POOL_MAX
13566
+ );
13567
+ const workerEnv = fastAiWorkerPgPoolMax ? { ...process.env, PG_POOL_MAX: fastAiWorkerPgPoolMax } : void 0;
13519
13568
  const totalExpectedTests = Math.max(
13520
13569
  testSuite.length,
13521
13570
  totalTests ?? testSuite.length,
@@ -13573,7 +13622,7 @@ var init_workerPool = __esm({
13573
13622
  console.log(line);
13574
13623
  }
13575
13624
  console.log("");
13576
- const bar = new import_progress6.default(
13625
+ const bar = new import_progress7.default(
13577
13626
  ":current/:total [:bar][:percent] avg :amount win :winRate trades :trades :eta(s)",
13578
13627
  {
13579
13628
  total: totalExpectedTests,
@@ -13601,6 +13650,7 @@ var init_workerPool = __esm({
13601
13650
  const chunkId = runId ? `${runId}-${attemptId}` : attemptId;
13602
13651
  const chunkWithId = chunk.map((test) => ({ ...test, chunkId }));
13603
13652
  const tester = (0, import_child_process.fork)(testerWorkerPath, [], {
13653
+ ...workerEnv ? { env: workerEnv } : {},
13604
13654
  execArgv: testerNeedsTsRuntime ? [
13605
13655
  `--max-old-space-size=${workerHeapMb2}`,
13606
13656
  "-r",
@@ -20833,12 +20883,12 @@ var continuity_exports = {};
20833
20883
  __export(continuity_exports, {
20834
20884
  main: () => main13
20835
20885
  });
20836
- var import_args12, import_progress7, import_chalk20, import_connectors10, import_cli8, import_constants11, import_time5, import_logger2, import_timescale7, flags12, interval2, intervalKey, projectRoot5, parseProviders, runContinuity, main13;
20886
+ var import_args12, import_progress8, import_chalk20, import_connectors10, import_cli8, import_constants11, import_time5, import_logger2, import_timescale7, flags12, interval2, intervalKey, projectRoot5, parseProviders, runContinuity, main13;
20837
20887
  var init_continuity2 = __esm({
20838
20888
  "src/scripts/continuity.ts"() {
20839
20889
  "use strict";
20840
20890
  import_args12 = __toESM(require("args"));
20841
- import_progress7 = __toESM(require("progress"));
20891
+ import_progress8 = __toESM(require("progress"));
20842
20892
  import_chalk20 = __toESM(require("chalk"));
20843
20893
  import_connectors10 = require("@tradejs/node/connectors");
20844
20894
  import_cli8 = require("@tradejs/node/cli");
@@ -20895,7 +20945,7 @@ var init_continuity2 = __esm({
20895
20945
  void 0,
20896
20946
  { universe }
20897
20947
  );
20898
- const bar = new import_progress7.default(
20948
+ const bar = new import_progress8.default(
20899
20949
  ":current/:total [:bar][:percent] broken::broken fixed::fixed :eta(s) :symbol",
20900
20950
  {
20901
20951
  total: tickers.length,
@@ -21149,14 +21199,14 @@ var derivativesIngestCoinalyzeAll_exports = {};
21149
21199
  __export(derivativesIngestCoinalyzeAll_exports, {
21150
21200
  main: () => main15
21151
21201
  });
21152
- var import_config5, import_args14, import_chalk22, import_progress8, import_lodash2, import_connectors12, import_indicators3, import_async4, import_userSettings5, import_cli9, import_timescale9, coinalyzeIntervalMap2, flags14, asInt6, parseList2, coinalyzeBaseUrl, coinalyzeMaxRetries, lastRequestTs3, fetchJsonWithRateLimit2, fetchCoinalyzeMarkets2, selectBestMarket2, buildMatches2, normalizeMetricPoint2, toSeriesMap2, fetchMetricBatch2, main15;
21202
+ var import_config5, import_args14, import_chalk22, import_progress9, import_lodash2, import_connectors12, import_indicators3, import_async4, import_userSettings5, import_cli9, import_timescale9, coinalyzeIntervalMap2, flags14, asInt6, parseList2, coinalyzeBaseUrl, coinalyzeMaxRetries, lastRequestTs3, fetchJsonWithRateLimit2, fetchCoinalyzeMarkets2, selectBestMarket2, buildMatches2, normalizeMetricPoint2, toSeriesMap2, fetchMetricBatch2, main15;
21153
21203
  var init_derivativesIngestCoinalyzeAll = __esm({
21154
21204
  "src/scripts/derivativesIngestCoinalyzeAll.ts"() {
21155
21205
  "use strict";
21156
21206
  import_config5 = require("dotenv/config");
21157
21207
  import_args14 = __toESM(require("args"));
21158
21208
  import_chalk22 = __toESM(require("chalk"));
21159
- import_progress8 = __toESM(require("progress"));
21209
+ import_progress9 = __toESM(require("progress"));
21160
21210
  import_lodash2 = __toESM(require("lodash"));
21161
21211
  import_connectors12 = require("@tradejs/connectors");
21162
21212
  import_indicators3 = require("@tradejs/core/indicators");
@@ -21433,7 +21483,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
21433
21483
  const symbolBatches = import_lodash2.default.chunk(matches, symbolBatchSize);
21434
21484
  const windowsPerPair = Math.ceil(days / batchDays);
21435
21485
  const totalWindows = symbolBatches.length * intervals.length * windowsPerPair;
21436
- const bar = new import_progress8.default(
21486
+ const bar = new import_progress9.default(
21437
21487
  ":current/:total [:bar][:percent] :eta(s) :batch rows=:rows fail=:fail",
21438
21488
  {
21439
21489
  total: Math.max(1, totalWindows),
@@ -22731,11 +22781,11 @@ var migration_exports = {};
22731
22781
  __export(migration_exports, {
22732
22782
  main: () => main22
22733
22783
  });
22734
- var import_progress9, import_chalk30, import_logger3, import_files, import_timescale11, DIR, re, BATCH, projectRoot7, migrateFile, main22;
22784
+ var import_progress10, import_chalk30, import_logger3, import_files, import_timescale11, DIR, re, BATCH, projectRoot7, migrateFile, main22;
22735
22785
  var init_migration = __esm({
22736
22786
  "src/scripts/migration.ts"() {
22737
22787
  "use strict";
22738
- import_progress9 = __toESM(require("progress"));
22788
+ import_progress10 = __toESM(require("progress"));
22739
22789
  import_chalk30 = __toESM(require("chalk"));
22740
22790
  import_logger3 = require("@tradejs/infra/logger");
22741
22791
  import_files = require("@tradejs/infra/files");
@@ -22762,7 +22812,7 @@ var init_migration = __esm({
22762
22812
  };
22763
22813
  main22 = async () => {
22764
22814
  const files = await (0, import_files.getFiles)(DIR, projectRoot7);
22765
- const bar = new import_progress9.default(
22815
+ const bar = new import_progress10.default(
22766
22816
  ":current/:total [:bar][:percent] :eta(s) :file",
22767
22817
  {
22768
22818
  total: files.length,
@@ -32232,13 +32282,13 @@ __export(signals_exports, {
32232
32282
  signalsConfiguredScopesOnce: () => signalsConfiguredScopesOnce,
32233
32283
  signalsDaemon: () => signalsDaemon
32234
32284
  });
32235
- var import_config11, import_args31, import_progress10, import_chalk43, import_connectors16, import_cli12, import_async5, import_strategies13, import_constants16, import_strategies14, import_time8, import_logger10, import_tradingAccounts3, SLOW_SIGNALS_WARNING_MS, projectRoot14, flags30, interval4, intervalMs, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, resolveSignalsDaemonMaxLiveBars, isSignalsKlineWsEnabled, resolveSignalsKlineWsWaitMs, createDefaultSignalsLifecycle, timeOperation3, formatSlowSignalsWarning, resolveSignalsConnectorName, createSignalsSession, findSignals, signals, loadConfiguredSignalsScopes, hasExplicitSignalsScope, signalsConfiguredScopesOnce, signalsDaemon, main38;
32285
+ var import_config11, import_args31, import_progress11, import_chalk43, import_connectors16, import_cli12, import_async5, import_strategies13, import_constants16, import_strategies14, import_time8, import_logger10, import_tradingAccounts3, SLOW_SIGNALS_WARNING_MS, projectRoot14, flags30, interval4, intervalMs, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, resolveSignalsDaemonMaxLiveBars, isSignalsKlineWsEnabled, resolveSignalsKlineWsWaitMs, createDefaultSignalsLifecycle, timeOperation3, formatSlowSignalsWarning, resolveSignalsConnectorName, createSignalsSession, findSignals, signals, loadConfiguredSignalsScopes, hasExplicitSignalsScope, signalsConfiguredScopesOnce, signalsDaemon, main38;
32236
32286
  var init_signals = __esm({
32237
32287
  "src/scripts/signals.ts"() {
32238
32288
  "use strict";
32239
32289
  import_config11 = require("dotenv/config");
32240
32290
  import_args31 = __toESM(require("args"));
32241
- import_progress10 = __toESM(require("progress"));
32291
+ import_progress11 = __toESM(require("progress"));
32242
32292
  import_chalk43 = __toESM(require("chalk"));
32243
32293
  import_connectors16 = require("@tradejs/node/connectors");
32244
32294
  import_cli12 = require("@tradejs/node/cli");
@@ -32885,7 +32935,7 @@ var init_signals = __esm({
32885
32935
  return;
32886
32936
  }
32887
32937
  const strategyStats = createStrategySkipStats(runtimeStrategies);
32888
- const bar = new import_progress10.default(
32938
+ const bar = new import_progress11.default(
32889
32939
  ":current/:total [:bar][:percent] :found :eta(s) :symbol",
32890
32940
  {
32891
32941
  total: tickers.length,
@@ -33712,12 +33762,12 @@ var init_portfolioReplayConnector = __esm({
33712
33762
  });
33713
33763
 
33714
33764
  // src/lib/replay/historicalSignalsReplay.ts
33715
- var import_chalk44, import_progress11, import_backtest4, import_strategies15, import_time9, import_logger11, import_redis20, import_connectors17, import_cli13, import_strategies16, loadRuntimeStrategies2, loadReferenceConnector, buildPreparedData, buildAfterSignalsContext, buildSymbolSharedReplayKey, runHistoricalSignalsReplay;
33765
+ var import_chalk44, import_progress12, import_backtest4, import_strategies15, import_time9, import_logger11, import_redis20, import_connectors17, import_cli13, import_strategies16, loadRuntimeStrategies2, loadReferenceConnector, buildPreparedData, buildAfterSignalsContext, buildSymbolSharedReplayKey, runHistoricalSignalsReplay;
33716
33766
  var init_historicalSignalsReplay = __esm({
33717
33767
  "src/lib/replay/historicalSignalsReplay.ts"() {
33718
33768
  "use strict";
33719
33769
  import_chalk44 = __toESM(require("chalk"));
33720
- import_progress11 = __toESM(require("progress"));
33770
+ import_progress12 = __toESM(require("progress"));
33721
33771
  import_backtest4 = require("@tradejs/core/backtest");
33722
33772
  import_strategies15 = require("@tradejs/core/strategies");
33723
33773
  import_time9 = require("@tradejs/core/time");
@@ -33897,7 +33947,7 @@ var init_historicalSignalsReplay = __esm({
33897
33947
  const sharedReplayKeyPrefixes = [];
33898
33948
  let preparedSymbols = 0;
33899
33949
  let skippedSymbols = 0;
33900
- const prepareBar = new import_progress11.default(
33950
+ const prepareBar = new import_progress12.default(
33901
33951
  "prepare :current/:total [:bar][:percent] skipped=:skipped :etas(s) :symbol",
33902
33952
  {
33903
33953
  total: preparedRun.tickers.length,
@@ -34019,7 +34069,7 @@ var init_historicalSignalsReplay = __esm({
34019
34069
  interval: interval5
34020
34070
  });
34021
34071
  let abortedCycles = 0;
34022
- const cycleBar = new import_progress11.default(
34072
+ const cycleBar = new import_progress12.default(
34023
34073
  "cycles :current/:total [:bar][:percent] sig=:signals abort=:aborted :etas(s) :ts",
34024
34074
  {
34025
34075
  total: orderedTimestamps.length,
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/lib/hyperliquidWhaleBackfill.ts
@@ -24,6 +34,7 @@ __export(hyperliquidWhaleBackfill_exports, {
24
34
  fetchHyperliquidUserFillsByTime: () => fetchHyperliquidUserFillsByTime
25
35
  });
26
36
  module.exports = __toCommonJS(hyperliquidWhaleBackfill_exports);
37
+ var import_progress = __toESM(require("progress"));
27
38
  var import_timescale = require("@tradejs/infra/timescale");
28
39
  var import_strategies = require("@tradejs/node/strategies");
29
40
 
@@ -398,11 +409,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
398
409
  toMs,
399
410
  ...identity
400
411
  });
412
+ const totalCoverageBuckets = Math.ceil(
413
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
414
+ );
415
+ const coverageBar = new import_progress.default(
416
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
417
+ {
418
+ total: Math.max(1, totalCoverageBuckets),
419
+ width: 24
420
+ }
421
+ );
422
+ let displayedCoverageBuckets = 0;
401
423
  const coverageBuckets = await (0, import_timescale.rebuildHyperliquidWhaleCoverageRows)({
402
424
  fromMs,
403
425
  toMs,
404
426
  expectedWhales: whales.addresses.length,
405
- ...identity
427
+ ...identity,
428
+ onProgress: (progress) => {
429
+ const next = Math.max(
430
+ displayedCoverageBuckets,
431
+ Math.min(progress.completedBuckets, coverageBar.total)
432
+ );
433
+ const delta = next - displayedCoverageBuckets;
434
+ if (delta > 0) {
435
+ coverageBar.tick(delta, {
436
+ rows: progress.rows,
437
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
438
+ });
439
+ displayedCoverageBuckets = next;
440
+ }
441
+ }
406
442
  });
407
443
  const result = {
408
444
  cached: false,
@@ -4501,6 +4501,7 @@ var timeOperation = async (label, operation, log = console.log) => {
4501
4501
  };
4502
4502
 
4503
4503
  // src/lib/hyperliquidWhaleBackfill.ts
4504
+ var import_progress3 = __toESM(require("progress"));
4504
4505
  var import_timescale4 = require("@tradejs/infra/timescale");
4505
4506
  var import_strategies2 = require("@tradejs/node/strategies");
4506
4507
 
@@ -4875,11 +4876,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
4875
4876
  toMs,
4876
4877
  ...identity
4877
4878
  });
4879
+ const totalCoverageBuckets = Math.ceil(
4880
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
4881
+ );
4882
+ const coverageBar = new import_progress3.default(
4883
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
4884
+ {
4885
+ total: Math.max(1, totalCoverageBuckets),
4886
+ width: 24
4887
+ }
4888
+ );
4889
+ let displayedCoverageBuckets = 0;
4878
4890
  const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
4879
4891
  fromMs,
4880
4892
  toMs,
4881
4893
  expectedWhales: whales.addresses.length,
4882
- ...identity
4894
+ ...identity,
4895
+ onProgress: (progress) => {
4896
+ const next = Math.max(
4897
+ displayedCoverageBuckets,
4898
+ Math.min(progress.completedBuckets, coverageBar.total)
4899
+ );
4900
+ const delta = next - displayedCoverageBuckets;
4901
+ if (delta > 0) {
4902
+ coverageBar.tick(delta, {
4903
+ rows: progress.rows,
4904
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
4905
+ });
4906
+ displayedCoverageBuckets = next;
4907
+ }
4908
+ }
4883
4909
  });
4884
4910
  const result = {
4885
4911
  cached: false,
@@ -4542,6 +4542,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
4542
4542
  var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
4543
4543
 
4544
4544
  // src/lib/hyperliquidWhaleBackfill.ts
4545
+ var import_progress3 = __toESM(require("progress"));
4545
4546
  var import_timescale4 = require("@tradejs/infra/timescale");
4546
4547
  var import_strategies2 = require("@tradejs/node/strategies");
4547
4548
 
@@ -4916,11 +4917,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
4916
4917
  toMs,
4917
4918
  ...identity
4918
4919
  });
4920
+ const totalCoverageBuckets = Math.ceil(
4921
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
4922
+ );
4923
+ const coverageBar = new import_progress3.default(
4924
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
4925
+ {
4926
+ total: Math.max(1, totalCoverageBuckets),
4927
+ width: 24
4928
+ }
4929
+ );
4930
+ let displayedCoverageBuckets = 0;
4919
4931
  const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
4920
4932
  fromMs,
4921
4933
  toMs,
4922
4934
  expectedWhales: whales.addresses.length,
4923
- ...identity
4935
+ ...identity,
4936
+ onProgress: (progress) => {
4937
+ const next = Math.max(
4938
+ displayedCoverageBuckets,
4939
+ Math.min(progress.completedBuckets, coverageBar.total)
4940
+ );
4941
+ const delta = next - displayedCoverageBuckets;
4942
+ if (delta > 0) {
4943
+ coverageBar.tick(delta, {
4944
+ rows: progress.rows,
4945
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
4946
+ });
4947
+ displayedCoverageBuckets = next;
4948
+ }
4949
+ }
4924
4950
  });
4925
4951
  const result = {
4926
4952
  cached: false,
@@ -6273,10 +6299,27 @@ var resetRunState = () => {
6273
6299
  };
6274
6300
 
6275
6301
  // src/lib/backtest/workerPool.ts
6276
- var import_progress3 = __toESM(require("progress"));
6302
+ var import_progress4 = __toESM(require("progress"));
6277
6303
  var import_child_process = require("child_process");
6278
6304
  var import_chalk8 = __toESM(require("chalk"));
6279
6305
  var import_node_crypto2 = require("crypto");
6306
+ var DEFAULT_PG_POOL_MAX = 10;
6307
+ var FAST_AI_PG_CONNECTION_BUDGET = 18;
6308
+ var MIN_FAST_AI_WORKER_PG_POOL_MAX = 3;
6309
+ var resolveFastAiWorkerPgPoolMax = (testSuite, workerCount, configuredPoolMax) => {
6310
+ if (configuredPoolMax?.trim() || workerCount <= 1 || testSuite.length === 0 || testSuite.some((test) => !test.fast || !test.ai)) {
6311
+ return void 0;
6312
+ }
6313
+ return String(
6314
+ Math.min(
6315
+ DEFAULT_PG_POOL_MAX,
6316
+ Math.max(
6317
+ MIN_FAST_AI_WORKER_PG_POOL_MAX,
6318
+ Math.floor(FAST_AI_PG_CONNECTION_BUDGET / workerCount)
6319
+ )
6320
+ )
6321
+ );
6322
+ };
6280
6323
  var executeBacktestWorkerPool = async ({
6281
6324
  testSuite,
6282
6325
  userName: userName2,
@@ -6295,6 +6338,12 @@ var executeBacktestWorkerPool = async ({
6295
6338
  totalTests
6296
6339
  }) => {
6297
6340
  const chunks = chunkTestSuite(testSuite);
6341
+ const fastAiWorkerPgPoolMax = resolveFastAiWorkerPgPoolMax(
6342
+ testSuite,
6343
+ chunks.length,
6344
+ process.env.PG_POOL_MAX
6345
+ );
6346
+ const workerEnv = fastAiWorkerPgPoolMax ? { ...process.env, PG_POOL_MAX: fastAiWorkerPgPoolMax } : void 0;
6298
6347
  const totalExpectedTests = Math.max(
6299
6348
  testSuite.length,
6300
6349
  totalTests ?? testSuite.length,
@@ -6352,7 +6401,7 @@ var executeBacktestWorkerPool = async ({
6352
6401
  console.log(line);
6353
6402
  }
6354
6403
  console.log("");
6355
- const bar = new import_progress3.default(
6404
+ const bar = new import_progress4.default(
6356
6405
  ":current/:total [:bar][:percent] avg :amount win :winRate trades :trades :eta(s)",
6357
6406
  {
6358
6407
  total: totalExpectedTests,
@@ -6380,6 +6429,7 @@ var executeBacktestWorkerPool = async ({
6380
6429
  const chunkId = runId ? `${runId}-${attemptId}` : attemptId;
6381
6430
  const chunkWithId = chunk.map((test) => ({ ...test, chunkId }));
6382
6431
  const tester = (0, import_child_process.fork)(testerWorkerPath, [], {
6432
+ ...workerEnv ? { env: workerEnv } : {},
6383
6433
  execArgv: testerNeedsTsRuntime ? [
6384
6434
  `--max-old-space-size=${workerHeapMb2}`,
6385
6435
  "-r",
@@ -36,6 +36,7 @@ module.exports = __toCommonJS(hyperliquidWhaleBackfill_exports);
36
36
  var import_args = __toESM(require("args"));
37
37
 
38
38
  // src/lib/hyperliquidWhaleBackfill.ts
39
+ var import_progress = __toESM(require("progress"));
39
40
  var import_timescale = require("@tradejs/infra/timescale");
40
41
  var import_strategies = require("@tradejs/node/strategies");
41
42
 
@@ -410,11 +411,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
410
411
  toMs,
411
412
  ...identity
412
413
  });
414
+ const totalCoverageBuckets = Math.ceil(
415
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
416
+ );
417
+ const coverageBar = new import_progress.default(
418
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
419
+ {
420
+ total: Math.max(1, totalCoverageBuckets),
421
+ width: 24
422
+ }
423
+ );
424
+ let displayedCoverageBuckets = 0;
413
425
  const coverageBuckets = await (0, import_timescale.rebuildHyperliquidWhaleCoverageRows)({
414
426
  fromMs,
415
427
  toMs,
416
428
  expectedWhales: whales.addresses.length,
417
- ...identity
429
+ ...identity,
430
+ onProgress: (progress) => {
431
+ const next = Math.max(
432
+ displayedCoverageBuckets,
433
+ Math.min(progress.completedBuckets, coverageBar.total)
434
+ );
435
+ const delta = next - displayedCoverageBuckets;
436
+ if (delta > 0) {
437
+ coverageBar.tick(delta, {
438
+ rows: progress.rows,
439
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
440
+ });
441
+ displayedCoverageBuckets = next;
442
+ }
443
+ }
418
444
  });
419
445
  const result = {
420
446
  cached: false,
@@ -39,6 +39,7 @@ var import_node_crypto = require("crypto");
39
39
  var import_strategies2 = require("@tradejs/node/strategies");
40
40
 
41
41
  // src/lib/hyperliquidWhaleBackfill.ts
42
+ var import_progress = __toESM(require("progress"));
42
43
  var import_timescale = require("@tradejs/infra/timescale");
43
44
  var import_strategies = require("@tradejs/node/strategies");
44
45
 
@@ -5183,6 +5183,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
5183
5183
  var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
5184
5184
 
5185
5185
  // src/lib/hyperliquidWhaleBackfill.ts
5186
+ var import_progress3 = __toESM(require("progress"));
5186
5187
  var import_timescale4 = require("@tradejs/infra/timescale");
5187
5188
  var import_strategies2 = require("@tradejs/node/strategies");
5188
5189
 
@@ -5557,11 +5558,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
5557
5558
  toMs,
5558
5559
  ...identity
5559
5560
  });
5561
+ const totalCoverageBuckets = Math.ceil(
5562
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
5563
+ );
5564
+ const coverageBar = new import_progress3.default(
5565
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
5566
+ {
5567
+ total: Math.max(1, totalCoverageBuckets),
5568
+ width: 24
5569
+ }
5570
+ );
5571
+ let displayedCoverageBuckets = 0;
5560
5572
  const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
5561
5573
  fromMs,
5562
5574
  toMs,
5563
5575
  expectedWhales: whales.addresses.length,
5564
- ...identity
5576
+ ...identity,
5577
+ onProgress: (progress) => {
5578
+ const next = Math.max(
5579
+ displayedCoverageBuckets,
5580
+ Math.min(progress.completedBuckets, coverageBar.total)
5581
+ );
5582
+ const delta = next - displayedCoverageBuckets;
5583
+ if (delta > 0) {
5584
+ coverageBar.tick(delta, {
5585
+ rows: progress.rows,
5586
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
5587
+ });
5588
+ displayedCoverageBuckets = next;
5589
+ }
5590
+ }
5565
5591
  });
5566
5592
  const result = {
5567
5593
  cached: false,
@@ -6059,7 +6085,7 @@ var compactReplaySignal = (signal) => {
6059
6085
 
6060
6086
  // src/lib/replay/historicalSignalsReplay.ts
6061
6087
  var import_chalk9 = __toESM(require("chalk"));
6062
- var import_progress3 = __toESM(require("progress"));
6088
+ var import_progress4 = __toESM(require("progress"));
6063
6089
  var import_backtest = require("@tradejs/core/backtest");
6064
6090
  var import_strategies4 = require("@tradejs/core/strategies");
6065
6091
  var import_time3 = require("@tradejs/core/time");
@@ -6943,7 +6969,7 @@ var runHistoricalSignalsReplay = async ({
6943
6969
  const sharedReplayKeyPrefixes = [];
6944
6970
  let preparedSymbols = 0;
6945
6971
  let skippedSymbols = 0;
6946
- const prepareBar = new import_progress3.default(
6972
+ const prepareBar = new import_progress4.default(
6947
6973
  "prepare :current/:total [:bar][:percent] skipped=:skipped :etas(s) :symbol",
6948
6974
  {
6949
6975
  total: preparedRun.tickers.length,
@@ -7065,7 +7091,7 @@ var runHistoricalSignalsReplay = async ({
7065
7091
  interval
7066
7092
  });
7067
7093
  let abortedCycles = 0;
7068
- const cycleBar = new import_progress3.default(
7094
+ const cycleBar = new import_progress4.default(
7069
7095
  "cycles :current/:total [:bar][:percent] sig=:signals abort=:aborted :etas(s) :ts",
7070
7096
  {
7071
7097
  total: orderedTimestamps.length,
@@ -5186,6 +5186,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
5186
5186
  var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
5187
5187
 
5188
5188
  // src/lib/hyperliquidWhaleBackfill.ts
5189
+ var import_progress3 = __toESM(require("progress"));
5189
5190
  var import_timescale4 = require("@tradejs/infra/timescale");
5190
5191
  var import_strategies2 = require("@tradejs/node/strategies");
5191
5192
 
@@ -5560,11 +5561,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
5560
5561
  toMs,
5561
5562
  ...identity
5562
5563
  });
5564
+ const totalCoverageBuckets = Math.ceil(
5565
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
5566
+ );
5567
+ const coverageBar = new import_progress3.default(
5568
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
5569
+ {
5570
+ total: Math.max(1, totalCoverageBuckets),
5571
+ width: 24
5572
+ }
5573
+ );
5574
+ let displayedCoverageBuckets = 0;
5563
5575
  const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
5564
5576
  fromMs,
5565
5577
  toMs,
5566
5578
  expectedWhales: whales.addresses.length,
5567
- ...identity
5579
+ ...identity,
5580
+ onProgress: (progress) => {
5581
+ const next = Math.max(
5582
+ displayedCoverageBuckets,
5583
+ Math.min(progress.completedBuckets, coverageBar.total)
5584
+ );
5585
+ const delta = next - displayedCoverageBuckets;
5586
+ if (delta > 0) {
5587
+ coverageBar.tick(delta, {
5588
+ rows: progress.rows,
5589
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
5590
+ });
5591
+ displayedCoverageBuckets = next;
5592
+ }
5593
+ }
5568
5594
  });
5569
5595
  const result = {
5570
5596
  cached: false,
@@ -6062,7 +6088,7 @@ var compactReplaySignal = (signal) => {
6062
6088
 
6063
6089
  // src/lib/replay/historicalSignalsReplay.ts
6064
6090
  var import_chalk9 = __toESM(require("chalk"));
6065
- var import_progress3 = __toESM(require("progress"));
6091
+ var import_progress4 = __toESM(require("progress"));
6066
6092
  var import_backtest = require("@tradejs/core/backtest");
6067
6093
  var import_strategies4 = require("@tradejs/core/strategies");
6068
6094
  var import_time3 = require("@tradejs/core/time");
@@ -6946,7 +6972,7 @@ var runHistoricalSignalsReplay = async ({
6946
6972
  const sharedReplayKeyPrefixes = [];
6947
6973
  let preparedSymbols = 0;
6948
6974
  let skippedSymbols = 0;
6949
- const prepareBar = new import_progress3.default(
6975
+ const prepareBar = new import_progress4.default(
6950
6976
  "prepare :current/:total [:bar][:percent] skipped=:skipped :etas(s) :symbol",
6951
6977
  {
6952
6978
  total: preparedRun.tickers.length,
@@ -7068,7 +7094,7 @@ var runHistoricalSignalsReplay = async ({
7068
7094
  interval
7069
7095
  });
7070
7096
  let abortedCycles = 0;
7071
- const cycleBar = new import_progress3.default(
7097
+ const cycleBar = new import_progress4.default(
7072
7098
  "cycles :current/:total [:bar][:percent] sig=:signals abort=:aborted :etas(s) :ts",
7073
7099
  {
7074
7100
  total: orderedTimestamps.length,
@@ -5188,6 +5188,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
5188
5188
  var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
5189
5189
 
5190
5190
  // src/lib/hyperliquidWhaleBackfill.ts
5191
+ var import_progress3 = __toESM(require("progress"));
5191
5192
  var import_timescale4 = require("@tradejs/infra/timescale");
5192
5193
  var import_strategies2 = require("@tradejs/node/strategies");
5193
5194
 
@@ -5562,11 +5563,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
5562
5563
  toMs,
5563
5564
  ...identity
5564
5565
  });
5566
+ const totalCoverageBuckets = Math.ceil(
5567
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
5568
+ );
5569
+ const coverageBar = new import_progress3.default(
5570
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
5571
+ {
5572
+ total: Math.max(1, totalCoverageBuckets),
5573
+ width: 24
5574
+ }
5575
+ );
5576
+ let displayedCoverageBuckets = 0;
5565
5577
  const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
5566
5578
  fromMs,
5567
5579
  toMs,
5568
5580
  expectedWhales: whales.addresses.length,
5569
- ...identity
5581
+ ...identity,
5582
+ onProgress: (progress) => {
5583
+ const next = Math.max(
5584
+ displayedCoverageBuckets,
5585
+ Math.min(progress.completedBuckets, coverageBar.total)
5586
+ );
5587
+ const delta = next - displayedCoverageBuckets;
5588
+ if (delta > 0) {
5589
+ coverageBar.tick(delta, {
5590
+ rows: progress.rows,
5591
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
5592
+ });
5593
+ displayedCoverageBuckets = next;
5594
+ }
5595
+ }
5570
5596
  });
5571
5597
  const result = {
5572
5598
  cached: false,
@@ -1645,7 +1645,7 @@ __export(signals_exports, {
1645
1645
  module.exports = __toCommonJS(signals_exports);
1646
1646
  var import_config = require("dotenv/config");
1647
1647
  var import_args = __toESM(require("args"));
1648
- var import_progress3 = __toESM(require("progress"));
1648
+ var import_progress4 = __toESM(require("progress"));
1649
1649
  var import_chalk7 = __toESM(require("chalk"));
1650
1650
  var import_connectors6 = require("@tradejs/node/connectors");
1651
1651
  var import_cli2 = require("@tradejs/node/cli");
@@ -4553,6 +4553,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
4553
4553
  var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
4554
4554
 
4555
4555
  // src/lib/hyperliquidWhaleBackfill.ts
4556
+ var import_progress3 = __toESM(require("progress"));
4556
4557
  var import_timescale4 = require("@tradejs/infra/timescale");
4557
4558
  var import_strategies2 = require("@tradejs/node/strategies");
4558
4559
 
@@ -4927,11 +4928,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
4927
4928
  toMs,
4928
4929
  ...identity
4929
4930
  });
4931
+ const totalCoverageBuckets = Math.ceil(
4932
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
4933
+ );
4934
+ const coverageBar = new import_progress3.default(
4935
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
4936
+ {
4937
+ total: Math.max(1, totalCoverageBuckets),
4938
+ width: 24
4939
+ }
4940
+ );
4941
+ let displayedCoverageBuckets = 0;
4930
4942
  const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
4931
4943
  fromMs,
4932
4944
  toMs,
4933
4945
  expectedWhales: whales.addresses.length,
4934
- ...identity
4946
+ ...identity,
4947
+ onProgress: (progress) => {
4948
+ const next = Math.max(
4949
+ displayedCoverageBuckets,
4950
+ Math.min(progress.completedBuckets, coverageBar.total)
4951
+ );
4952
+ const delta = next - displayedCoverageBuckets;
4953
+ if (delta > 0) {
4954
+ coverageBar.tick(delta, {
4955
+ rows: progress.rows,
4956
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
4957
+ });
4958
+ displayedCoverageBuckets = next;
4959
+ }
4960
+ }
4935
4961
  });
4936
4962
  const result = {
4937
4963
  cached: false,
@@ -7029,7 +7055,7 @@ var signals = async (options = {}) => {
7029
7055
  return;
7030
7056
  }
7031
7057
  const strategyStats = createStrategySkipStats(runtimeStrategies);
7032
- const bar = new import_progress3.default(
7058
+ const bar = new import_progress4.default(
7033
7059
  ":current/:total [:bar][:percent] :found :eta(s) :symbol",
7034
7060
  {
7035
7061
  total: tickers.length,
@@ -1643,7 +1643,7 @@ module.exports = __toCommonJS(signalsDaemon_exports);
1643
1643
  // src/scripts/signals.ts
1644
1644
  var import_config = require("dotenv/config");
1645
1645
  var import_args = __toESM(require("args"));
1646
- var import_progress3 = __toESM(require("progress"));
1646
+ var import_progress4 = __toESM(require("progress"));
1647
1647
  var import_chalk7 = __toESM(require("chalk"));
1648
1648
  var import_connectors6 = require("@tradejs/node/connectors");
1649
1649
  var import_cli2 = require("@tradejs/node/cli");
@@ -4551,6 +4551,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
4551
4551
  var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
4552
4552
 
4553
4553
  // src/lib/hyperliquidWhaleBackfill.ts
4554
+ var import_progress3 = __toESM(require("progress"));
4554
4555
  var import_timescale4 = require("@tradejs/infra/timescale");
4555
4556
  var import_strategies2 = require("@tradejs/node/strategies");
4556
4557
 
@@ -4925,11 +4926,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
4925
4926
  toMs,
4926
4927
  ...identity
4927
4928
  });
4929
+ const totalCoverageBuckets = Math.ceil(
4930
+ (toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
4931
+ );
4932
+ const coverageBar = new import_progress3.default(
4933
+ "Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
4934
+ {
4935
+ total: Math.max(1, totalCoverageBuckets),
4936
+ width: 24
4937
+ }
4938
+ );
4939
+ let displayedCoverageBuckets = 0;
4928
4940
  const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
4929
4941
  fromMs,
4930
4942
  toMs,
4931
4943
  expectedWhales: whales.addresses.length,
4932
- ...identity
4944
+ ...identity,
4945
+ onProgress: (progress) => {
4946
+ const next = Math.max(
4947
+ displayedCoverageBuckets,
4948
+ Math.min(progress.completedBuckets, coverageBar.total)
4949
+ );
4950
+ const delta = next - displayedCoverageBuckets;
4951
+ if (delta > 0) {
4952
+ coverageBar.tick(delta, {
4953
+ rows: progress.rows,
4954
+ chunk: `${progress.chunkIndex}/${progress.totalChunks}`
4955
+ });
4956
+ displayedCoverageBuckets = next;
4957
+ }
4958
+ }
4933
4959
  });
4934
4960
  const result = {
4935
4961
  cached: false,
@@ -7027,7 +7053,7 @@ var signals = async (options = {}) => {
7027
7053
  return;
7028
7054
  }
7029
7055
  const strategyStats = createStrategySkipStats(runtimeStrategies);
7030
- const bar = new import_progress3.default(
7056
+ const bar = new import_progress4.default(
7031
7057
  ":current/:total [:bar][:percent] :found :eta(s) :symbol",
7032
7058
  {
7033
7059
  total: tickers.length,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/cli",
3
- "version": "2.0.16",
3
+ "version": "2.0.17",
4
4
  "description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
5
5
  "keywords": [
6
6
  "tradejs",
@@ -29,14 +29,14 @@
29
29
  "tradejs": "dist/cli.js"
30
30
  },
31
31
  "dependencies": {
32
- "@tradejs/base": "^2.0.16",
33
- "@tradejs/connectors": "^2.0.16",
34
- "@tradejs/core": "^2.0.16",
35
- "@tradejs/indicators": "^2.0.16",
36
- "@tradejs/infra": "^2.0.16",
37
- "@tradejs/node": "^2.0.16",
38
- "@tradejs/strategies": "^2.0.16",
39
- "@tradejs/types": "^2.0.16",
32
+ "@tradejs/base": "^2.0.17",
33
+ "@tradejs/connectors": "^2.0.17",
34
+ "@tradejs/core": "^2.0.17",
35
+ "@tradejs/indicators": "^2.0.17",
36
+ "@tradejs/infra": "^2.0.17",
37
+ "@tradejs/node": "^2.0.17",
38
+ "@tradejs/strategies": "^2.0.17",
39
+ "@tradejs/types": "^2.0.17",
40
40
  "args": "^5.0.3",
41
41
  "bcryptjs": "^2.4.3",
42
42
  "chalk": "4.1.2",