@tradejs/cli 1.0.4 → 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.
- package/README.md +5 -2
- package/dist/cli.js +2047 -929
- package/dist/lib/aiTrainMetrics.js +150 -0
- package/dist/scripts/aiExport.js +192 -0
- package/dist/scripts/aiExportSelect.js +135 -0
- package/dist/scripts/aiTrain.js +2239 -0
- package/dist/scripts/backtest.js +218 -32
- package/dist/scripts/derivativesIngest.js +5 -0
- package/dist/scripts/derivativesIngestCoinalyzeAll.js +21 -12
- package/dist/scripts/mlExport.js +112 -13
- package/dist/scripts/mlExportSelect.js +43 -9
- package/dist/scripts/mlTrainLatestSelect.js +4 -3
- package/dist/scripts/resolveExportStrategy.js +133 -0
- package/dist/scripts/selectStrategy.js +4 -3
- package/dist/scripts/signals.js +238 -133
- package/dist/scripts/spawnSiblingScript.js +71 -0
- package/dist/workers/testerWorker.js +13 -2
- package/package.json +20 -10
package/dist/scripts/signals.js
CHANGED
|
@@ -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,12 +68,11 @@ 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.
|
|
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();
|
|
75
|
+
var formatElapsed = (startedAt) => `${((Date.now() - startedAt) / 1e3).toFixed(1)}s`;
|
|
62
76
|
var resolveStrategyNameByConfigKey = (userName, key) => {
|
|
63
77
|
const parts = key.split(":");
|
|
64
78
|
if (parts.length !== 5) {
|
|
@@ -97,6 +111,45 @@ var loadRuntimeStrategies = async (userName) => {
|
|
|
97
111
|
);
|
|
98
112
|
return strategyConfigs.filter(Boolean);
|
|
99
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
|
+
};
|
|
100
153
|
var resolveSignalsConnectorName = async (value) => {
|
|
101
154
|
const connectorName = await (0, import_connectors2.resolveConnectorName)(value, projectRoot);
|
|
102
155
|
if (connectorName) {
|
|
@@ -109,13 +162,9 @@ var resolveSignalsConnectorName = async (value) => {
|
|
|
109
162
|
);
|
|
110
163
|
return import_connectors2.DEFAULT_CONNECTOR_NAME;
|
|
111
164
|
};
|
|
112
|
-
var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, runtimeStrategies) => {
|
|
113
|
-
const prevSignals = await (0, import_redis.getKeys)(import_redis.redisKeys.signalsBySymbol(symbol));
|
|
114
|
-
if (prevSignals.length) {
|
|
115
|
-
import_logger.logger.info("Exit by signal exists %s", symbol);
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
165
|
+
var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, runtimeStrategies, strategyStats) => {
|
|
118
166
|
const currentTimestamp = (0, import_time.getTimestamp)();
|
|
167
|
+
const strategySignals = [];
|
|
119
168
|
const [cachedData, btcCachedData] = await Promise.all([
|
|
120
169
|
connector.kline({
|
|
121
170
|
symbol,
|
|
@@ -135,10 +184,14 @@ var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, run
|
|
|
135
184
|
const lastCandle = cachedData.pop();
|
|
136
185
|
const btcLastCandle = btcCachedData.pop();
|
|
137
186
|
if (!lastCandle || !btcLastCandle) {
|
|
138
|
-
return;
|
|
187
|
+
return strategySignals;
|
|
139
188
|
}
|
|
140
189
|
for (const runtimeStrategy of runtimeStrategies) {
|
|
141
190
|
const { strategyName, strategyCreator, strategyConfig } = runtimeStrategy;
|
|
191
|
+
const stats = strategyStats.get(strategyName);
|
|
192
|
+
if (stats) {
|
|
193
|
+
stats.evaluated += 1;
|
|
194
|
+
}
|
|
142
195
|
const strategy = await strategyCreator({
|
|
143
196
|
userName: flags.user,
|
|
144
197
|
connector,
|
|
@@ -156,8 +209,15 @@ var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, run
|
|
|
156
209
|
});
|
|
157
210
|
const signal = await strategy(lastCandle, btcLastCandle);
|
|
158
211
|
if (!signal || typeof signal === "string") {
|
|
212
|
+
if (typeof signal === "string") {
|
|
213
|
+
recordStrategyReason(strategyStats, strategyName, signal);
|
|
214
|
+
}
|
|
159
215
|
continue;
|
|
160
216
|
}
|
|
217
|
+
if (stats) {
|
|
218
|
+
stats.signals += 1;
|
|
219
|
+
}
|
|
220
|
+
strategySignals.push(signal);
|
|
161
221
|
await (0, import_redis.setData)(import_redis.redisKeys.signal(symbol, signal.signalId), signal, {
|
|
162
222
|
expire: import_constants.TTL_1D
|
|
163
223
|
});
|
|
@@ -165,145 +225,190 @@ var findSignals = async (symbol, connector, btcBinanceData, btcCoinbaseData, run
|
|
|
165
225
|
expire: import_constants.TTL_3M
|
|
166
226
|
});
|
|
167
227
|
import_logger.logger.info("Signal found %s by strategy %s", symbol, strategyName);
|
|
168
|
-
return signal;
|
|
169
228
|
}
|
|
229
|
+
return strategySignals;
|
|
170
230
|
};
|
|
171
231
|
var signals = async () => {
|
|
232
|
+
const startedAt = Date.now();
|
|
172
233
|
const signals2 = new Array();
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
connectorName
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (!connectorFactory) {
|
|
179
|
-
throw new Error(`Connector "${connectorName}" is not registered`);
|
|
180
|
-
}
|
|
181
|
-
const marketConnector = await connectorFactory({
|
|
182
|
-
userName: flags.user
|
|
183
|
-
});
|
|
184
|
-
let btcBinanceConnector = marketConnector;
|
|
185
|
-
let btcCoinbaseConnector = marketConnector;
|
|
186
|
-
if (connectorName.toLowerCase() === import_connectors2.DEFAULT_CONNECTOR_NAME.toLowerCase()) {
|
|
187
|
-
const binanceFactory = await (0, import_connectors2.getConnectorCreatorByName)(
|
|
188
|
-
import_connectors.ConnectorNames.Binance,
|
|
234
|
+
let status = "completed";
|
|
235
|
+
try {
|
|
236
|
+
const connectorName = await resolveSignalsConnectorName(flags.connector);
|
|
237
|
+
const connectorFactory = await (0, import_connectors2.getConnectorCreatorByName)(
|
|
238
|
+
connectorName,
|
|
189
239
|
projectRoot
|
|
190
240
|
);
|
|
191
|
-
if (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
241
|
+
if (!connectorFactory) {
|
|
242
|
+
throw new Error(`Connector "${connectorName}" is not registered`);
|
|
243
|
+
}
|
|
244
|
+
const marketConnector = await connectorFactory({
|
|
245
|
+
userName: flags.user
|
|
246
|
+
});
|
|
247
|
+
let btcBinanceConnector = marketConnector;
|
|
248
|
+
let btcCoinbaseConnector = marketConnector;
|
|
249
|
+
if (connectorName.toLowerCase() === import_connectors2.DEFAULT_CONNECTOR_NAME.toLowerCase()) {
|
|
250
|
+
const binanceFactory = await (0, import_connectors2.getConnectorCreatorByName)(
|
|
251
|
+
import_connectors.ConnectorNames.Binance,
|
|
252
|
+
projectRoot
|
|
253
|
+
);
|
|
254
|
+
if (binanceFactory) {
|
|
255
|
+
btcBinanceConnector = await binanceFactory({
|
|
256
|
+
userName: flags.user
|
|
257
|
+
});
|
|
258
|
+
} else {
|
|
259
|
+
import_logger.logger.warn(
|
|
260
|
+
"Binance connector is unavailable. Reusing %s.",
|
|
261
|
+
connectorName
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
const coinbaseFactory = await (0, import_connectors2.getConnectorCreatorByName)(
|
|
265
|
+
import_connectors.ConnectorNames.Coinbase,
|
|
266
|
+
projectRoot
|
|
199
267
|
);
|
|
268
|
+
if (coinbaseFactory) {
|
|
269
|
+
btcCoinbaseConnector = await coinbaseFactory({
|
|
270
|
+
userName: flags.user
|
|
271
|
+
});
|
|
272
|
+
} else {
|
|
273
|
+
import_logger.logger.warn(
|
|
274
|
+
"Coinbase connector is unavailable. Reusing %s.",
|
|
275
|
+
connectorName
|
|
276
|
+
);
|
|
277
|
+
}
|
|
200
278
|
}
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
279
|
+
const tickers = await (0, import_cli.getTickers)(
|
|
280
|
+
marketConnector,
|
|
281
|
+
flags.tickers,
|
|
282
|
+
flags.exclude,
|
|
283
|
+
flags.tickersLimit,
|
|
284
|
+
flags.chunk
|
|
204
285
|
);
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
286
|
+
if (flags.showTickersList) {
|
|
287
|
+
console.log(import_chalk.default.gray(JSON.stringify(tickers.sort(), null, 2)));
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (!flags.cacheOnly) {
|
|
291
|
+
await (0, import_cli.update)(
|
|
292
|
+
marketConnector,
|
|
293
|
+
interval,
|
|
294
|
+
tickers,
|
|
295
|
+
import_constants.SIGNALS_CLI_PRELOAD_DAYS
|
|
213
296
|
);
|
|
297
|
+
if (btcBinanceConnector !== marketConnector) {
|
|
298
|
+
await (0, import_cli.update)(
|
|
299
|
+
btcBinanceConnector,
|
|
300
|
+
interval,
|
|
301
|
+
["BTCUSDT"],
|
|
302
|
+
import_constants.SIGNALS_CLI_PRELOAD_DAYS
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
if (btcCoinbaseConnector !== marketConnector) {
|
|
306
|
+
await (0, import_cli.update)(
|
|
307
|
+
btcCoinbaseConnector,
|
|
308
|
+
interval,
|
|
309
|
+
["BTCUSDT"],
|
|
310
|
+
import_constants.SIGNALS_CLI_PRELOAD_DAYS
|
|
311
|
+
);
|
|
312
|
+
}
|
|
214
313
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
314
|
+
const currentTimestamp = (0, import_time.getTimestamp)();
|
|
315
|
+
const [btcBinanceData, btcCoinbaseData] = await Promise.all([
|
|
316
|
+
btcBinanceConnector.kline({
|
|
317
|
+
symbol: "BTCUSDT",
|
|
318
|
+
start: PRELOAD_START,
|
|
319
|
+
end: currentTimestamp,
|
|
320
|
+
cacheOnly: true,
|
|
321
|
+
interval
|
|
322
|
+
}),
|
|
323
|
+
btcCoinbaseConnector.kline({
|
|
324
|
+
symbol: "BTCUSDT",
|
|
325
|
+
start: PRELOAD_START,
|
|
326
|
+
end: currentTimestamp,
|
|
327
|
+
cacheOnly: true,
|
|
328
|
+
interval
|
|
329
|
+
})
|
|
330
|
+
]);
|
|
331
|
+
if (flags.updateOnly) {
|
|
332
|
+
return;
|
|
231
333
|
}
|
|
232
|
-
|
|
233
|
-
|
|
334
|
+
const runtimeStrategies = await loadRuntimeStrategies(flags.user);
|
|
335
|
+
if (!runtimeStrategies.length) {
|
|
336
|
+
import_logger.logger.warn(
|
|
337
|
+
"No strategy configs found by users:%s:strategies:*:config",
|
|
338
|
+
flags.user
|
|
339
|
+
);
|
|
340
|
+
return;
|
|
234
341
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
symbol: "BTCUSDT",
|
|
240
|
-
start: PRELOAD_START,
|
|
241
|
-
end: currentTimestamp,
|
|
242
|
-
cacheOnly: true,
|
|
243
|
-
interval
|
|
244
|
-
}),
|
|
245
|
-
btcCoinbaseConnector.kline({
|
|
246
|
-
symbol: "BTCUSDT",
|
|
247
|
-
start: PRELOAD_START,
|
|
248
|
-
end: currentTimestamp,
|
|
249
|
-
cacheOnly: true,
|
|
250
|
-
interval
|
|
251
|
-
})
|
|
252
|
-
]);
|
|
253
|
-
if (flags.updateOnly) {
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
const runtimeStrategies = await loadRuntimeStrategies(flags.user);
|
|
257
|
-
if (!runtimeStrategies.length) {
|
|
258
|
-
import_logger.logger.warn(
|
|
259
|
-
"No strategy configs found by users:%s:strategies:*:config",
|
|
260
|
-
flags.user
|
|
342
|
+
import_logger.logger.info(
|
|
343
|
+
import_chalk.default.yellow(
|
|
344
|
+
`loaded strategies: ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
|
|
345
|
+
)
|
|
261
346
|
);
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
{
|
|
272
|
-
|
|
273
|
-
|
|
347
|
+
const strategyStats = createStrategySkipStats(runtimeStrategies);
|
|
348
|
+
const bar = new import_progress.default(
|
|
349
|
+
":current/:total [:bar][:percent] :found :eta(s) :symbol",
|
|
350
|
+
{
|
|
351
|
+
total: tickers.length,
|
|
352
|
+
width: 30
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
import_logger.logger.info(import_chalk.default.yellow(`tickers: ${tickers.length}`));
|
|
356
|
+
await (0, import_async.runWithConcurrency)(tickers, 5, async (symbol) => {
|
|
357
|
+
const strategySignals = await findSignals(
|
|
358
|
+
symbol,
|
|
359
|
+
marketConnector,
|
|
360
|
+
btcBinanceData,
|
|
361
|
+
btcCoinbaseData,
|
|
362
|
+
runtimeStrategies,
|
|
363
|
+
strategyStats
|
|
364
|
+
);
|
|
365
|
+
if (strategySignals.length > 0) {
|
|
366
|
+
signals2.push(...strategySignals);
|
|
367
|
+
}
|
|
368
|
+
bar.tick(1, {
|
|
369
|
+
found: import_chalk.default.cyan(signals2.length),
|
|
370
|
+
symbol: import_chalk.default.gray(symbol)
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
if (!flags.skipScreenshots) {
|
|
374
|
+
await (0, import_cli.makeScreenshots)(signals2, "15", flags.user);
|
|
274
375
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
376
|
+
if (flags.notify) {
|
|
377
|
+
await (0, import_cli.sendToTG)(signals2, "15", flags.user);
|
|
378
|
+
}
|
|
379
|
+
import_logger.logger.info(
|
|
380
|
+
JSON.stringify(
|
|
381
|
+
signals2.map((s) => s.symbol),
|
|
382
|
+
null,
|
|
383
|
+
2
|
|
384
|
+
)
|
|
284
385
|
);
|
|
285
|
-
if (
|
|
286
|
-
|
|
386
|
+
if (flags.showSkipStats) {
|
|
387
|
+
logStrategySkipStats(runtimeStrategies, strategyStats);
|
|
287
388
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
389
|
+
} catch (error) {
|
|
390
|
+
status = "failed";
|
|
391
|
+
import_logger.logger.error(
|
|
392
|
+
"signals failed: %s",
|
|
393
|
+
error?.message || String(error)
|
|
394
|
+
);
|
|
395
|
+
throw error;
|
|
396
|
+
} finally {
|
|
397
|
+
import_logger.logger.info(
|
|
398
|
+
import_chalk.default.yellow(
|
|
399
|
+
`signals ${status} in ${formatElapsed(startedAt)} (found=${signals2.length})`
|
|
400
|
+
)
|
|
401
|
+
);
|
|
299
402
|
}
|
|
300
|
-
import_logger.logger.info(
|
|
301
|
-
JSON.stringify(
|
|
302
|
-
signals2.map((s) => s.symbol),
|
|
303
|
-
null,
|
|
304
|
-
2
|
|
305
|
-
)
|
|
306
|
-
);
|
|
307
|
-
process.exit();
|
|
308
403
|
};
|
|
309
|
-
|
|
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
|
|
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
|
|
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/cli",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Official
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "Official CLI for the TradeJS open-source framework: infra setup, backtests, signals, bots, and ML workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
7
7
|
"trading",
|
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
"automation"
|
|
13
13
|
],
|
|
14
14
|
"homepage": "https://tradejs.dev",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/tradejs-dev/tradejs.git",
|
|
18
|
+
"directory": "packages/cli"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/tradejs-dev/tradejs/issues"
|
|
22
|
+
},
|
|
15
23
|
"main": "dist/cli.js",
|
|
16
24
|
"types": "dist/cli.d.ts",
|
|
17
25
|
"files": [
|
|
@@ -21,14 +29,14 @@
|
|
|
21
29
|
"tradejs": "dist/cli.js"
|
|
22
30
|
},
|
|
23
31
|
"dependencies": {
|
|
24
|
-
"@tradejs/base": "^1.0.
|
|
25
|
-
"@tradejs/connectors": "^1.0.
|
|
26
|
-
"@tradejs/core": "^1.0.
|
|
27
|
-
"@tradejs/indicators": "^1.0.
|
|
28
|
-
"@tradejs/infra": "^1.0.
|
|
29
|
-
"@tradejs/node": "^1.0.
|
|
30
|
-
"@tradejs/strategies": "^1.0.
|
|
31
|
-
"@tradejs/types": "^1.0.
|
|
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",
|
|
32
40
|
"args": "^5.0.3",
|
|
33
41
|
"bcryptjs": "^2.4.3",
|
|
34
42
|
"chalk": "4.1.2",
|
|
@@ -55,6 +63,8 @@
|
|
|
55
63
|
"clean-redis": "yarn run run:dist clean-redis",
|
|
56
64
|
"clean-tests": "yarn run run:dist clean-tests",
|
|
57
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",
|
|
58
68
|
"backtest": "yarn run run:dist backtest",
|
|
59
69
|
"bot": "yarn run run:dist bot",
|
|
60
70
|
"signals": "yarn run run:dist signals",
|