@tradejs/cli 1.0.5 → 1.0.6

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.
@@ -22,9 +22,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  mod
23
23
  ));
24
24
 
25
- // src/scripts/mlExportSelect.ts
26
- var import_child_process = require("child_process");
27
-
28
25
  // src/scripts/selectStrategy.ts
29
26
  var import_readline = __toESM(require("readline"));
30
27
  var import_chalk = __toESM(require("chalk"));
@@ -48,9 +45,10 @@ var getStrategyChoices = async () => {
48
45
  "VolumeDivergence"
49
46
  ];
50
47
  };
51
- var selectStrategy = async (promptLabel = "Select strategy") => {
52
- const strategies = await getStrategyChoices();
53
- const fallbackStrategy = strategies.includes(defaultStrategy) ? defaultStrategy : strategies[0];
48
+ var selectStrategy = async (promptLabel = "Select strategy", options) => {
49
+ const strategies = options?.strategies && options.strategies.length ? options.strategies : await getStrategyChoices();
50
+ const preferredDefault = options?.defaultStrategy || defaultStrategy;
51
+ const fallbackStrategy = strategies.includes(preferredDefault) ? preferredDefault : strategies[0];
54
52
  if (!process.stdin.isTTY) {
55
53
  return fallbackStrategy;
56
54
  }
@@ -88,12 +86,48 @@ var selectStrategy = async (promptLabel = "Select strategy") => {
88
86
  return fallbackStrategy;
89
87
  };
90
88
 
89
+ // src/scripts/spawnSiblingScript.ts
90
+ var import_fs = __toESM(require("fs"));
91
+ var import_path = __toESM(require("path"));
92
+ var import_child_process = require("child_process");
93
+ var spawnSiblingScript = (currentDir, scriptBaseName, extraArgs) => {
94
+ const searchDirs = [currentDir, import_path.default.resolve(currentDir, "scripts")];
95
+ const candidates = searchDirs.flatMap((dir) => [
96
+ import_path.default.resolve(dir, `${scriptBaseName}.js`),
97
+ import_path.default.resolve(dir, `${scriptBaseName}.ts`)
98
+ ]);
99
+ const scriptPath = candidates.find((candidate) => import_fs.default.existsSync(candidate));
100
+ if (!scriptPath) {
101
+ throw new Error(
102
+ `Script "${scriptBaseName}" not found. Checked: ${candidates.join(", ")}`
103
+ );
104
+ }
105
+ const commandArgs = scriptPath.endsWith(".ts") ? [
106
+ "-r",
107
+ "ts-node/register",
108
+ "-r",
109
+ "tsconfig-paths/register",
110
+ scriptPath,
111
+ ...extraArgs
112
+ ] : [scriptPath, ...extraArgs];
113
+ const result = (0, import_child_process.spawnSync)(process.execPath, commandArgs, {
114
+ env: process.env,
115
+ stdio: "inherit"
116
+ });
117
+ if (result.error) {
118
+ throw result.error;
119
+ }
120
+ return result.status ?? 1;
121
+ };
122
+
91
123
  // src/scripts/mlExportSelect.ts
92
124
  var run = async () => {
93
125
  const selected = await selectStrategy();
94
- const args = ["ts-node", "./src/scripts/mlExport", "--strategy", selected];
95
- const result = (0, import_child_process.spawnSync)("yarn", args, { stdio: "inherit" });
96
- process.exit(result.status ?? 1);
126
+ const status = spawnSiblingScript(__dirname, "mlExport", [
127
+ "--strategy",
128
+ selected
129
+ ]);
130
+ process.exit(status);
97
131
  };
98
132
  run().catch((err) => {
99
133
  console.error("Failed to select strategy:", err);
@@ -56,9 +56,10 @@ var getStrategyChoices = async () => {
56
56
  "VolumeDivergence"
57
57
  ];
58
58
  };
59
- var selectStrategy = async (promptLabel = "Select strategy") => {
60
- const strategies = await getStrategyChoices();
61
- const fallbackStrategy = strategies.includes(defaultStrategy) ? defaultStrategy : strategies[0];
59
+ var selectStrategy = async (promptLabel = "Select strategy", options) => {
60
+ const strategies = options?.strategies && options.strategies.length ? options.strategies : await getStrategyChoices();
61
+ const preferredDefault = options?.defaultStrategy || defaultStrategy;
62
+ const fallbackStrategy = strategies.includes(preferredDefault) ? preferredDefault : strategies[0];
62
63
  if (!process.stdin.isTTY) {
63
64
  return fallbackStrategy;
64
65
  }
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
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
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/scripts/resolveExportStrategy.ts
31
+ var resolveExportStrategy_exports = {};
32
+ __export(resolveExportStrategy_exports, {
33
+ resolveExportStrategy: () => resolveExportStrategy
34
+ });
35
+ module.exports = __toCommonJS(resolveExportStrategy_exports);
36
+
37
+ // src/scripts/selectStrategy.ts
38
+ var import_readline = __toESM(require("readline"));
39
+ var import_chalk = __toESM(require("chalk"));
40
+ var import_strategies = require("@tradejs/node/strategies");
41
+ var defaultStrategy = "TrendLine";
42
+ var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
43
+ var getStrategyChoices = async () => {
44
+ try {
45
+ const loaded = await (0, import_strategies.getAvailableStrategyNames)(projectRoot);
46
+ if (loaded.length) {
47
+ return loaded;
48
+ }
49
+ } catch (error) {
50
+ console.warn(`Failed to load strategy list: ${String(error)}`);
51
+ }
52
+ return [
53
+ "Breakout",
54
+ "MaStrategy",
55
+ "AdaptiveMomentumRibbon",
56
+ "TrendLine",
57
+ "VolumeDivergence"
58
+ ];
59
+ };
60
+ var selectStrategy = async (promptLabel = "Select strategy", options) => {
61
+ const strategies = options?.strategies && options.strategies.length ? options.strategies : await getStrategyChoices();
62
+ const preferredDefault = options?.defaultStrategy || defaultStrategy;
63
+ const fallbackStrategy = strategies.includes(preferredDefault) ? preferredDefault : strategies[0];
64
+ if (!process.stdin.isTTY) {
65
+ return fallbackStrategy;
66
+ }
67
+ console.log(import_chalk.default.cyan("Available strategies:"));
68
+ strategies.forEach((name, index) => {
69
+ const isDefault = name === defaultStrategy;
70
+ const label = isDefault ? import_chalk.default.green(name) : name;
71
+ const suffix = isDefault ? import_chalk.default.gray(" (default)") : "";
72
+ console.log(` ${import_chalk.default.yellow(String(index + 1))}) ${label}${suffix}`);
73
+ });
74
+ const rl = import_readline.default.createInterface({
75
+ input: process.stdin,
76
+ output: process.stdout
77
+ });
78
+ const question = (text) => new Promise((resolve) => rl.question(text, resolve));
79
+ const answer = await question(
80
+ `${promptLabel} [${import_chalk.default.green(fallbackStrategy)}]: `
81
+ );
82
+ rl.close();
83
+ const trimmed = answer.trim();
84
+ if (!trimmed) {
85
+ return fallbackStrategy;
86
+ }
87
+ const asNumber = Number(trimmed);
88
+ if (Number.isFinite(asNumber) && asNumber >= 1 && asNumber <= strategies.length) {
89
+ return strategies[asNumber - 1];
90
+ }
91
+ const byName = strategies.find(
92
+ (name) => name.toLowerCase() === trimmed.toLowerCase()
93
+ );
94
+ if (byName) {
95
+ return byName;
96
+ }
97
+ console.warn(`Unknown strategy "${trimmed}", using ${fallbackStrategy}.`);
98
+ return fallbackStrategy;
99
+ };
100
+
101
+ // src/scripts/resolveExportStrategy.ts
102
+ var resolveExportStrategy = async ({
103
+ explicitStrategy,
104
+ outDir,
105
+ datasetLabel,
106
+ promptLabel,
107
+ listStrategies
108
+ }) => {
109
+ const raw = String(explicitStrategy || "").trim();
110
+ if (raw) {
111
+ return raw;
112
+ }
113
+ const availableStrategies = await listStrategies({ outDir });
114
+ if (!availableStrategies.length) {
115
+ return null;
116
+ }
117
+ if (availableStrategies.length === 1) {
118
+ return availableStrategies[0];
119
+ }
120
+ if (!process.stdin.isTTY) {
121
+ throw new Error(
122
+ `Multiple ${datasetLabel} chunk strategies found in ${outDir}: ${availableStrategies.join(", ")}. Pass --strategy.`
123
+ );
124
+ }
125
+ return selectStrategy(promptLabel, {
126
+ strategies: availableStrategies,
127
+ defaultStrategy: availableStrategies[0]
128
+ });
129
+ };
130
+ // Annotate the CommonJS export names for ESM import in node:
131
+ 0 && (module.exports = {
132
+ resolveExportStrategy
133
+ });
@@ -55,9 +55,10 @@ var getStrategyChoices = async () => {
55
55
  "VolumeDivergence"
56
56
  ];
57
57
  };
58
- var selectStrategy = async (promptLabel = "Select strategy") => {
59
- const strategies = await getStrategyChoices();
60
- const fallbackStrategy = strategies.includes(defaultStrategy) ? defaultStrategy : strategies[0];
58
+ var selectStrategy = async (promptLabel = "Select strategy", options) => {
59
+ const strategies = options?.strategies && options.strategies.length ? options.strategies : await getStrategyChoices();
60
+ const preferredDefault = options?.defaultStrategy || defaultStrategy;
61
+ const fallbackStrategy = strategies.includes(preferredDefault) ? preferredDefault : strategies[0];
61
62
  if (!process.stdin.isTTY) {
62
63
  return fallbackStrategy;
63
64
  }
@@ -5,6 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
8
12
  var __copyProps = (to, from, except, desc) => {
9
13
  if (from && typeof from === "object" || typeof from === "function") {
10
14
  for (let key of __getOwnPropNames(from))
@@ -21,8 +25,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
25
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
26
  mod
23
27
  ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
24
29
 
25
30
  // src/scripts/signals.ts
31
+ var signals_exports = {};
32
+ __export(signals_exports, {
33
+ signals: () => signals
34
+ });
35
+ module.exports = __toCommonJS(signals_exports);
26
36
  var import_config = require("dotenv/config");
27
37
  var import_args = __toESM(require("args"));
28
38
  var import_progress = __toESM(require("progress"));
@@ -46,6 +56,11 @@ import_args.default.option(["S", "skipScreenshots"], "Skip screenshot generation
46
56
  import_args.default.option(["u", "updateOnly"], "Only update tickers history", false);
47
57
  import_args.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
48
58
  import_args.default.option(["L", "showTickersList"], "Just show only ticker list", false);
59
+ import_args.default.option(
60
+ ["R", "showSkipStats"],
61
+ "Show aggregated skip stats by strategy",
62
+ false
63
+ );
49
64
  import_args.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
50
65
  import_args.default.option(["U", "user"], "Use user confg", "root");
51
66
  import_args.default.option(
@@ -53,11 +68,9 @@ import_args.default.option(
53
68
  "Connector provider or name for signals (e.g. bybit, binance, coinbase, custom)",
54
69
  "bybit"
55
70
  );
56
- var PRELOAD_START = (0, import_time.getTimestamp)(import_constants.SIGNALS_PRELOAD_DAYS);
71
+ var PRELOAD_START = (0, import_time.getTimestamp)(import_constants.SIGNALS_CLI_PRELOAD_DAYS);
57
72
  var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
58
73
  var flags = import_args.default.parse(process.argv);
59
- var minTouches = parseInt(flags.points);
60
- var offset = parseInt(flags.offset);
61
74
  var interval = flags.timeframe.toString();
62
75
  var formatElapsed = (startedAt) => `${((Date.now() - startedAt) / 1e3).toFixed(1)}s`;
63
76
  var resolveStrategyNameByConfigKey = (userName, key) => {
@@ -98,6 +111,45 @@ var loadRuntimeStrategies = async (userName) => {
98
111
  );
99
112
  return strategyConfigs.filter(Boolean);
100
113
  };
114
+ var createStrategySkipStats = (runtimeStrategies) => new Map(
115
+ runtimeStrategies.map(({ strategyName }) => [
116
+ strategyName,
117
+ {
118
+ evaluated: 0,
119
+ signals: 0,
120
+ reasons: /* @__PURE__ */ new Map()
121
+ }
122
+ ])
123
+ );
124
+ var recordStrategyReason = (strategyStats, strategyName, reason) => {
125
+ const stats = strategyStats.get(strategyName);
126
+ if (!stats) {
127
+ return;
128
+ }
129
+ stats.reasons.set(reason, (stats.reasons.get(reason) ?? 0) + 1);
130
+ };
131
+ var logStrategySkipStats = (runtimeStrategies, strategyStats) => {
132
+ import_logger.logger.info(import_chalk.default.yellow("skip stats:"));
133
+ for (const { strategyName } of runtimeStrategies) {
134
+ const stats = strategyStats.get(strategyName);
135
+ if (!stats) {
136
+ continue;
137
+ }
138
+ import_logger.logger.info(
139
+ `${strategyName}: evaluated=${stats.evaluated}, signals=${stats.signals}`
140
+ );
141
+ const sortedReasons = [...stats.reasons.entries()].sort(
142
+ (left, right) => right[1] - left[1] || left[0].localeCompare(right[0])
143
+ );
144
+ if (!sortedReasons.length) {
145
+ import_logger.logger.info(" none");
146
+ continue;
147
+ }
148
+ for (const [reason, count] of sortedReasons) {
149
+ import_logger.logger.info(` ${reason}: ${count}`);
150
+ }
151
+ }
152
+ };
101
153
  var resolveSignalsConnectorName = async (value) => {
102
154
  const connectorName = await (0, import_connectors2.resolveConnectorName)(value, projectRoot);
103
155
  if (connectorName) {
@@ -110,13 +162,9 @@ var resolveSignalsConnectorName = async (value) => {
110
162
  );
111
163
  return import_connectors2.DEFAULT_CONNECTOR_NAME;
112
164
  };
113
- var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, runtimeStrategies) => {
114
- const prevSignals = await (0, import_redis.getKeys)(import_redis.redisKeys.signalsBySymbol(symbol));
115
- if (prevSignals.length) {
116
- import_logger.logger.info("Exit by signal exists %s", symbol);
117
- return null;
118
- }
165
+ var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, runtimeStrategies, strategyStats) => {
119
166
  const currentTimestamp = (0, import_time.getTimestamp)();
167
+ const strategySignals = [];
120
168
  const [cachedData, btcCachedData] = await Promise.all([
121
169
  connector.kline({
122
170
  symbol,
@@ -136,10 +184,14 @@ var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, run
136
184
  const lastCandle = cachedData.pop();
137
185
  const btcLastCandle = btcCachedData.pop();
138
186
  if (!lastCandle || !btcLastCandle) {
139
- return;
187
+ return strategySignals;
140
188
  }
141
189
  for (const runtimeStrategy of runtimeStrategies) {
142
190
  const { strategyName, strategyCreator, strategyConfig } = runtimeStrategy;
191
+ const stats = strategyStats.get(strategyName);
192
+ if (stats) {
193
+ stats.evaluated += 1;
194
+ }
143
195
  const strategy = await strategyCreator({
144
196
  userName: flags.user,
145
197
  connector,
@@ -157,8 +209,15 @@ var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, run
157
209
  });
158
210
  const signal = await strategy(lastCandle, btcLastCandle);
159
211
  if (!signal || typeof signal === "string") {
212
+ if (typeof signal === "string") {
213
+ recordStrategyReason(strategyStats, strategyName, signal);
214
+ }
160
215
  continue;
161
216
  }
217
+ if (stats) {
218
+ stats.signals += 1;
219
+ }
220
+ strategySignals.push(signal);
162
221
  await (0, import_redis.setData)(import_redis.redisKeys.signal(symbol, signal.signalId), signal, {
163
222
  expire: import_constants.TTL_1D
164
223
  });
@@ -166,8 +225,8 @@ var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, run
166
225
  expire: import_constants.TTL_3M
167
226
  });
168
227
  import_logger.logger.info("Signal found %s by strategy %s", symbol, strategyName);
169
- return signal;
170
228
  }
229
+ return strategySignals;
171
230
  };
172
231
  var signals = async () => {
173
232
  const startedAt = Date.now();
@@ -229,12 +288,27 @@ var signals = async () => {
229
288
  return;
230
289
  }
231
290
  if (!flags.cacheOnly) {
232
- await (0, import_cli.update)(marketConnector, interval, tickers);
291
+ await (0, import_cli.update)(
292
+ marketConnector,
293
+ interval,
294
+ tickers,
295
+ import_constants.SIGNALS_CLI_PRELOAD_DAYS
296
+ );
233
297
  if (btcBinanceConnector !== marketConnector) {
234
- await (0, import_cli.update)(btcBinanceConnector, interval, ["BTCUSDT"]);
298
+ await (0, import_cli.update)(
299
+ btcBinanceConnector,
300
+ interval,
301
+ ["BTCUSDT"],
302
+ import_constants.SIGNALS_CLI_PRELOAD_DAYS
303
+ );
235
304
  }
236
305
  if (btcCoinbaseConnector !== marketConnector) {
237
- await (0, import_cli.update)(btcCoinbaseConnector, interval, ["BTCUSDT"]);
306
+ await (0, import_cli.update)(
307
+ btcCoinbaseConnector,
308
+ interval,
309
+ ["BTCUSDT"],
310
+ import_constants.SIGNALS_CLI_PRELOAD_DAYS
311
+ );
238
312
  }
239
313
  }
240
314
  const currentTimestamp = (0, import_time.getTimestamp)();
@@ -270,6 +344,7 @@ var signals = async () => {
270
344
  `loaded strategies: ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
271
345
  )
272
346
  );
347
+ const strategyStats = createStrategySkipStats(runtimeStrategies);
273
348
  const bar = new import_progress.default(
274
349
  ":current/:total [:bar][:percent] :found :eta(s) :symbol",
275
350
  {
@@ -279,15 +354,16 @@ var signals = async () => {
279
354
  );
280
355
  import_logger.logger.info(import_chalk.default.yellow(`tickers: ${tickers.length}`));
281
356
  await (0, import_async.runWithConcurrency)(tickers, 5, async (symbol) => {
282
- const signal = await findSignals(
357
+ const strategySignals = await findSignals(
283
358
  symbol,
284
359
  marketConnector,
285
360
  btcBinanceData,
286
361
  btcCoinbaseData,
287
- runtimeStrategies
362
+ runtimeStrategies,
363
+ strategyStats
288
364
  );
289
- if (signal) {
290
- signals2.push(signal);
365
+ if (strategySignals.length > 0) {
366
+ signals2.push(...strategySignals);
291
367
  }
292
368
  bar.tick(1, {
293
369
  found: import_chalk.default.cyan(signals2.length),
@@ -295,11 +371,10 @@ var signals = async () => {
295
371
  });
296
372
  });
297
373
  if (!flags.skipScreenshots) {
298
- await (0, import_cli.makeScreenshots)(signals2, "15");
299
- await (0, import_cli.makeScreenshots)(signals2, "60");
374
+ await (0, import_cli.makeScreenshots)(signals2, "15", flags.user);
300
375
  }
301
376
  if (flags.notify) {
302
- await (0, import_cli.sendToTG)(signals2, "15");
377
+ await (0, import_cli.sendToTG)(signals2, "15", flags.user);
303
378
  }
304
379
  import_logger.logger.info(
305
380
  JSON.stringify(
@@ -308,6 +383,9 @@ var signals = async () => {
308
383
  2
309
384
  )
310
385
  );
386
+ if (flags.showSkipStats) {
387
+ logStrategySkipStats(runtimeStrategies, strategyStats);
388
+ }
311
389
  } catch (error) {
312
390
  status = "failed";
313
391
  import_logger.logger.error(
@@ -323,8 +401,14 @@ var signals = async () => {
323
401
  );
324
402
  }
325
403
  };
326
- signals().then(() => {
327
- process.exit(0);
328
- }).catch(() => {
329
- process.exit(1);
404
+ if (process.env.NODE_ENV !== "test") {
405
+ signals().then(() => {
406
+ process.exit(0);
407
+ }).catch(() => {
408
+ process.exit(1);
409
+ });
410
+ }
411
+ // Annotate the CommonJS export names for ESM import in node:
412
+ 0 && (module.exports = {
413
+ signals
330
414
  });
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
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
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/scripts/spawnSiblingScript.ts
31
+ var spawnSiblingScript_exports = {};
32
+ __export(spawnSiblingScript_exports, {
33
+ spawnSiblingScript: () => spawnSiblingScript
34
+ });
35
+ module.exports = __toCommonJS(spawnSiblingScript_exports);
36
+ var import_fs = __toESM(require("fs"));
37
+ var import_path = __toESM(require("path"));
38
+ var import_child_process = require("child_process");
39
+ var spawnSiblingScript = (currentDir, scriptBaseName, extraArgs) => {
40
+ const searchDirs = [currentDir, import_path.default.resolve(currentDir, "scripts")];
41
+ const candidates = searchDirs.flatMap((dir) => [
42
+ import_path.default.resolve(dir, `${scriptBaseName}.js`),
43
+ import_path.default.resolve(dir, `${scriptBaseName}.ts`)
44
+ ]);
45
+ const scriptPath = candidates.find((candidate) => import_fs.default.existsSync(candidate));
46
+ if (!scriptPath) {
47
+ throw new Error(
48
+ `Script "${scriptBaseName}" not found. Checked: ${candidates.join(", ")}`
49
+ );
50
+ }
51
+ const commandArgs = scriptPath.endsWith(".ts") ? [
52
+ "-r",
53
+ "ts-node/register",
54
+ "-r",
55
+ "tsconfig-paths/register",
56
+ scriptPath,
57
+ ...extraArgs
58
+ ] : [scriptPath, ...extraArgs];
59
+ const result = (0, import_child_process.spawnSync)(process.execPath, commandArgs, {
60
+ env: process.env,
61
+ stdio: "inherit"
62
+ });
63
+ if (result.error) {
64
+ throw result.error;
65
+ }
66
+ return result.status ?? 1;
67
+ };
68
+ // Annotate the CommonJS export names for ESM import in node:
69
+ 0 && (module.exports = {
70
+ spawnSiblingScript
71
+ });
@@ -2,6 +2,7 @@
2
2
 
3
3
  // src/workers/testerWorker.ts
4
4
  var import_backtest = require("@tradejs/node/backtest");
5
+ var import_ai = require("@tradejs/infra/ai");
5
6
  var import_logger = require("@tradejs/infra/logger");
6
7
  var import_ml = require("@tradejs/infra/ml");
7
8
  var import_redis = require("@tradejs/infra/redis");
@@ -23,10 +24,12 @@ process.on(
23
24
  if (!testResult) {
24
25
  throw new Error("No result");
25
26
  }
26
- const { stat, orderLogId } = testResult;
27
+ const { stat, orderLogId, inlineOrderLog, inlinePositionLog } = testResult;
27
28
  process.send?.({
28
29
  stat,
29
30
  orderLogId,
31
+ inlineOrderLog,
32
+ inlinePositionLog,
30
33
  test
31
34
  });
32
35
  } catch (error) {
@@ -36,6 +39,7 @@ process.on(
36
39
  process.send?.({
37
40
  error: true,
38
41
  id: test.name,
42
+ symbol: test.symbol,
39
43
  msg: {
40
44
  message: errorMessage,
41
45
  stack: errorStack
@@ -44,10 +48,17 @@ process.on(
44
48
  }
45
49
  }
46
50
  } finally {
51
+ await (0, import_ai.closeAllAiDatasetWriters)();
47
52
  await (0, import_ml.closeAllMlDatasetWriters)();
48
53
  (0, import_backtest.resetTestingKlineCache)();
49
54
  }
50
- process.send?.({ done: true });
55
+ if (process.send) {
56
+ process.send({ done: true }, () => {
57
+ process.disconnect?.();
58
+ process.exit(0);
59
+ });
60
+ return;
61
+ }
51
62
  process.disconnect?.();
52
63
  process.exit(0);
53
64
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Official CLI for the TradeJS open-source 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": "^1.0.5",
33
- "@tradejs/connectors": "^1.0.5",
34
- "@tradejs/core": "^1.0.5",
35
- "@tradejs/indicators": "^1.0.5",
36
- "@tradejs/infra": "^1.0.5",
37
- "@tradejs/node": "^1.0.5",
38
- "@tradejs/strategies": "^1.0.5",
39
- "@tradejs/types": "^1.0.5",
32
+ "@tradejs/base": "^1.0.6",
33
+ "@tradejs/connectors": "^1.0.6",
34
+ "@tradejs/core": "^1.0.6",
35
+ "@tradejs/indicators": "^1.0.6",
36
+ "@tradejs/infra": "^1.0.6",
37
+ "@tradejs/node": "^1.0.6",
38
+ "@tradejs/strategies": "^1.0.6",
39
+ "@tradejs/types": "^1.0.6",
40
40
  "args": "^5.0.3",
41
41
  "bcryptjs": "^2.4.3",
42
42
  "chalk": "4.1.2",
@@ -63,6 +63,8 @@
63
63
  "clean-redis": "yarn run run:dist clean-redis",
64
64
  "clean-tests": "yarn run run:dist clean-tests",
65
65
  "doctor": "yarn run run:dist doctor",
66
+ "ai-export": "yarn run run:dist ai-export",
67
+ "ai-train": "yarn run run:dist ai-train",
66
68
  "backtest": "yarn run run:dist backtest",
67
69
  "bot": "yarn run run:dist bot",
68
70
  "signals": "yarn run run:dist signals",