@tradejs/cli 2.0.18 → 2.0.19

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.
Files changed (41) hide show
  1. package/dist/cli.js +12810 -19565
  2. package/dist/lib/aiExport.js +1 -1607
  3. package/dist/lib/binanceMarketContextBackfill.js +7 -6
  4. package/dist/lib/coinMarketCapContextBackfill.js +19 -18
  5. package/dist/lib/derivativesContextBackfill.js +10 -9
  6. package/dist/lib/hyperliquidWhaleBackfill.js +8 -8
  7. package/dist/lib/hyperliquidWhaleStream.js +4 -4
  8. package/dist/lib/marketContextPrepare.js +83 -1686
  9. package/dist/lib/runEnvironment.js +14 -1666
  10. package/dist/lib/runFormatting.js +1 -1607
  11. package/dist/lib/runtimeDebugEvidence.js +2 -48
  12. package/dist/lib/runtimeRedis.js +6 -57
  13. package/dist/lib/runtimeStrategyBacktest.js +2 -48
  14. package/dist/scripts/aiExport.js +1 -1607
  15. package/dist/scripts/aiPocketSearch.js +1 -1607
  16. package/dist/scripts/aiTrain.js +17 -1623
  17. package/dist/scripts/backtest.js +110 -1759
  18. package/dist/scripts/binanceMarketIngest.js +5 -4
  19. package/dist/scripts/candlesMigrateProvider.js +6 -5186
  20. package/dist/scripts/cleanupMarketContext.js +4 -3
  21. package/dist/scripts/continuity.js +4 -3
  22. package/dist/scripts/derivativesIngest.js +6 -4
  23. package/dist/scripts/derivativesIngestCoinalyzeAll.js +5 -4
  24. package/dist/scripts/doctor.js +2 -5184
  25. package/dist/scripts/hyperliquidWhaleBackfill.js +8 -8
  26. package/dist/scripts/hyperliquidWhaleIngest.js +4 -4
  27. package/dist/scripts/hyperliquidWhalesUpdate.js +1 -1
  28. package/dist/scripts/migration.js +3 -3
  29. package/dist/scripts/mlExport.js +1 -1607
  30. package/dist/scripts/replay.js +133 -1782
  31. package/dist/scripts/replayRunner.js +133 -1782
  32. package/dist/scripts/replayRuntimeEvidence.js +2 -48
  33. package/dist/scripts/researchAuto.js +3 -49
  34. package/dist/scripts/results.js +1 -1607
  35. package/dist/scripts/runtimeEvidence.js +2 -48
  36. package/dist/scripts/runtimeParity.js +121 -1746
  37. package/dist/scripts/signals.js +1057 -2647
  38. package/dist/scripts/signalsDaemon.js +1051 -2608
  39. package/dist/scripts/signalsSummary.js +4 -26
  40. package/dist/workers/testerWorker.js +2 -2
  41. package/package.json +11 -9
@@ -5,13 +5,6 @@ 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 __commonJS = (cb, mod) => function __require() {
9
- try {
10
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
- } catch (e) {
12
- throw mod = 0, e;
13
- }
14
- };
15
8
  var __export = (target, all) => {
16
9
  for (var name in all)
17
10
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -34,1605 +27,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
27
  ));
35
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
29
 
37
- // ../../node_modules/ms/index.js
38
- var require_ms = __commonJS({
39
- "../../node_modules/ms/index.js"(exports2, module2) {
40
- "use strict";
41
- var s = 1e3;
42
- var m = s * 60;
43
- var h = m * 60;
44
- var d = h * 24;
45
- var w = d * 7;
46
- var y = d * 365.25;
47
- module2.exports = function(val, options) {
48
- options = options || {};
49
- var type = typeof val;
50
- if (type === "string" && val.length > 0) {
51
- return parse(val);
52
- } else if (type === "number" && isFinite(val)) {
53
- return options.long ? fmtLong(val) : fmtShort(val);
54
- }
55
- throw new Error(
56
- "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
57
- );
58
- };
59
- function parse(str) {
60
- str = String(str);
61
- if (str.length > 100) {
62
- return;
63
- }
64
- var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
65
- str
66
- );
67
- if (!match) {
68
- return;
69
- }
70
- var n = parseFloat(match[1]);
71
- var type = (match[2] || "ms").toLowerCase();
72
- switch (type) {
73
- case "years":
74
- case "year":
75
- case "yrs":
76
- case "yr":
77
- case "y":
78
- return n * y;
79
- case "weeks":
80
- case "week":
81
- case "w":
82
- return n * w;
83
- case "days":
84
- case "day":
85
- case "d":
86
- return n * d;
87
- case "hours":
88
- case "hour":
89
- case "hrs":
90
- case "hr":
91
- case "h":
92
- return n * h;
93
- case "minutes":
94
- case "minute":
95
- case "mins":
96
- case "min":
97
- case "m":
98
- return n * m;
99
- case "seconds":
100
- case "second":
101
- case "secs":
102
- case "sec":
103
- case "s":
104
- return n * s;
105
- case "milliseconds":
106
- case "millisecond":
107
- case "msecs":
108
- case "msec":
109
- case "ms":
110
- return n;
111
- default:
112
- return void 0;
113
- }
114
- }
115
- function fmtShort(ms) {
116
- var msAbs = Math.abs(ms);
117
- if (msAbs >= d) {
118
- return Math.round(ms / d) + "d";
119
- }
120
- if (msAbs >= h) {
121
- return Math.round(ms / h) + "h";
122
- }
123
- if (msAbs >= m) {
124
- return Math.round(ms / m) + "m";
125
- }
126
- if (msAbs >= s) {
127
- return Math.round(ms / s) + "s";
128
- }
129
- return ms + "ms";
130
- }
131
- function fmtLong(ms) {
132
- var msAbs = Math.abs(ms);
133
- if (msAbs >= d) {
134
- return plural(ms, msAbs, d, "day");
135
- }
136
- if (msAbs >= h) {
137
- return plural(ms, msAbs, h, "hour");
138
- }
139
- if (msAbs >= m) {
140
- return plural(ms, msAbs, m, "minute");
141
- }
142
- if (msAbs >= s) {
143
- return plural(ms, msAbs, s, "second");
144
- }
145
- return ms + " ms";
146
- }
147
- function plural(ms, msAbs, n, name) {
148
- var isPlural = msAbs >= n * 1.5;
149
- return Math.round(ms / n) + " " + name + (isPlural ? "s" : "");
150
- }
151
- }
152
- });
153
-
154
- // ../../node_modules/list-it/node_modules/debug/src/common.js
155
- var require_common = __commonJS({
156
- "../../node_modules/list-it/node_modules/debug/src/common.js"(exports2, module2) {
157
- "use strict";
158
- function setup(env) {
159
- createDebug.debug = createDebug;
160
- createDebug.default = createDebug;
161
- createDebug.coerce = coerce;
162
- createDebug.disable = disable;
163
- createDebug.enable = enable;
164
- createDebug.enabled = enabled;
165
- createDebug.humanize = require_ms();
166
- createDebug.destroy = destroy;
167
- Object.keys(env).forEach((key) => {
168
- createDebug[key] = env[key];
169
- });
170
- createDebug.names = [];
171
- createDebug.skips = [];
172
- createDebug.formatters = {};
173
- function selectColor(namespace) {
174
- let hash = 0;
175
- for (let i = 0; i < namespace.length; i++) {
176
- hash = (hash << 5) - hash + namespace.charCodeAt(i);
177
- hash |= 0;
178
- }
179
- return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
180
- }
181
- createDebug.selectColor = selectColor;
182
- function createDebug(namespace) {
183
- let prevTime;
184
- let enableOverride = null;
185
- let namespacesCache;
186
- let enabledCache;
187
- function debug(...args2) {
188
- if (!debug.enabled) {
189
- return;
190
- }
191
- const self = debug;
192
- const curr = Number(/* @__PURE__ */ new Date());
193
- const ms = curr - (prevTime || curr);
194
- self.diff = ms;
195
- self.prev = prevTime;
196
- self.curr = curr;
197
- prevTime = curr;
198
- args2[0] = createDebug.coerce(args2[0]);
199
- if (typeof args2[0] !== "string") {
200
- args2.unshift("%O");
201
- }
202
- let index = 0;
203
- args2[0] = args2[0].replace(/%([a-zA-Z%])/g, (match, format2) => {
204
- if (match === "%%") {
205
- return "%";
206
- }
207
- index++;
208
- const formatter = createDebug.formatters[format2];
209
- if (typeof formatter === "function") {
210
- const val = args2[index];
211
- match = formatter.call(self, val);
212
- args2.splice(index, 1);
213
- index--;
214
- }
215
- return match;
216
- });
217
- createDebug.formatArgs.call(self, args2);
218
- const logFn = self.log || createDebug.log;
219
- logFn.apply(self, args2);
220
- }
221
- debug.namespace = namespace;
222
- debug.useColors = createDebug.useColors();
223
- debug.color = createDebug.selectColor(namespace);
224
- debug.extend = extend;
225
- debug.destroy = createDebug.destroy;
226
- Object.defineProperty(debug, "enabled", {
227
- enumerable: true,
228
- configurable: false,
229
- get: () => {
230
- if (enableOverride !== null) {
231
- return enableOverride;
232
- }
233
- if (namespacesCache !== createDebug.namespaces) {
234
- namespacesCache = createDebug.namespaces;
235
- enabledCache = createDebug.enabled(namespace);
236
- }
237
- return enabledCache;
238
- },
239
- set: (v) => {
240
- enableOverride = v;
241
- }
242
- });
243
- if (typeof createDebug.init === "function") {
244
- createDebug.init(debug);
245
- }
246
- return debug;
247
- }
248
- function extend(namespace, delimiter) {
249
- const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
250
- newDebug.log = this.log;
251
- return newDebug;
252
- }
253
- function enable(namespaces) {
254
- createDebug.save(namespaces);
255
- createDebug.namespaces = namespaces;
256
- createDebug.names = [];
257
- createDebug.skips = [];
258
- const split = (typeof namespaces === "string" ? namespaces : "").trim().replace(/\s+/g, ",").split(",").filter(Boolean);
259
- for (const ns of split) {
260
- if (ns[0] === "-") {
261
- createDebug.skips.push(ns.slice(1));
262
- } else {
263
- createDebug.names.push(ns);
264
- }
265
- }
266
- }
267
- function matchesTemplate(search, template) {
268
- let searchIndex = 0;
269
- let templateIndex = 0;
270
- let starIndex = -1;
271
- let matchIndex = 0;
272
- while (searchIndex < search.length) {
273
- if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === "*")) {
274
- if (template[templateIndex] === "*") {
275
- starIndex = templateIndex;
276
- matchIndex = searchIndex;
277
- templateIndex++;
278
- } else {
279
- searchIndex++;
280
- templateIndex++;
281
- }
282
- } else if (starIndex !== -1) {
283
- templateIndex = starIndex + 1;
284
- matchIndex++;
285
- searchIndex = matchIndex;
286
- } else {
287
- return false;
288
- }
289
- }
290
- while (templateIndex < template.length && template[templateIndex] === "*") {
291
- templateIndex++;
292
- }
293
- return templateIndex === template.length;
294
- }
295
- function disable() {
296
- const namespaces = [
297
- ...createDebug.names,
298
- ...createDebug.skips.map((namespace) => "-" + namespace)
299
- ].join(",");
300
- createDebug.enable("");
301
- return namespaces;
302
- }
303
- function enabled(name) {
304
- for (const skip of createDebug.skips) {
305
- if (matchesTemplate(name, skip)) {
306
- return false;
307
- }
308
- }
309
- for (const ns of createDebug.names) {
310
- if (matchesTemplate(name, ns)) {
311
- return true;
312
- }
313
- }
314
- return false;
315
- }
316
- function coerce(val) {
317
- if (val instanceof Error) {
318
- return val.stack || val.message;
319
- }
320
- return val;
321
- }
322
- function destroy() {
323
- console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
324
- }
325
- createDebug.enable(createDebug.load());
326
- return createDebug;
327
- }
328
- module2.exports = setup;
329
- }
330
- });
331
-
332
- // ../../node_modules/list-it/node_modules/debug/src/browser.js
333
- var require_browser = __commonJS({
334
- "../../node_modules/list-it/node_modules/debug/src/browser.js"(exports2, module2) {
335
- "use strict";
336
- exports2.formatArgs = formatArgs;
337
- exports2.save = save;
338
- exports2.load = load;
339
- exports2.useColors = useColors;
340
- exports2.storage = localstorage();
341
- exports2.destroy = /* @__PURE__ */ (() => {
342
- let warned = false;
343
- return () => {
344
- if (!warned) {
345
- warned = true;
346
- console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
347
- }
348
- };
349
- })();
350
- exports2.colors = [
351
- "#0000CC",
352
- "#0000FF",
353
- "#0033CC",
354
- "#0033FF",
355
- "#0066CC",
356
- "#0066FF",
357
- "#0099CC",
358
- "#0099FF",
359
- "#00CC00",
360
- "#00CC33",
361
- "#00CC66",
362
- "#00CC99",
363
- "#00CCCC",
364
- "#00CCFF",
365
- "#3300CC",
366
- "#3300FF",
367
- "#3333CC",
368
- "#3333FF",
369
- "#3366CC",
370
- "#3366FF",
371
- "#3399CC",
372
- "#3399FF",
373
- "#33CC00",
374
- "#33CC33",
375
- "#33CC66",
376
- "#33CC99",
377
- "#33CCCC",
378
- "#33CCFF",
379
- "#6600CC",
380
- "#6600FF",
381
- "#6633CC",
382
- "#6633FF",
383
- "#66CC00",
384
- "#66CC33",
385
- "#9900CC",
386
- "#9900FF",
387
- "#9933CC",
388
- "#9933FF",
389
- "#99CC00",
390
- "#99CC33",
391
- "#CC0000",
392
- "#CC0033",
393
- "#CC0066",
394
- "#CC0099",
395
- "#CC00CC",
396
- "#CC00FF",
397
- "#CC3300",
398
- "#CC3333",
399
- "#CC3366",
400
- "#CC3399",
401
- "#CC33CC",
402
- "#CC33FF",
403
- "#CC6600",
404
- "#CC6633",
405
- "#CC9900",
406
- "#CC9933",
407
- "#CCCC00",
408
- "#CCCC33",
409
- "#FF0000",
410
- "#FF0033",
411
- "#FF0066",
412
- "#FF0099",
413
- "#FF00CC",
414
- "#FF00FF",
415
- "#FF3300",
416
- "#FF3333",
417
- "#FF3366",
418
- "#FF3399",
419
- "#FF33CC",
420
- "#FF33FF",
421
- "#FF6600",
422
- "#FF6633",
423
- "#FF9900",
424
- "#FF9933",
425
- "#FFCC00",
426
- "#FFCC33"
427
- ];
428
- function useColors() {
429
- if (typeof window !== "undefined" && window.process && (window.process.type === "renderer" || window.process.__nwjs)) {
430
- return true;
431
- }
432
- if (typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
433
- return false;
434
- }
435
- let m;
436
- return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773
437
- typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?
438
- // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
439
- typeof navigator !== "undefined" && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker
440
- typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
441
- }
442
- function formatArgs(args2) {
443
- args2[0] = (this.useColors ? "%c" : "") + this.namespace + (this.useColors ? " %c" : " ") + args2[0] + (this.useColors ? "%c " : " ") + "+" + module2.exports.humanize(this.diff);
444
- if (!this.useColors) {
445
- return;
446
- }
447
- const c = "color: " + this.color;
448
- args2.splice(1, 0, c, "color: inherit");
449
- let index = 0;
450
- let lastC = 0;
451
- args2[0].replace(/%[a-zA-Z%]/g, (match) => {
452
- if (match === "%%") {
453
- return;
454
- }
455
- index++;
456
- if (match === "%c") {
457
- lastC = index;
458
- }
459
- });
460
- args2.splice(lastC, 0, c);
461
- }
462
- exports2.log = console.debug || console.log || (() => {
463
- });
464
- function save(namespaces) {
465
- try {
466
- if (namespaces) {
467
- exports2.storage.setItem("debug", namespaces);
468
- } else {
469
- exports2.storage.removeItem("debug");
470
- }
471
- } catch (error) {
472
- }
473
- }
474
- function load() {
475
- let r;
476
- try {
477
- r = exports2.storage.getItem("debug") || exports2.storage.getItem("DEBUG");
478
- } catch (error) {
479
- }
480
- if (!r && typeof process !== "undefined" && "env" in process) {
481
- r = process.env.DEBUG;
482
- }
483
- return r;
484
- }
485
- function localstorage() {
486
- try {
487
- return localStorage;
488
- } catch (error) {
489
- }
490
- }
491
- module2.exports = require_common()(exports2);
492
- var { formatters } = module2.exports;
493
- formatters.j = function(v) {
494
- try {
495
- return JSON.stringify(v);
496
- } catch (error) {
497
- return "[UnexpectedJSONParseError]: " + error.message;
498
- }
499
- };
500
- }
501
- });
502
-
503
- // ../../node_modules/has-flag/index.js
504
- var require_has_flag = __commonJS({
505
- "../../node_modules/has-flag/index.js"(exports2, module2) {
506
- "use strict";
507
- module2.exports = (flag, argv = process.argv) => {
508
- const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
509
- const position = argv.indexOf(prefix + flag);
510
- const terminatorPosition = argv.indexOf("--");
511
- return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
512
- };
513
- }
514
- });
515
-
516
- // ../../node_modules/supports-color/index.js
517
- var require_supports_color = __commonJS({
518
- "../../node_modules/supports-color/index.js"(exports2, module2) {
519
- "use strict";
520
- var os = require("os");
521
- var tty = require("tty");
522
- var hasFlag = require_has_flag();
523
- var { env } = process;
524
- var forceColor;
525
- if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
526
- forceColor = 0;
527
- } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
528
- forceColor = 1;
529
- }
530
- if ("FORCE_COLOR" in env) {
531
- if (env.FORCE_COLOR === "true") {
532
- forceColor = 1;
533
- } else if (env.FORCE_COLOR === "false") {
534
- forceColor = 0;
535
- } else {
536
- forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
537
- }
538
- }
539
- function translateLevel(level) {
540
- if (level === 0) {
541
- return false;
542
- }
543
- return {
544
- level,
545
- hasBasic: true,
546
- has256: level >= 2,
547
- has16m: level >= 3
548
- };
549
- }
550
- function supportsColor(haveStream, streamIsTTY) {
551
- if (forceColor === 0) {
552
- return 0;
553
- }
554
- if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
555
- return 3;
556
- }
557
- if (hasFlag("color=256")) {
558
- return 2;
559
- }
560
- if (haveStream && !streamIsTTY && forceColor === void 0) {
561
- return 0;
562
- }
563
- const min = forceColor || 0;
564
- if (env.TERM === "dumb") {
565
- return min;
566
- }
567
- if (process.platform === "win32") {
568
- const osRelease = os.release().split(".");
569
- if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
570
- return Number(osRelease[2]) >= 14931 ? 3 : 2;
571
- }
572
- return 1;
573
- }
574
- if ("CI" in env) {
575
- if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
576
- return 1;
577
- }
578
- return min;
579
- }
580
- if ("TEAMCITY_VERSION" in env) {
581
- return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
582
- }
583
- if (env.COLORTERM === "truecolor") {
584
- return 3;
585
- }
586
- if ("TERM_PROGRAM" in env) {
587
- const version = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
588
- switch (env.TERM_PROGRAM) {
589
- case "iTerm.app":
590
- return version >= 3 ? 3 : 2;
591
- case "Apple_Terminal":
592
- return 2;
593
- }
594
- }
595
- if (/-256(color)?$/i.test(env.TERM)) {
596
- return 2;
597
- }
598
- if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
599
- return 1;
600
- }
601
- if ("COLORTERM" in env) {
602
- return 1;
603
- }
604
- return min;
605
- }
606
- function getSupportLevel(stream) {
607
- const level = supportsColor(stream, stream && stream.isTTY);
608
- return translateLevel(level);
609
- }
610
- module2.exports = {
611
- supportsColor: getSupportLevel,
612
- stdout: translateLevel(supportsColor(true, tty.isatty(1))),
613
- stderr: translateLevel(supportsColor(true, tty.isatty(2)))
614
- };
615
- }
616
- });
617
-
618
- // ../../node_modules/list-it/node_modules/debug/src/node.js
619
- var require_node = __commonJS({
620
- "../../node_modules/list-it/node_modules/debug/src/node.js"(exports2, module2) {
621
- "use strict";
622
- var tty = require("tty");
623
- var util = require("util");
624
- exports2.init = init;
625
- exports2.log = log;
626
- exports2.formatArgs = formatArgs;
627
- exports2.save = save;
628
- exports2.load = load;
629
- exports2.useColors = useColors;
630
- exports2.destroy = util.deprecate(
631
- () => {
632
- },
633
- "Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."
634
- );
635
- exports2.colors = [6, 2, 3, 4, 5, 1];
636
- try {
637
- const supportsColor = require_supports_color();
638
- if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
639
- exports2.colors = [
640
- 20,
641
- 21,
642
- 26,
643
- 27,
644
- 32,
645
- 33,
646
- 38,
647
- 39,
648
- 40,
649
- 41,
650
- 42,
651
- 43,
652
- 44,
653
- 45,
654
- 56,
655
- 57,
656
- 62,
657
- 63,
658
- 68,
659
- 69,
660
- 74,
661
- 75,
662
- 76,
663
- 77,
664
- 78,
665
- 79,
666
- 80,
667
- 81,
668
- 92,
669
- 93,
670
- 98,
671
- 99,
672
- 112,
673
- 113,
674
- 128,
675
- 129,
676
- 134,
677
- 135,
678
- 148,
679
- 149,
680
- 160,
681
- 161,
682
- 162,
683
- 163,
684
- 164,
685
- 165,
686
- 166,
687
- 167,
688
- 168,
689
- 169,
690
- 170,
691
- 171,
692
- 172,
693
- 173,
694
- 178,
695
- 179,
696
- 184,
697
- 185,
698
- 196,
699
- 197,
700
- 198,
701
- 199,
702
- 200,
703
- 201,
704
- 202,
705
- 203,
706
- 204,
707
- 205,
708
- 206,
709
- 207,
710
- 208,
711
- 209,
712
- 214,
713
- 215,
714
- 220,
715
- 221
716
- ];
717
- }
718
- } catch (error) {
719
- }
720
- exports2.inspectOpts = Object.keys(process.env).filter((key) => {
721
- return /^debug_/i.test(key);
722
- }).reduce((obj, key) => {
723
- const prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, (_, k) => {
724
- return k.toUpperCase();
725
- });
726
- let val = process.env[key];
727
- if (/^(yes|on|true|enabled)$/i.test(val)) {
728
- val = true;
729
- } else if (/^(no|off|false|disabled)$/i.test(val)) {
730
- val = false;
731
- } else if (val === "null") {
732
- val = null;
733
- } else {
734
- val = Number(val);
735
- }
736
- obj[prop] = val;
737
- return obj;
738
- }, {});
739
- function useColors() {
740
- return "colors" in exports2.inspectOpts ? Boolean(exports2.inspectOpts.colors) : tty.isatty(process.stderr.fd);
741
- }
742
- function formatArgs(args2) {
743
- const { namespace: name, useColors: useColors2 } = this;
744
- if (useColors2) {
745
- const c = this.color;
746
- const colorCode = "\x1B[3" + (c < 8 ? c : "8;5;" + c);
747
- const prefix = ` ${colorCode};1m${name} \x1B[0m`;
748
- args2[0] = prefix + args2[0].split("\n").join("\n" + prefix);
749
- args2.push(colorCode + "m+" + module2.exports.humanize(this.diff) + "\x1B[0m");
750
- } else {
751
- args2[0] = getDate() + name + " " + args2[0];
752
- }
753
- }
754
- function getDate() {
755
- if (exports2.inspectOpts.hideDate) {
756
- return "";
757
- }
758
- return (/* @__PURE__ */ new Date()).toISOString() + " ";
759
- }
760
- function log(...args2) {
761
- return process.stderr.write(util.formatWithOptions(exports2.inspectOpts, ...args2) + "\n");
762
- }
763
- function save(namespaces) {
764
- if (namespaces) {
765
- process.env.DEBUG = namespaces;
766
- } else {
767
- delete process.env.DEBUG;
768
- }
769
- }
770
- function load() {
771
- return process.env.DEBUG;
772
- }
773
- function init(debug) {
774
- debug.inspectOpts = {};
775
- const keys = Object.keys(exports2.inspectOpts);
776
- for (let i = 0; i < keys.length; i++) {
777
- debug.inspectOpts[keys[i]] = exports2.inspectOpts[keys[i]];
778
- }
779
- }
780
- module2.exports = require_common()(exports2);
781
- var { formatters } = module2.exports;
782
- formatters.o = function(v) {
783
- this.inspectOpts.colors = this.useColors;
784
- return util.inspect(v, this.inspectOpts).split("\n").map((str) => str.trim()).join(" ");
785
- };
786
- formatters.O = function(v) {
787
- this.inspectOpts.colors = this.useColors;
788
- return util.inspect(v, this.inspectOpts);
789
- };
790
- }
791
- });
792
-
793
- // ../../node_modules/list-it/node_modules/debug/src/index.js
794
- var require_src = __commonJS({
795
- "../../node_modules/list-it/node_modules/debug/src/index.js"(exports2, module2) {
796
- "use strict";
797
- if (typeof process === "undefined" || process.type === "renderer" || process.browser === true || process.__nwjs) {
798
- module2.exports = require_browser();
799
- } else {
800
- module2.exports = require_node();
801
- }
802
- }
803
- });
804
-
805
- // ../../node_modules/eastasianwidth/eastasianwidth.js
806
- var require_eastasianwidth = __commonJS({
807
- "../../node_modules/eastasianwidth/eastasianwidth.js"(exports2, module2) {
808
- "use strict";
809
- var eaw = {};
810
- if ("undefined" == typeof module2) {
811
- window.eastasianwidth = eaw;
812
- } else {
813
- module2.exports = eaw;
814
- }
815
- eaw.eastAsianWidth = function(character) {
816
- var x = character.charCodeAt(0);
817
- var y = character.length == 2 ? character.charCodeAt(1) : 0;
818
- var codePoint = x;
819
- if (55296 <= x && x <= 56319 && (56320 <= y && y <= 57343)) {
820
- x &= 1023;
821
- y &= 1023;
822
- codePoint = x << 10 | y;
823
- codePoint += 65536;
824
- }
825
- if (12288 == codePoint || 65281 <= codePoint && codePoint <= 65376 || 65504 <= codePoint && codePoint <= 65510) {
826
- return "F";
827
- }
828
- if (8361 == codePoint || 65377 <= codePoint && codePoint <= 65470 || 65474 <= codePoint && codePoint <= 65479 || 65482 <= codePoint && codePoint <= 65487 || 65490 <= codePoint && codePoint <= 65495 || 65498 <= codePoint && codePoint <= 65500 || 65512 <= codePoint && codePoint <= 65518) {
829
- return "H";
830
- }
831
- if (4352 <= codePoint && codePoint <= 4447 || 4515 <= codePoint && codePoint <= 4519 || 4602 <= codePoint && codePoint <= 4607 || 9001 <= codePoint && codePoint <= 9002 || 11904 <= codePoint && codePoint <= 11929 || 11931 <= codePoint && codePoint <= 12019 || 12032 <= codePoint && codePoint <= 12245 || 12272 <= codePoint && codePoint <= 12283 || 12289 <= codePoint && codePoint <= 12350 || 12353 <= codePoint && codePoint <= 12438 || 12441 <= codePoint && codePoint <= 12543 || 12549 <= codePoint && codePoint <= 12589 || 12593 <= codePoint && codePoint <= 12686 || 12688 <= codePoint && codePoint <= 12730 || 12736 <= codePoint && codePoint <= 12771 || 12784 <= codePoint && codePoint <= 12830 || 12832 <= codePoint && codePoint <= 12871 || 12880 <= codePoint && codePoint <= 13054 || 13056 <= codePoint && codePoint <= 19903 || 19968 <= codePoint && codePoint <= 42124 || 42128 <= codePoint && codePoint <= 42182 || 43360 <= codePoint && codePoint <= 43388 || 44032 <= codePoint && codePoint <= 55203 || 55216 <= codePoint && codePoint <= 55238 || 55243 <= codePoint && codePoint <= 55291 || 63744 <= codePoint && codePoint <= 64255 || 65040 <= codePoint && codePoint <= 65049 || 65072 <= codePoint && codePoint <= 65106 || 65108 <= codePoint && codePoint <= 65126 || 65128 <= codePoint && codePoint <= 65131 || 110592 <= codePoint && codePoint <= 110593 || 127488 <= codePoint && codePoint <= 127490 || 127504 <= codePoint && codePoint <= 127546 || 127552 <= codePoint && codePoint <= 127560 || 127568 <= codePoint && codePoint <= 127569 || 131072 <= codePoint && codePoint <= 194367 || 177984 <= codePoint && codePoint <= 196605 || 196608 <= codePoint && codePoint <= 262141) {
832
- return "W";
833
- }
834
- if (32 <= codePoint && codePoint <= 126 || 162 <= codePoint && codePoint <= 163 || 165 <= codePoint && codePoint <= 166 || 172 == codePoint || 175 == codePoint || 10214 <= codePoint && codePoint <= 10221 || 10629 <= codePoint && codePoint <= 10630) {
835
- return "Na";
836
- }
837
- if (161 == codePoint || 164 == codePoint || 167 <= codePoint && codePoint <= 168 || 170 == codePoint || 173 <= codePoint && codePoint <= 174 || 176 <= codePoint && codePoint <= 180 || 182 <= codePoint && codePoint <= 186 || 188 <= codePoint && codePoint <= 191 || 198 == codePoint || 208 == codePoint || 215 <= codePoint && codePoint <= 216 || 222 <= codePoint && codePoint <= 225 || 230 == codePoint || 232 <= codePoint && codePoint <= 234 || 236 <= codePoint && codePoint <= 237 || 240 == codePoint || 242 <= codePoint && codePoint <= 243 || 247 <= codePoint && codePoint <= 250 || 252 == codePoint || 254 == codePoint || 257 == codePoint || 273 == codePoint || 275 == codePoint || 283 == codePoint || 294 <= codePoint && codePoint <= 295 || 299 == codePoint || 305 <= codePoint && codePoint <= 307 || 312 == codePoint || 319 <= codePoint && codePoint <= 322 || 324 == codePoint || 328 <= codePoint && codePoint <= 331 || 333 == codePoint || 338 <= codePoint && codePoint <= 339 || 358 <= codePoint && codePoint <= 359 || 363 == codePoint || 462 == codePoint || 464 == codePoint || 466 == codePoint || 468 == codePoint || 470 == codePoint || 472 == codePoint || 474 == codePoint || 476 == codePoint || 593 == codePoint || 609 == codePoint || 708 == codePoint || 711 == codePoint || 713 <= codePoint && codePoint <= 715 || 717 == codePoint || 720 == codePoint || 728 <= codePoint && codePoint <= 731 || 733 == codePoint || 735 == codePoint || 768 <= codePoint && codePoint <= 879 || 913 <= codePoint && codePoint <= 929 || 931 <= codePoint && codePoint <= 937 || 945 <= codePoint && codePoint <= 961 || 963 <= codePoint && codePoint <= 969 || 1025 == codePoint || 1040 <= codePoint && codePoint <= 1103 || 1105 == codePoint || 8208 == codePoint || 8211 <= codePoint && codePoint <= 8214 || 8216 <= codePoint && codePoint <= 8217 || 8220 <= codePoint && codePoint <= 8221 || 8224 <= codePoint && codePoint <= 8226 || 8228 <= codePoint && codePoint <= 8231 || 8240 == codePoint || 8242 <= codePoint && codePoint <= 8243 || 8245 == codePoint || 8251 == codePoint || 8254 == codePoint || 8308 == codePoint || 8319 == codePoint || 8321 <= codePoint && codePoint <= 8324 || 8364 == codePoint || 8451 == codePoint || 8453 == codePoint || 8457 == codePoint || 8467 == codePoint || 8470 == codePoint || 8481 <= codePoint && codePoint <= 8482 || 8486 == codePoint || 8491 == codePoint || 8531 <= codePoint && codePoint <= 8532 || 8539 <= codePoint && codePoint <= 8542 || 8544 <= codePoint && codePoint <= 8555 || 8560 <= codePoint && codePoint <= 8569 || 8585 == codePoint || 8592 <= codePoint && codePoint <= 8601 || 8632 <= codePoint && codePoint <= 8633 || 8658 == codePoint || 8660 == codePoint || 8679 == codePoint || 8704 == codePoint || 8706 <= codePoint && codePoint <= 8707 || 8711 <= codePoint && codePoint <= 8712 || 8715 == codePoint || 8719 == codePoint || 8721 == codePoint || 8725 == codePoint || 8730 == codePoint || 8733 <= codePoint && codePoint <= 8736 || 8739 == codePoint || 8741 == codePoint || 8743 <= codePoint && codePoint <= 8748 || 8750 == codePoint || 8756 <= codePoint && codePoint <= 8759 || 8764 <= codePoint && codePoint <= 8765 || 8776 == codePoint || 8780 == codePoint || 8786 == codePoint || 8800 <= codePoint && codePoint <= 8801 || 8804 <= codePoint && codePoint <= 8807 || 8810 <= codePoint && codePoint <= 8811 || 8814 <= codePoint && codePoint <= 8815 || 8834 <= codePoint && codePoint <= 8835 || 8838 <= codePoint && codePoint <= 8839 || 8853 == codePoint || 8857 == codePoint || 8869 == codePoint || 8895 == codePoint || 8978 == codePoint || 9312 <= codePoint && codePoint <= 9449 || 9451 <= codePoint && codePoint <= 9547 || 9552 <= codePoint && codePoint <= 9587 || 9600 <= codePoint && codePoint <= 9615 || 9618 <= codePoint && codePoint <= 9621 || 9632 <= codePoint && codePoint <= 9633 || 9635 <= codePoint && codePoint <= 9641 || 9650 <= codePoint && codePoint <= 9651 || 9654 <= codePoint && codePoint <= 9655 || 9660 <= codePoint && codePoint <= 9661 || 9664 <= codePoint && codePoint <= 9665 || 9670 <= codePoint && codePoint <= 9672 || 9675 == codePoint || 9678 <= codePoint && codePoint <= 9681 || 9698 <= codePoint && codePoint <= 9701 || 9711 == codePoint || 9733 <= codePoint && codePoint <= 9734 || 9737 == codePoint || 9742 <= codePoint && codePoint <= 9743 || 9748 <= codePoint && codePoint <= 9749 || 9756 == codePoint || 9758 == codePoint || 9792 == codePoint || 9794 == codePoint || 9824 <= codePoint && codePoint <= 9825 || 9827 <= codePoint && codePoint <= 9829 || 9831 <= codePoint && codePoint <= 9834 || 9836 <= codePoint && codePoint <= 9837 || 9839 == codePoint || 9886 <= codePoint && codePoint <= 9887 || 9918 <= codePoint && codePoint <= 9919 || 9924 <= codePoint && codePoint <= 9933 || 9935 <= codePoint && codePoint <= 9953 || 9955 == codePoint || 9960 <= codePoint && codePoint <= 9983 || 10045 == codePoint || 10071 == codePoint || 10102 <= codePoint && codePoint <= 10111 || 11093 <= codePoint && codePoint <= 11097 || 12872 <= codePoint && codePoint <= 12879 || 57344 <= codePoint && codePoint <= 63743 || 65024 <= codePoint && codePoint <= 65039 || 65533 == codePoint || 127232 <= codePoint && codePoint <= 127242 || 127248 <= codePoint && codePoint <= 127277 || 127280 <= codePoint && codePoint <= 127337 || 127344 <= codePoint && codePoint <= 127386 || 917760 <= codePoint && codePoint <= 917999 || 983040 <= codePoint && codePoint <= 1048573 || 1048576 <= codePoint && codePoint <= 1114109) {
838
- return "A";
839
- }
840
- return "N";
841
- };
842
- eaw.characterLength = function(character) {
843
- var code = this.eastAsianWidth(character);
844
- if (code == "F" || code == "W" || code == "A") {
845
- return 2;
846
- } else {
847
- return 1;
848
- }
849
- };
850
- function stringToArray(string) {
851
- return string.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) || [];
852
- }
853
- eaw.length = function(string) {
854
- var characters = stringToArray(string);
855
- var len = 0;
856
- for (var i = 0; i < characters.length; i++) {
857
- len = len + this.characterLength(characters[i]);
858
- }
859
- return len;
860
- };
861
- eaw.slice = function(text, start, end) {
862
- textLen = eaw.length(text);
863
- start = start ? start : 0;
864
- end = end ? end : 1;
865
- if (start < 0) {
866
- start = textLen + start;
867
- }
868
- if (end < 0) {
869
- end = textLen + end;
870
- }
871
- var result = "";
872
- var eawLen = 0;
873
- var chars = stringToArray(text);
874
- for (var i = 0; i < chars.length; i++) {
875
- var char = chars[i];
876
- var charLen = eaw.length(char);
877
- if (eawLen >= start - (charLen == 2 ? 1 : 0)) {
878
- if (eawLen + charLen <= end) {
879
- result += char;
880
- } else {
881
- break;
882
- }
883
- }
884
- eawLen += charLen;
885
- }
886
- return result;
887
- };
888
- }
889
- });
890
-
891
- // ../../node_modules/list-it/lib/data-cell.js
892
- var require_data_cell = __commonJS({
893
- "../../node_modules/list-it/lib/data-cell.js"(exports2, module2) {
894
- "use strict";
895
- var eaw = require_eastasianwidth();
896
- function DataCell() {
897
- this.data = "";
898
- }
899
- module2.exports = DataCell;
900
- DataCell.prototype.getData = function() {
901
- return this.data;
902
- };
903
- DataCell.prototype.setData = function(data) {
904
- this.data = data;
905
- };
906
- DataCell.prototype.visibleLength = function() {
907
- if (typeof this.data != "string") {
908
- return ("" + this.data).length;
909
- }
910
- return DataCell.visibleLength(this.data);
911
- };
912
- DataCell.visibleLength = function(data) {
913
- const s = data.replace(/\x1b[^m]*m/g, "");
914
- return eaw.length(s);
915
- };
916
- }
917
- });
918
-
919
- // ../../node_modules/list-it/lib/row.js
920
- var require_row = __commonJS({
921
- "../../node_modules/list-it/lib/row.js"(exports2, module2) {
922
- "use strict";
923
- function Row() {
924
- this.cells = [];
925
- this.empty = true;
926
- this.fixed = false;
927
- }
928
- module2.exports = Row;
929
- Row.prototype.getCellLength = function() {
930
- return this.cells.length;
931
- };
932
- Row.prototype.getCell = function(idx) {
933
- return this.cells[idx];
934
- };
935
- Row.prototype.pushCell = function(cell) {
936
- if (this.isFixed()) {
937
- throw "pushCell Fail, The row was already fixed.";
938
- }
939
- this.empty = false;
940
- return this.cells.push(cell);
941
- };
942
- Row.prototype.fix = function() {
943
- this.fixed = true;
944
- };
945
- Row.prototype.isEmpty = function() {
946
- return this.empty;
947
- };
948
- Row.prototype.isFixed = function() {
949
- return this.fixed;
950
- };
951
- }
952
- });
953
-
954
- // ../../node_modules/list-it/lib/column.js
955
- var require_column = __commonJS({
956
- "../../node_modules/list-it/lib/column.js"(exports2, module2) {
957
- "use strict";
958
- var DataCell = require_data_cell();
959
- function Column() {
960
- this.opt = {
961
- "autoAlign": false
962
- };
963
- this.width = 0;
964
- this.textWidth = null;
965
- this.intLen = 0;
966
- this.fracLen = 0;
967
- this.expLen = 0;
968
- this.cellAtRow = {};
969
- this.header = null;
970
- }
971
- module2.exports = Column;
972
- Column.prototype.getWidth = function() {
973
- return this.width;
974
- };
975
- Column.prototype.setTextWidth = function(textWidth) {
976
- this.textWidth = textWidth;
977
- };
978
- Column.prototype.setCellAt = function(row, cell) {
979
- this.cellAtRow[row] = cell;
980
- };
981
- Column.prototype.setHeader = function(header) {
982
- this.header = header;
983
- };
984
- Column.prototype.hasHeader = function() {
985
- return this.header != null;
986
- };
987
- Column.prototype.updateWidth = function() {
988
- const headerWidth = !this.hasHeader() ? 0 : DataCell.visibleLength("" + this.header);
989
- this.width = headerWidth;
990
- Object.keys(this.cellAtRow).forEach((key) => {
991
- const cell = this.cellAtRow[key];
992
- const data = cell.getData();
993
- let width = cell.visibleLength();
994
- if (typeof data == "number") {
995
- if (this.opt.autoAlign) {
996
- this.updateNumWidth(data);
997
- width = this.getNumMaxWidth();
998
- }
999
- }
1000
- if (width > this.width) {
1001
- this.width = width;
1002
- }
1003
- if (typeof data == "string") {
1004
- if (this.textWidth && this.textWidth > headerWidth) {
1005
- if (this.width > this.textWidth) {
1006
- this.width = this.textWidth;
1007
- }
1008
- }
1009
- }
1010
- });
1011
- };
1012
- Column.prototype.formatColumnHeader = function() {
1013
- if (!this.hasHeader()) {
1014
- return null;
1015
- }
1016
- const width = this.getWidth();
1017
- const header = this.header;
1018
- const headerWidth = DataCell.visibleLength("" + header);
1019
- if (header.length == headerWidth && width - headerWidth <= 0) {
1020
- return ("" + header).substring(0, width);
1021
- }
1022
- return "" + header + " ".repeat(width - headerWidth);
1023
- };
1024
- Column.prototype.formatCell = function(data) {
1025
- const width = this.getWidth();
1026
- if (this.opt.autoAlign) {
1027
- if (typeof data == "number") {
1028
- return this.makeAutoAlignNum(data).padStart(width, " ");
1029
- }
1030
- }
1031
- const dataWidth = DataCell.visibleLength("" + data);
1032
- if (data.length == dataWidth && width - dataWidth <= 0) {
1033
- return ("" + data).substring(0, width);
1034
- }
1035
- return "" + data + " ".repeat(width - dataWidth);
1036
- };
1037
- Column.prototype.setAutoAlign = function(autoAlign) {
1038
- this.opt.autoAlign = autoAlign;
1039
- };
1040
- Column.prototype.updateNumWidth = function(num) {
1041
- const numInfo = this.analyzeNumber(num);
1042
- const intLen = numInfo.intStr.length;
1043
- const fracLen = numInfo.fracStr.length;
1044
- const expLen = numInfo.expStr.length;
1045
- if (intLen > this.intLen) {
1046
- this.intLen = intLen;
1047
- }
1048
- if (fracLen > this.fracLen) {
1049
- this.fracLen = fracLen;
1050
- }
1051
- if (expLen > this.expLen) {
1052
- this.expLen = expLen;
1053
- }
1054
- };
1055
- Column.prototype.getNumMaxWidth = function() {
1056
- return this.intLen + this.fracLen + (this.fracLen > 0 ? 1 : 0) + this.expLen + (this.expLen > 0 ? 1 : 0);
1057
- };
1058
- Column.prototype.makeAutoAlignNum = function(num) {
1059
- const numInfo = this.analyzeNumber(num);
1060
- const intStr = numInfo.intStr.padStart(this.intLen, " ");
1061
- const fracStr = numInfo.expStr != "" ? numInfo.fracStr.padEnd(this.fracLen, "0") : numInfo.fracStr.padEnd(this.fracLen, " ");
1062
- const expStr = numInfo.expStr.padEnd(this.expLen, " ");
1063
- if (numInfo.expStr != "") {
1064
- return [intStr, ".", fracStr, "e", expStr].join("");
1065
- }
1066
- if (numInfo.pointPos >= 0) {
1067
- if (this.expLen > 0) {
1068
- return [intStr, ".", fracStr, " ", expStr].join("");
1069
- }
1070
- return [intStr, ".", fracStr].join("");
1071
- } else if (this.fracLen == 0) {
1072
- return intStr;
1073
- }
1074
- if (this.expLen > 0) {
1075
- return [intStr, ".0", fracStr.substr(1), " ", expStr].join("");
1076
- }
1077
- return [intStr, ".0", fracStr.substr(1)].join("");
1078
- };
1079
- Column.prototype.analyzeNumber = function(num) {
1080
- const s = "" + num;
1081
- let intStr = "";
1082
- let fracStr = "";
1083
- const pointPos = s.indexOf(".");
1084
- const expIndex = s.indexOf("e");
1085
- if (expIndex >= 0) {
1086
- if (pointPos < 0) {
1087
- return {
1088
- pointPos: expIndex,
1089
- intStr: s.substr(0, expIndex),
1090
- fracStr: "0",
1091
- expStr: s.substr(expIndex + 1)
1092
- };
1093
- }
1094
- return {
1095
- pointPos,
1096
- intStr: s.substr(0, pointPos),
1097
- fracStr: s.substring(pointPos + 1, expIndex),
1098
- expStr: s.substr(expIndex + 1)
1099
- };
1100
- }
1101
- if (pointPos < 0) {
1102
- intStr = s;
1103
- } else {
1104
- intStr = s.substr(0, pointPos);
1105
- fracStr = s.substr(pointPos + 1);
1106
- }
1107
- return {
1108
- "pointPos": pointPos,
1109
- "intStr": intStr,
1110
- "fracStr": fracStr,
1111
- "expStr": ""
1112
- };
1113
- };
1114
- }
1115
- });
1116
-
1117
- // ../../node_modules/ansi-escape-sequences/dist/index.cjs
1118
- var require_dist = __commonJS({
1119
- "../../node_modules/ansi-escape-sequences/dist/index.cjs"(exports2, module2) {
1120
- "use strict";
1121
- function isObject(input) {
1122
- return typeof input === "object" && input !== null;
1123
- }
1124
- function isArrayLike(input) {
1125
- return isObject(input) && typeof input.length === "number";
1126
- }
1127
- function arrayify(input) {
1128
- if (Array.isArray(input)) {
1129
- return input;
1130
- } else if (input === void 0) {
1131
- return [];
1132
- } else if (isArrayLike(input) || input instanceof Set) {
1133
- return Array.from(input);
1134
- } else {
1135
- return [input];
1136
- }
1137
- }
1138
- var csi = "\x1B[";
1139
- var ansi = {};
1140
- ansi.style = {
1141
- reset: "\x1B[0m",
1142
- bold: "\x1B[1m",
1143
- italic: "\x1B[3m",
1144
- underline: "\x1B[4m",
1145
- fontDefault: "\x1B[10m",
1146
- font2: "\x1B[11m",
1147
- font3: "\x1B[12m",
1148
- font4: "\x1B[13m",
1149
- font5: "\x1B[14m",
1150
- font6: "\x1B[15m",
1151
- imageNegative: "\x1B[7m",
1152
- imagePositive: "\x1B[27m",
1153
- black: "\x1B[30m",
1154
- red: "\x1B[31m",
1155
- green: "\x1B[32m",
1156
- yellow: "\x1B[33m",
1157
- blue: "\x1B[34m",
1158
- magenta: "\x1B[35m",
1159
- cyan: "\x1B[36m",
1160
- white: "\x1B[37m",
1161
- grey: "\x1B[90m",
1162
- gray: "\x1B[90m",
1163
- brightRed: "\x1B[91m",
1164
- brightGreen: "\x1B[92m",
1165
- brightYellow: "\x1B[93m",
1166
- brightBlue: "\x1B[94m",
1167
- brightMagenta: "\x1B[95m",
1168
- brightCyan: "\x1B[96m",
1169
- brightWhite: "\x1B[97m",
1170
- "bg-black": "\x1B[40m",
1171
- "bg-red": "\x1B[41m",
1172
- "bg-green": "\x1B[42m",
1173
- "bg-yellow": "\x1B[43m",
1174
- "bg-blue": "\x1B[44m",
1175
- "bg-magenta": "\x1B[45m",
1176
- "bg-cyan": "\x1B[46m",
1177
- "bg-white": "\x1B[47m",
1178
- "bg-grey": "\x1B[100m",
1179
- "bg-gray": "\x1B[100m",
1180
- "bg-brightRed": "\x1B[101m",
1181
- "bg-brightGreen": "\x1B[102m",
1182
- "bg-brightYellow": "\x1B[103m",
1183
- "bg-brightBlue": "\x1B[104m",
1184
- "bg-brightMagenta": "\x1B[105m",
1185
- "bg-brightCyan": "\x1B[106m",
1186
- "bg-brightWhite": "\x1B[107m"
1187
- };
1188
- ansi.rgb = function(r, g, b) {
1189
- return `\x1B[38;2;${r};${g};${b}m`;
1190
- };
1191
- ansi.bgRgb = function(r, g, b) {
1192
- return `\x1B[48;2;${r};${g};${b}m`;
1193
- };
1194
- ansi.styles = function(styles) {
1195
- styles = arrayify(styles);
1196
- return styles.map(function(effect) {
1197
- const rgbMatches = effect.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
1198
- const bgRgbMatches = effect.match(/bg-rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
1199
- if (bgRgbMatches) {
1200
- const [full, r, g, b] = bgRgbMatches;
1201
- return ansi.bgRgb(r, g, b);
1202
- } else if (rgbMatches) {
1203
- const [full, r, g, b] = rgbMatches;
1204
- return ansi.rgb(r, g, b);
1205
- } else {
1206
- return ansi.style[effect];
1207
- }
1208
- }).join("");
1209
- };
1210
- ansi.format = function(str, styleArray) {
1211
- const re = /\[([\w\s-\(\),]+)\]{([^]*?)}/;
1212
- let matches;
1213
- str = String(str);
1214
- if (!str) return "";
1215
- while (matches = str.match(re)) {
1216
- const inlineStyles = matches[1].split(/\s+/);
1217
- const inlineString = matches[2];
1218
- str = str.replace(matches[0], ansi.format(inlineString, inlineStyles));
1219
- }
1220
- return styleArray && styleArray.length ? ansi.styles(styleArray) + str + ansi.style.reset : str;
1221
- };
1222
- ansi.cursor = {
1223
- /**
1224
- * Moves the cursor `lines` cells up. If the cursor is already at the edge of the screen, this has no effect
1225
- * @param [lines=1] {number}
1226
- * @return {string}
1227
- */
1228
- up: function(lines) {
1229
- return csi + (lines || 1) + "A";
1230
- },
1231
- /**
1232
- * Moves the cursor `lines` cells down. If the cursor is already at the edge of the screen, this has no effect
1233
- * @param [lines=1] {number}
1234
- * @return {string}
1235
- */
1236
- down: function(lines) {
1237
- return csi + (lines || 1) + "B";
1238
- },
1239
- /**
1240
- * Moves the cursor `lines` cells forward. If the cursor is already at the edge of the screen, this has no effect
1241
- * @param [lines=1] {number}
1242
- * @return {string}
1243
- */
1244
- forward: function(lines) {
1245
- return csi + (lines || 1) + "C";
1246
- },
1247
- /**
1248
- * Moves the cursor `lines` cells back. If the cursor is already at the edge of the screen, this has no effect
1249
- * @param [lines=1] {number}
1250
- * @return {string}
1251
- */
1252
- back: function(lines) {
1253
- return csi + (lines || 1) + "D";
1254
- },
1255
- /**
1256
- * Moves cursor to beginning of the line n lines down.
1257
- * @param [lines=1] {number}
1258
- * @return {string}
1259
- */
1260
- nextLine: function(lines) {
1261
- return csi + (lines || 1) + "E";
1262
- },
1263
- /**
1264
- * Moves cursor to beginning of the line n lines up.
1265
- * @param [lines=1] {number}
1266
- * @return {string}
1267
- */
1268
- previousLine: function(lines) {
1269
- return csi + (lines || 1) + "F";
1270
- },
1271
- /**
1272
- * Moves the cursor to column n.
1273
- * @param n {number} - column number
1274
- * @return {string}
1275
- */
1276
- horizontalAbsolute: function(n) {
1277
- return csi + n + "G";
1278
- },
1279
- /**
1280
- * Moves the cursor to row n, column m. The values are 1-based, and default to 1 (top left corner) if omitted.
1281
- * @param n {number} - row number
1282
- * @param m {number} - column number
1283
- * @return {string}
1284
- */
1285
- position: function(n, m) {
1286
- return csi + (n || 1) + ";" + (m || 1) + "H";
1287
- },
1288
- /**
1289
- * Hides the cursor
1290
- */
1291
- hide: csi + "?25l",
1292
- /**
1293
- * Shows the cursor
1294
- */
1295
- show: csi + "?25h"
1296
- };
1297
- ansi.erase = {
1298
- /**
1299
- * Clears part of the screen. If n is 0 (or missing), clear from cursor to end of screen. If n is 1, clear from cursor to beginning of the screen. If n is 2, clear entire screen.
1300
- * @param n {number}
1301
- * @return {string}
1302
- */
1303
- display: function(n) {
1304
- return csi + (n || 0) + "J";
1305
- },
1306
- /**
1307
- * Erases part of the line. If n is zero (or missing), clear from cursor to the end of the line. If n is one, clear from cursor to beginning of the line. If n is two, clear entire line. Cursor position does not change.
1308
- * @param n {number}
1309
- * @return {string}
1310
- */
1311
- inLine: function(n) {
1312
- return csi + (n || 0) + "K";
1313
- }
1314
- };
1315
- module2.exports = ansi;
1316
- }
1317
- });
1318
-
1319
- // ../../node_modules/list-it/lib/list-it-buffer.js
1320
- var require_list_it_buffer = __commonJS({
1321
- "../../node_modules/list-it/lib/list-it-buffer.js"(exports2, module2) {
1322
- "use strict";
1323
- var debug = require_src()("list-it-buffer");
1324
- var DataCell = require_data_cell();
1325
- var Row = require_row();
1326
- var Column = require_column();
1327
- var ansi = require_dist();
1328
- function ListItBuffer(opt) {
1329
- opt = opt || {};
1330
- this.opt = {
1331
- "autoAlign": true,
1332
- "columnWidth": null,
1333
- "header": null,
1334
- "headerBold": false,
1335
- "headerColor": "",
1336
- "headerUnderline": false
1337
- };
1338
- if (opt.header != null && !Array.isArray(opt.header)) {
1339
- throw new Error([
1340
- `Invalid header was specified. It must be an array, but (${JSON.stringify(opt.header)}):${typeof opt.header} was specified.`
1341
- ].join(" "));
1342
- }
1343
- if (opt.headerColor && !(opt.headerColor in COLORS)) {
1344
- throw new Error([
1345
- `Invalid color ${JSON.stringify(opt.headerColor)} was specified.`,
1346
- "Available color names:",
1347
- ...AVAILABLE_COLORS.map((color) => `* ${JSON.stringify(color)}`)
1348
- ].join("\n"));
1349
- }
1350
- Object.keys(this.opt).forEach((key) => {
1351
- if (key in opt) {
1352
- this.opt[key] = opt[key];
1353
- }
1354
- });
1355
- this.lines = [];
1356
- this.columns = [];
1357
- this.columnWidth = this.opt.columnWidth;
1358
- if (this.opt.header) {
1359
- this.setHeaderRow(this.opt.header);
1360
- }
1361
- }
1362
- module2.exports = ListItBuffer;
1363
- ListItBuffer.prototype.nl = function() {
1364
- const lastRowIndex = this.lines.length - 1;
1365
- if (lastRowIndex >= 0 && !this.lines[lastRowIndex].isFixed()) {
1366
- this.lines[lastRowIndex].fix();
1367
- }
1368
- this.pushNewRow();
1369
- return this;
1370
- };
1371
- ListItBuffer.prototype.d = function(data) {
1372
- if (arguments.length > 1) {
1373
- const array = Array.apply(null, arguments);
1374
- if (ListItBuffer.isMultiDimensionalArray(array)) {
1375
- array.forEach((row) => this.addRow(row));
1376
- } else {
1377
- array.forEach((data2) => this.d(data2));
1378
- }
1379
- return this;
1380
- }
1381
- if (Array.isArray(data)) {
1382
- if (ListItBuffer.isMultiDimensionalArray(data)) {
1383
- data.forEach((row) => this.addRow(row));
1384
- } else if (ListItBuffer.isObjectArray(data)) {
1385
- data = objectArrayToTable(data);
1386
- if (!this.header && (this.opt.headerBold || this.opt.headerColor || this.opt.headerUnderline)) {
1387
- this.setHeaderRow(data.shift());
1388
- }
1389
- data.forEach((row) => this.addRow(row));
1390
- } else {
1391
- this.addRow(data);
1392
- }
1393
- return this;
1394
- }
1395
- const rowidx = this.lines.length - 1;
1396
- if (rowidx < 0 || this.lines[rowidx].isFixed()) {
1397
- this.pushNewRow();
1398
- }
1399
- const cell = new DataCell();
1400
- cell.setData(data);
1401
- const iRow = this.lines.length - 1;
1402
- let iCol = this.lines[iRow].getCellLength();
1403
- if (iCol >= this.columns.length) {
1404
- this.addColumn();
1405
- }
1406
- this.columns[iCol].setCellAt(iRow, cell);
1407
- this.lines[iRow].pushCell(cell);
1408
- return this;
1409
- };
1410
- ListItBuffer.isMultiDimensionalArray = function(arr) {
1411
- if (!Array.isArray(arr)) {
1412
- throw Error("The parameter arr must be array");
1413
- }
1414
- for (let element of arr) {
1415
- if (!Array.isArray(element)) {
1416
- return false;
1417
- }
1418
- }
1419
- return true;
1420
- };
1421
- ListItBuffer.isObjectArray = function(arr) {
1422
- if (!Array.isArray(arr)) {
1423
- throw Error("The parameter arr must be array");
1424
- }
1425
- const ctor = arr[0].constructor;
1426
- for (let element of arr) {
1427
- if (typeof element != "object") {
1428
- return false;
1429
- } else {
1430
- if (element.constructor.name != ctor.name) {
1431
- return false;
1432
- }
1433
- }
1434
- }
1435
- return true;
1436
- };
1437
- ListItBuffer.prototype.addRow = function(row) {
1438
- row.forEach((col) => {
1439
- switch (typeof col) {
1440
- case "string":
1441
- case "number":
1442
- this.d(col);
1443
- break;
1444
- default:
1445
- this.d(col != null ? col.toString() : "(null)");
1446
- break;
1447
- }
1448
- });
1449
- this.nl();
1450
- };
1451
- ListItBuffer.prototype.pushNewRow = function() {
1452
- this.lines.push(new Row());
1453
- };
1454
- ListItBuffer.prototype.toString = function() {
1455
- const rows = [];
1456
- this.columns.forEach((column, iCol) => {
1457
- if (this.header != null) {
1458
- column.setHeader(this.header[iCol] || "");
1459
- }
1460
- column.setTextWidth(this.getColumnWidth(iCol));
1461
- column.updateWidth();
1462
- });
1463
- if (this.header != null) {
1464
- const headerLine = this.applyHeaderStyleOption(
1465
- this.columns.map((column) => column.formatColumnHeader()).join(" ")
1466
- );
1467
- rows.push(headerLine);
1468
- const headerUnderline = this.generateHeaderUnderline();
1469
- if (headerUnderline) {
1470
- rows.push(headerUnderline);
1471
- }
1472
- }
1473
- this.lines.forEach((line) => {
1474
- if (line.isFixed() || !line.isEmpty()) {
1475
- if (line.isEmpty()) {
1476
- rows.push("\n");
1477
- } else {
1478
- rows.push(this.columns.map((column, iCol) => {
1479
- const cell = line.getCell(iCol);
1480
- const data = cell.getData();
1481
- return column.formatCell(data);
1482
- }).join(" "));
1483
- }
1484
- }
1485
- });
1486
- return rows.join("\n");
1487
- };
1488
- var COLORS = {};
1489
- var BGCOLORS = {};
1490
- Object.keys(ansi.style).forEach((key) => {
1491
- const value = ansi.style[key];
1492
- if (/^bg-/.test(key)) {
1493
- BGCOLORS[key.substr(3)] = value;
1494
- } else {
1495
- COLORS[key] = value;
1496
- debug(`COLOR-KEY: ${key}`);
1497
- }
1498
- });
1499
- Object.keys(COLORS).forEach((key) => {
1500
- if (!(key in BGCOLORS)) {
1501
- delete COLORS[key];
1502
- debug(`remove COLOR-KEY: ${key}`);
1503
- }
1504
- });
1505
- var AVAILABLE_COLORS = Object.keys(COLORS);
1506
- debug(`AVAILABLE_COLORS:${JSON.stringify(AVAILABLE_COLORS)}`);
1507
- ListItBuffer.prototype.applyHeaderStyleOption = function(line) {
1508
- if (!this.opt.headerBold && !this.opt.headerColor) {
1509
- return line;
1510
- }
1511
- const textBuffer = [];
1512
- if (this.opt.headerBold) {
1513
- textBuffer.push(ansi.style.bold);
1514
- }
1515
- if (this.opt.headerColor) {
1516
- textBuffer.push(COLORS[this.opt.headerColor]);
1517
- }
1518
- textBuffer.push(line);
1519
- textBuffer.push(ansi.style.reset);
1520
- return textBuffer.join("");
1521
- };
1522
- ListItBuffer.prototype.generateHeaderUnderline = function() {
1523
- if (!this.opt.headerUnderline) {
1524
- return null;
1525
- }
1526
- if (this.header == null) {
1527
- return null;
1528
- }
1529
- return this.columns.map(
1530
- (column) => "-".repeat(column.getWidth())
1531
- ).join(" ");
1532
- };
1533
- function objectArrayToTable(objects) {
1534
- const keys = Object.keys(objects[0]);
1535
- const body = objects.map((item) => keys.map((key) => {
1536
- if (item[key] != null && typeof item[key] == "object" && item[key].constructor.name == "Date") {
1537
- return item[key].toISOString();
1538
- }
1539
- return item[key];
1540
- }));
1541
- return [keys, ...body];
1542
- }
1543
- ListItBuffer.prototype.setColumnWidth = function(indexOfColumns, width) {
1544
- this.columnWidth = this.columnWidth || [];
1545
- if (typeof indexOfColumns !== "number") {
1546
- throw new Error("indexOfColumns must be a number");
1547
- }
1548
- if (!width) {
1549
- delete this.columnWidth[indexOfColumns];
1550
- } else {
1551
- if (typeof width !== "number") {
1552
- throw new Error("width must be a number");
1553
- }
1554
- this.columnWidth[indexOfColumns] = width;
1555
- }
1556
- return this;
1557
- };
1558
- ListItBuffer.prototype.setColumnWidthAll = function(widthForAll) {
1559
- if (widthForAll != null && !Array.isArray(widthForAll) && typeof widthForAll !== "number") {
1560
- throw new Error(
1561
- "widthForAll must be one of a null, an Array or a number"
1562
- );
1563
- }
1564
- if (Array.isArray(widthForAll)) {
1565
- for (let i = 0; i < widthForAll.length; i++) {
1566
- const width = widthForAll[i];
1567
- if (width != void 0 && typeof width !== "number") {
1568
- throw new Error(
1569
- `widthForAll[${i}] must be an undefined or a number`
1570
- );
1571
- }
1572
- }
1573
- }
1574
- this.columnWidth = widthForAll;
1575
- return this;
1576
- };
1577
- ListItBuffer.prototype.getColumnWidth = function(indexOfColumns) {
1578
- if (Array.isArray(this.columnWidth)) {
1579
- return this.columnWidth[indexOfColumns];
1580
- }
1581
- return this.columnWidth;
1582
- };
1583
- ListItBuffer.prototype.setHeaderRow = function(header) {
1584
- if (header && !Array.isArray(header)) {
1585
- throw new Error([
1586
- "The header must be an array,",
1587
- `but ${typeof header} was specified.`,
1588
- `header: ${JSON.stringify(header)}`
1589
- ].join(" "));
1590
- }
1591
- this.header = header;
1592
- if (this.header == null) {
1593
- this.columns.forEach((column) => column.setHeader(null));
1594
- } else {
1595
- this.header.forEach((headerText, iCol) => {
1596
- if (iCol >= this.columns.length) {
1597
- this.addColumn(headerText);
1598
- }
1599
- });
1600
- }
1601
- return this;
1602
- };
1603
- ListItBuffer.prototype.addColumn = function(headerText) {
1604
- const column = new Column();
1605
- if (headerText) {
1606
- column.setHeader(headerText);
1607
- }
1608
- if (this.opt.autoAlign) {
1609
- column.setAutoAlign(true);
1610
- }
1611
- this.columns.push(column);
1612
- };
1613
- }
1614
- });
1615
-
1616
- // ../../node_modules/list-it/index.js
1617
- var require_list_it = __commonJS({
1618
- "../../node_modules/list-it/index.js"(exports2, module2) {
1619
- "use strict";
1620
- var ListItBuffer = require_list_it_buffer();
1621
- function ListIt2(opt) {
1622
- ListItBuffer.call(this, opt);
1623
- }
1624
- ListIt2.prototype = new ListItBuffer();
1625
- ListIt2.buffer = function(opt) {
1626
- opt = opt || {};
1627
- if (!("autoAlign" in opt)) {
1628
- opt.autoAlign = false;
1629
- }
1630
- return new ListIt2(opt);
1631
- };
1632
- module2.exports = ListIt2;
1633
- }
1634
- });
1635
-
1636
30
  // src/scripts/signalsDaemon.ts
1637
31
  var signalsDaemon_exports = {};
1638
32
  __export(signalsDaemon_exports, {
@@ -1643,25 +37,26 @@ module.exports = __toCommonJS(signalsDaemon_exports);
1643
37
  // src/scripts/signals.ts
1644
38
  var import_config = require("dotenv/config");
1645
39
  var import_args = __toESM(require("args"));
40
+
41
+ // src/lib/signals/runner.ts
1646
42
  var import_progress4 = __toESM(require("progress"));
1647
43
  var import_chalk7 = __toESM(require("chalk"));
1648
44
  var import_connectors6 = require("@tradejs/node/connectors");
1649
45
  var import_cli2 = require("@tradejs/node/cli");
1650
46
  var import_async3 = require("@tradejs/core/async");
1651
- var import_strategies5 = require("@tradejs/core/strategies");
47
+ var import_strategies6 = require("@tradejs/core/strategies");
1652
48
  var import_constants3 = require("@tradejs/core/constants");
1653
- var import_strategies6 = require("@tradejs/node/strategies");
1654
49
  var import_time3 = require("@tradejs/core/time");
1655
- var import_logger4 = require("@tradejs/infra/logger");
1656
- var import_tradingAccounts2 = require("@tradejs/infra/tradingAccounts");
50
+ var import_logger5 = require("@tradejs/infra/logger");
51
+ var import_runtimeDeployments = require("@tradejs/infra/runtimeDeployments");
1657
52
 
1658
53
  // src/lib/marketData/windows.ts
1659
54
  var import_indicators = require("@tradejs/core/indicators");
1660
- var resolveOpenTimestamp = (timestamp, intervalMs2) => Number.isFinite(intervalMs2) && intervalMs2 > 0 ? Math.floor(timestamp / intervalMs2) * intervalMs2 : timestamp;
1661
- var getClosedCandlesForInterval = (candles, currentTimestamp, intervalMs2) => {
55
+ var resolveOpenTimestamp = (timestamp, intervalMs) => Number.isFinite(intervalMs) && intervalMs > 0 ? Math.floor(timestamp / intervalMs) * intervalMs : timestamp;
56
+ var getClosedCandlesForInterval = (candles, currentTimestamp, intervalMs) => {
1662
57
  const currentOpenTimestamp = resolveOpenTimestamp(
1663
58
  currentTimestamp,
1664
- intervalMs2
59
+ intervalMs
1665
60
  );
1666
61
  return candles.filter((candle) => candle.timestamp < currentOpenTimestamp);
1667
62
  };
@@ -1669,7 +64,7 @@ var alignSymbolWithBtcReference = (symbolCandles, btcCandles) => (0, import_indi
1669
64
 
1670
65
  // src/lib/runFormatting.ts
1671
66
  var import_date_fns = require("date-fns");
1672
- var ListIt = require_list_it();
67
+ var ListIt = require("list-it");
1673
68
  var formatDuration = (startedAt) => {
1674
69
  const seconds = Math.max(0, (Date.now() - startedAt) / 1e3);
1675
70
  if (seconds < 60) return `${seconds.toFixed(1)}s`;
@@ -1714,7 +109,7 @@ var invokeAfterSignalsHooks = async (hooks, params) => {
1714
109
 
1715
110
  // src/lib/marketContextPrepare.ts
1716
111
  var import_chalk4 = __toESM(require("chalk"));
1717
- var import_timescale5 = require("@tradejs/infra/timescale");
112
+ var import_marketContext3 = require("@tradejs/infra/timescale/marketContext");
1718
113
  var import_registry = require("@tradejs/node/registry");
1719
114
 
1720
115
  // src/lib/binanceMarketContextBackfill.ts
@@ -1723,7 +118,8 @@ var import_chalk = __toESM(require("chalk"));
1723
118
  var import_connectors = require("@tradejs/connectors");
1724
119
  var import_connectors2 = require("@tradejs/node/connectors");
1725
120
  var import_strategies = require("@tradejs/node/strategies");
1726
- var import_timescale = require("@tradejs/infra/timescale");
121
+ var import_marketContext = require("@tradejs/infra/timescale/marketContext");
122
+ var import_client = require("@tradejs/infra/timescale/client");
1727
123
 
1728
124
  // src/lib/binanceMarketData.ts
1729
125
  var MARKET_FEATURE_INTERVAL_MS = {
@@ -1777,17 +173,17 @@ var classifyBtcAltRegime = ({
1777
173
  };
1778
174
  var aggregateAggTradesToRows = ({
1779
175
  symbol,
1780
- interval: interval2,
176
+ interval,
1781
177
  trades,
1782
178
  source = "binance_agg_trades"
1783
179
  }) => {
1784
- const intervalMs2 = MARKET_FEATURE_INTERVAL_MS[interval2];
180
+ const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
1785
181
  const buckets = /* @__PURE__ */ new Map();
1786
182
  for (const trade of trades) {
1787
- const bucketTs = Math.floor(trade.timestamp / intervalMs2) * intervalMs2;
183
+ const bucketTs = Math.floor(trade.timestamp / intervalMs) * intervalMs;
1788
184
  const row = buckets.get(bucketTs) ?? {
1789
185
  symbol,
1790
- interval: interval2,
186
+ interval,
1791
187
  ts: new Date(bucketTs),
1792
188
  trades: 0,
1793
189
  buyBaseVolume: 0,
@@ -1821,7 +217,7 @@ var aggregateAggTradesToRows = ({
1821
217
  };
1822
218
  var buildKlineTradeFlowRows = ({
1823
219
  symbol,
1824
- interval: interval2,
220
+ interval,
1825
221
  candles,
1826
222
  source = "binance_klines"
1827
223
  }) => candles.map((candle) => {
@@ -1835,7 +231,7 @@ var buildKlineTradeFlowRows = ({
1835
231
  const trades = candle.trades != null && Number.isFinite(candle.trades) ? Math.max(0, Math.trunc(candle.trades)) : 0;
1836
232
  return {
1837
233
  symbol,
1838
- interval: interval2,
234
+ interval,
1839
235
  ts: new Date(candle.timestamp),
1840
236
  trades,
1841
237
  buyBaseVolume,
@@ -1853,7 +249,7 @@ var buildKlineTradeFlowRows = ({
1853
249
  }).filter((row) => row != null);
1854
250
  var buildMarketBreadthRows = ({
1855
251
  universe,
1856
- interval: interval2,
252
+ interval,
1857
253
  candlesBySymbol,
1858
254
  btcCandles,
1859
255
  source = "binance_klines"
@@ -1878,10 +274,10 @@ var buildMarketBreadthRows = ({
1878
274
  btcCandles.map((candle) => Math.max(0, candle.turnover ?? 0))
1879
275
  )
1880
276
  } : null;
1881
- const intervalMs2 = MARKET_FEATURE_INTERVAL_MS[interval2];
1882
- const bars1h = Math.max(1, Math.round(36e5 / intervalMs2));
1883
- const bars4h = Math.max(1, Math.round(144e5 / intervalMs2));
1884
- const bars24h = Math.max(1, Math.round(864e5 / intervalMs2));
277
+ const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
278
+ const bars1h = Math.max(1, Math.round(36e5 / intervalMs));
279
+ const bars4h = Math.max(1, Math.round(144e5 / intervalMs));
280
+ const bars24h = Math.max(1, Math.round(864e5 / intervalMs));
1885
281
  for (const candles of Object.values(candlesBySymbol)) {
1886
282
  for (const candle of candles) timestamps.add(candle.timestamp);
1887
283
  }
@@ -1992,7 +388,7 @@ var buildMarketBreadthRows = ({
1992
388
  const btcTurnoverShareChange24h = btcTurnoverShare24h == null || previousBtcTurnoverShare24h == null ? null : btcTurnoverShare24h - previousBtcTurnoverShare24h;
1993
389
  return {
1994
390
  universe,
1995
- interval: interval2,
391
+ interval,
1996
392
  ts: new Date(timestamp),
1997
393
  symbolsCount: returns.length,
1998
394
  advancers,
@@ -2053,17 +449,17 @@ var getReferenceSymbols = () => {
2053
449
  const symbols = (process.env.BINANCE_MARKET_CONTEXT_REFERENCE_SYMBOLS || "BTCUSDT,ETHUSDT").split(",").map((item) => item.trim().toUpperCase()).filter(Boolean);
2054
450
  return symbols.length ? [...new Set(symbols)] : ["BTCUSDT", "ETHUSDT"];
2055
451
  };
2056
- var intervalToMarketFeatureInterval = (interval2) => {
2057
- const normalized = String(interval2).trim().toLowerCase();
452
+ var intervalToMarketFeatureInterval = (interval) => {
453
+ const normalized = String(interval).trim().toLowerCase();
2058
454
  if (normalized === "1" || normalized === "1m") return "1m";
2059
455
  if (normalized === "5" || normalized === "5m") return "5m";
2060
456
  if (normalized === "60" || normalized === "1h") return "1h";
2061
457
  return "15m";
2062
458
  };
2063
- var marketIntervalToConnectorInterval = (interval2) => {
2064
- if (interval2 === "1m") return "1";
2065
- if (interval2 === "5m") return "5";
2066
- if (interval2 === "1h") return "60";
459
+ var marketIntervalToConnectorInterval = (interval) => {
460
+ if (interval === "1m") return "1";
461
+ if (interval === "5m") return "5";
462
+ if (interval === "1h") return "60";
2067
463
  return "15";
2068
464
  };
2069
465
  var resolveBinanceMarketContextBackfillWindow = ({
@@ -2086,21 +482,21 @@ var hasCoverage = ({
2086
482
  coverage,
2087
483
  startMs,
2088
484
  endMs,
2089
- intervalMs: intervalMs2
485
+ intervalMs
2090
486
  }) => {
2091
487
  if (!coverage) return false;
2092
- const expectedRows = Math.max(1, Math.floor((endMs - startMs) / intervalMs2));
2093
- return coverage.firstMs <= startMs + intervalMs2 && coverage.lastMs >= endMs - intervalMs2 && coverage.rows >= Math.floor(expectedRows * 0.9);
488
+ const expectedRows = Math.max(1, Math.floor((endMs - startMs) / intervalMs));
489
+ return coverage.firstMs <= startMs + intervalMs && coverage.lastMs >= endMs - intervalMs && coverage.rows >= Math.floor(expectedRows * 0.9);
2094
490
  };
2095
491
  var buildBreadthBackfillChunks = ({
2096
492
  startMs,
2097
493
  endMs,
2098
- intervalMs: intervalMs2,
494
+ intervalMs,
2099
495
  chunkDays
2100
496
  }) => {
2101
- const chunkMs = Math.max(intervalMs2, chunkDays * DAY_MS);
2102
- const warmupBars = Math.max(50, Math.ceil(DAY_MS * 2 / intervalMs2));
2103
- const warmupMs = warmupBars * intervalMs2;
497
+ const chunkMs = Math.max(intervalMs, chunkDays * DAY_MS);
498
+ const warmupBars = Math.max(50, Math.ceil(DAY_MS * 2 / intervalMs));
499
+ const warmupMs = warmupBars * intervalMs;
2104
500
  const chunks = [];
2105
501
  let cursor = startMs;
2106
502
  while (cursor <= endMs) {
@@ -2117,10 +513,10 @@ var buildBreadthBackfillChunks = ({
2117
513
  var buildTradeFlowBackfillChunks = ({
2118
514
  startMs,
2119
515
  endMs,
2120
- intervalMs: intervalMs2,
516
+ intervalMs,
2121
517
  chunkDays
2122
518
  }) => {
2123
- const chunkMs = Math.max(intervalMs2, chunkDays * DAY_MS);
519
+ const chunkMs = Math.max(intervalMs, chunkDays * DAY_MS);
2124
520
  const chunks = [];
2125
521
  let cursor = startMs;
2126
522
  while (cursor <= endMs) {
@@ -2133,13 +529,13 @@ var buildTradeFlowBackfillChunks = ({
2133
529
  var filterMissingBreadthBackfillChunks = ({
2134
530
  chunks,
2135
531
  coverage,
2136
- intervalMs: intervalMs2
532
+ intervalMs
2137
533
  }) => chunks.filter(
2138
534
  (chunk) => !hasCoverage({
2139
535
  coverage,
2140
536
  startMs: chunk.startMs,
2141
537
  endMs: chunk.endMs,
2142
- intervalMs: intervalMs2
538
+ intervalMs
2143
539
  })
2144
540
  );
2145
541
  var fetchAggTradesForWindow = async ({
@@ -2179,12 +575,12 @@ var fetchAggTradesForWindow = async ({
2179
575
  return rows;
2180
576
  };
2181
577
  var getBinanceConnector = async ({
2182
- projectRoot: projectRoot2,
578
+ projectRoot,
2183
579
  userName
2184
580
  }) => {
2185
581
  const creator = await (0, import_connectors2.getConnectorCreatorByName)(
2186
582
  import_connectors.ConnectorNames.Binance,
2187
- projectRoot2
583
+ projectRoot
2188
584
  );
2189
585
  if (!creator) {
2190
586
  throw new Error(
@@ -2225,13 +621,13 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2225
621
  if (!enabled || !symbols.length) {
2226
622
  return skippedBackfillResult();
2227
623
  }
2228
- const interval2 = intervalToMarketFeatureInterval(params.interval);
2229
- const intervalMs2 = MARKET_FEATURE_INTERVAL_MS[interval2];
624
+ const interval = intervalToMarketFeatureInterval(params.interval);
625
+ const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
2230
626
  const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
2231
627
  if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
2232
628
  return skippedBackfillResult();
2233
629
  }
2234
- await (0, import_timescale.waitForDbReady)();
630
+ await (0, import_client.waitForDbReady)();
2235
631
  const connector = await getBinanceConnector({
2236
632
  projectRoot: params.projectRoot,
2237
633
  userName: params.userName
@@ -2273,13 +669,13 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2273
669
  let breadthRows = 0;
2274
670
  console.log(
2275
671
  import_chalk.default.cyan(
2276
- `binance market context backfill: requestedSymbols=${symbols.length}, referenceSymbols=${referenceSymbols.length}, interval=${interval2}, tradeFlowWindow=${new Date(tradeFlowStartMs).toISOString()}..${new Date(endMs).toISOString()}, breadthWindow=${new Date(breadthStartMs).toISOString()}..${new Date(endMs).toISOString()}`
672
+ `binance market context backfill: requestedSymbols=${symbols.length}, referenceSymbols=${referenceSymbols.length}, interval=${interval}, tradeFlowWindow=${new Date(tradeFlowStartMs).toISOString()}..${new Date(endMs).toISOString()}, breadthWindow=${new Date(breadthStartMs).toISOString()}..${new Date(endMs).toISOString()}`
2277
673
  )
2278
674
  );
2279
675
  if (includeTradeFlow && referenceSymbols.length) {
2280
- const coverage = await (0, import_timescale.getMarketTradeFlowCoverage)({
676
+ const coverage = await (0, import_marketContext.getMarketTradeFlowCoverage)({
2281
677
  symbols: referenceSymbols,
2282
- interval: interval2,
678
+ interval,
2283
679
  startMs: tradeFlowStartMs,
2284
680
  endMs
2285
681
  });
@@ -2288,7 +684,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2288
684
  coverage: coverage.get(symbol),
2289
685
  startMs: tradeFlowStartMs,
2290
686
  endMs,
2291
- intervalMs: intervalMs2
687
+ intervalMs
2292
688
  })
2293
689
  );
2294
690
  const bar = new import_progress.default(
@@ -2301,11 +697,11 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2301
697
  if (!missingSymbols.length) {
2302
698
  bar.tick(1, { rows: 0, skip: referenceSymbols.length, symbol: "cached" });
2303
699
  }
2304
- const connectorInterval = marketIntervalToConnectorInterval(interval2);
700
+ const connectorInterval = marketIntervalToConnectorInterval(interval);
2305
701
  const chunks = buildTradeFlowBackfillChunks({
2306
702
  startMs: tradeFlowStartMs,
2307
703
  endMs,
2308
- intervalMs: intervalMs2,
704
+ intervalMs,
2309
705
  chunkDays: tradeFlowChunkDays
2310
706
  });
2311
707
  const chunkBar = missingSymbols.length ? new import_progress.default(
@@ -2324,7 +720,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2324
720
  coverage: symbolCoverage,
2325
721
  startMs: chunk.startMs,
2326
722
  endMs: chunk.endMs,
2327
- intervalMs: intervalMs2
723
+ intervalMs
2328
724
  })) {
2329
725
  skippedTradeFlowChunks += 1;
2330
726
  chunkBar?.tick(1, {
@@ -2337,7 +733,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2337
733
  }
2338
734
  const rows = tradeFlowSource === "agg_trades" ? aggregateAggTradesToRows({
2339
735
  symbol,
2340
- interval: interval2,
736
+ interval,
2341
737
  trades: await fetchAggTradesForWindow({
2342
738
  connector,
2343
739
  symbol,
@@ -2348,7 +744,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2348
744
  })
2349
745
  }) : buildKlineTradeFlowRows({
2350
746
  symbol,
2351
- interval: interval2,
747
+ interval,
2352
748
  candles: await connector.kline({
2353
749
  symbol,
2354
750
  interval: connectorInterval,
@@ -2361,7 +757,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2361
757
  const ts = row.ts.getTime();
2362
758
  return ts >= chunk.startMs && ts <= chunk.endMs;
2363
759
  });
2364
- await (0, import_timescale.upsertMarketTradeFlowRows)(boundedRows);
760
+ await (0, import_marketContext.upsertMarketTradeFlowRows)(boundedRows);
2365
761
  tradeFlowRows += boundedRows.length;
2366
762
  chunkBar?.tick(1, {
2367
763
  rows: tradeFlowRows,
@@ -2380,18 +776,18 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2380
776
  if (includeBreadth) {
2381
777
  const breadthUniverses = (0, import_strategies.getBinanceBreadthUniverses)();
2382
778
  const breadthSymbols = breadthUniverses.at(-1)?.symbols ?? [];
2383
- const connectorInterval = marketIntervalToConnectorInterval(interval2);
779
+ const connectorInterval = marketIntervalToConnectorInterval(interval);
2384
780
  const chunks = buildBreadthBackfillChunks({
2385
781
  startMs: breadthStartMs,
2386
782
  endMs,
2387
- intervalMs: intervalMs2,
783
+ intervalMs,
2388
784
  chunkDays: breadthChunkDays
2389
785
  });
2390
786
  const plans = await Promise.all(
2391
787
  breadthUniverses.map(async (definition) => {
2392
- const coverage = await (0, import_timescale.getMarketBreadthCoverage)({
788
+ const coverage = await (0, import_marketContext.getMarketBreadthCoverage)({
2393
789
  universe: definition.universe,
2394
- interval: interval2,
790
+ interval,
2395
791
  startMs: breadthStartMs,
2396
792
  endMs
2397
793
  });
@@ -2400,11 +796,11 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2400
796
  coverage,
2401
797
  startMs: breadthStartMs,
2402
798
  endMs,
2403
- intervalMs: intervalMs2
799
+ intervalMs
2404
800
  }) || !hasBtcAltMetrics ? !hasBtcAltMetrics ? chunks : filterMissingBreadthBackfillChunks({
2405
801
  chunks,
2406
802
  coverage,
2407
- intervalMs: intervalMs2
803
+ intervalMs
2408
804
  }) : [];
2409
805
  if (!missingChunks2.length) {
2410
806
  console.log(
@@ -2483,14 +879,14 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2483
879
  );
2484
880
  const rows = buildMarketBreadthRows({
2485
881
  universe: plan.definition.universe,
2486
- interval: interval2,
882
+ interval,
2487
883
  candlesBySymbol: universeCandles,
2488
884
  btcCandles
2489
885
  }).filter((row) => {
2490
886
  const ts = row.ts.getTime();
2491
887
  return ts >= chunk.startMs && ts <= chunk.endMs;
2492
888
  });
2493
- await (0, import_timescale.upsertMarketBreadthRows)(rows);
889
+ await (0, import_marketContext.upsertMarketBreadthRows)(rows);
2494
890
  breadthRows += rows.length;
2495
891
  }
2496
892
  }
@@ -2518,7 +914,8 @@ var import_progress2 = __toESM(require("progress"));
2518
914
  var import_async = require("@tradejs/core/async");
2519
915
  var import_constants = require("@tradejs/core/constants");
2520
916
  var import_indicators2 = require("@tradejs/core/indicators");
2521
- var import_timescale2 = require("@tradejs/infra/timescale");
917
+ var import_derivatives = require("@tradejs/infra/timescale/derivatives");
918
+ var import_client2 = require("@tradejs/infra/timescale/client");
2522
919
  var import_userSettings = require("@tradejs/infra/userSettings");
2523
920
  var HOUR_MS = 60 * 60 * 1e3;
2524
921
  var DAY_MS2 = 24 * HOUR_MS;
@@ -2528,7 +925,7 @@ var coinalyzeIntervalMap = {
2528
925
  "15m": "15min",
2529
926
  "1h": "1hour"
2530
927
  };
2531
- var derivativesIntervalMs = (interval2) => interval2 === "1h" ? HOUR_MS : 15 * 60 * 1e3;
928
+ var derivativesIntervalMs = (interval) => interval === "1h" ? HOUR_MS : 15 * 60 * 1e3;
2532
929
  var lastRequestTs = 0;
2533
930
  var asInt2 = (value, fallback) => {
2534
931
  const parsed = Number.parseInt(String(value ?? ""), 10);
@@ -2618,12 +1015,12 @@ var resolveDerivativesContextBackfillWindow = (params) => {
2618
1015
  };
2619
1016
  };
2620
1017
  var resolveDerivativesContextIntervalBackfillWindow = (params) => {
2621
- const intervalMs2 = derivativesIntervalMs(params.interval);
2622
- const alignedToMs = params.closedOnly ? (0, import_indicators2.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs2) * intervalMs2;
1018
+ const intervalMs = derivativesIntervalMs(params.interval);
1019
+ const alignedToMs = params.closedOnly ? (0, import_indicators2.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs) * intervalMs;
2623
1020
  return {
2624
- fromMs: Math.floor(params.fromMs / intervalMs2) * intervalMs2,
1021
+ fromMs: Math.floor(params.fromMs / intervalMs) * intervalMs,
2625
1022
  toMs: alignedToMs,
2626
- intervalMs: intervalMs2
1023
+ intervalMs
2627
1024
  };
2628
1025
  };
2629
1026
  var resolveDerivativesContextMissingFetchFromMs = (params) => {
@@ -2972,10 +1369,10 @@ var toSeriesMap = (raw, metric) => {
2972
1369
  return out;
2973
1370
  };
2974
1371
  var fetchMetricBatch = async (params) => {
2975
- const { endpoint, metric, marketSymbols, apiKey, interval: interval2, fromMs, toMs } = params;
1372
+ const { endpoint, metric, marketSymbols, apiKey, interval, fromMs, toMs } = params;
2976
1373
  const url = new URL(`${getCoinalyzeBaseUrl()}${endpoint}`);
2977
1374
  url.searchParams.set("symbols", marketSymbols.join(","));
2978
- url.searchParams.set("interval", coinalyzeIntervalMap[interval2] || interval2);
1375
+ url.searchParams.set("interval", coinalyzeIntervalMap[interval] || interval);
2979
1376
  url.searchParams.set("from", String(Math.floor(fromMs / 1e3)));
2980
1377
  url.searchParams.set("to", String(Math.floor(toMs / 1e3)));
2981
1378
  const raw = await fetchJsonWithRateLimit(url.toString(), apiKey);
@@ -3019,25 +1416,25 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3019
1416
  30
3020
1417
  );
3021
1418
  const batchMs = batchDays * DAY_MS2;
3022
- const intervalWindows = intervals.map((interval2) => ({
3023
- interval: interval2,
1419
+ const intervalWindows = intervals.map((interval) => ({
1420
+ interval,
3024
1421
  ...resolveDerivativesContextIntervalBackfillWindow({
3025
1422
  fromMs,
3026
1423
  toMs: safeEndMs,
3027
- interval: interval2,
1424
+ interval,
3028
1425
  closedOnly: mode === "signals"
3029
1426
  })
3030
1427
  })).filter((item) => item.toMs > item.fromMs);
3031
1428
  if (!intervalWindows.length) {
3032
1429
  return skippedBackfillResult2();
3033
1430
  }
3034
- await (0, import_timescale2.waitForDbReady)();
1431
+ await (0, import_client2.waitForDbReady)();
3035
1432
  const edgesByInterval = /* @__PURE__ */ new Map();
3036
1433
  await Promise.all(
3037
- intervalWindows.map(async ({ interval: interval2 }) => {
1434
+ intervalWindows.map(async ({ interval }) => {
3038
1435
  edgesByInterval.set(
3039
- interval2,
3040
- await (0, import_timescale2.getDerivativesDataEdgesForSymbols)(symbols, interval2)
1436
+ interval,
1437
+ await (0, import_derivatives.getDerivativesDataEdgesForSymbols)(symbols, interval)
3041
1438
  );
3042
1439
  })
3043
1440
  );
@@ -3046,32 +1443,32 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3046
1443
  const liquidationCoverageRangesByInterval = /* @__PURE__ */ new Map();
3047
1444
  const coverageNowMs = Date.now();
3048
1445
  await Promise.all(
3049
- intervalWindows.map(async (window2) => {
1446
+ intervalWindows.map(async (window) => {
3050
1447
  const confirmedLiquidationWindow = (0, import_indicators2.resolveCoinalyzeConfirmedIntradayCoverage)({
3051
- interval: window2.interval,
3052
- fromMs: window2.fromMs,
3053
- toMs: window2.toMs,
1448
+ interval: window.interval,
1449
+ fromMs: window.fromMs,
1450
+ toMs: window.toMs,
3054
1451
  nowMs: coverageNowMs
3055
1452
  });
3056
1453
  const [coverageRows, liquidationCoverageRows] = await Promise.all([
3057
- (0, import_timescale2.getDerivativesBackfillCoverage)({
1454
+ (0, import_derivatives.getDerivativesBackfillCoverage)({
3058
1455
  source: "coinalyze",
3059
1456
  symbols,
3060
- interval: window2.interval,
3061
- fromMs: window2.fromMs,
3062
- toMs: window2.toMs
1457
+ interval: window.interval,
1458
+ fromMs: window.fromMs,
1459
+ toMs: window.toMs
3063
1460
  }),
3064
- confirmedLiquidationWindow ? (0, import_timescale2.getDerivativesMetricCoverage)({
1461
+ confirmedLiquidationWindow ? (0, import_derivatives.getDerivativesMetricCoverage)({
3065
1462
  source: "coinalyze",
3066
1463
  metric: "liquidation",
3067
1464
  symbols,
3068
- interval: window2.interval,
1465
+ interval: window.interval,
3069
1466
  fromMs: confirmedLiquidationWindow.fromMs,
3070
1467
  toMs: confirmedLiquidationWindow.toMs
3071
1468
  }) : Promise.resolve([])
3072
1469
  ]);
3073
1470
  coverageKeysByInterval.set(
3074
- window2.interval,
1471
+ window.interval,
3075
1472
  new Set(
3076
1473
  coverageRows.map(
3077
1474
  (row) => coverageKey({
@@ -3090,7 +1487,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3090
1487
  ranges.push({ fromMs: row.fromMs, toMs: row.toMs });
3091
1488
  rangesBySymbol.set(symbol, ranges);
3092
1489
  }
3093
- coverageRangesByInterval.set(window2.interval, rangesBySymbol);
1490
+ coverageRangesByInterval.set(window.interval, rangesBySymbol);
3094
1491
  const liquidationRangesBySymbol = /* @__PURE__ */ new Map();
3095
1492
  for (const row of liquidationCoverageRows) {
3096
1493
  const symbol = row.symbol.toUpperCase();
@@ -3099,33 +1496,33 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3099
1496
  liquidationRangesBySymbol.set(symbol, ranges);
3100
1497
  }
3101
1498
  liquidationCoverageRangesByInterval.set(
3102
- window2.interval,
1499
+ window.interval,
3103
1500
  liquidationRangesBySymbol
3104
1501
  );
3105
1502
  })
3106
1503
  );
3107
1504
  const cachedWindows = intervalWindows.reduce(
3108
- (sum, window2) => sum + countBackfillWindows({
3109
- fromMs: window2.fromMs,
3110
- toMs: window2.toMs,
1505
+ (sum, window) => sum + countBackfillWindows({
1506
+ fromMs: window.fromMs,
1507
+ toMs: window.toMs,
3111
1508
  batchMs,
3112
- intervalMs: window2.intervalMs
1509
+ intervalMs: window.intervalMs
3113
1510
  }),
3114
1511
  0
3115
1512
  );
3116
- const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window2) => {
3117
- const edgesBySymbol = edgesByInterval.get(window2.interval);
3118
- const coverageKeys = coverageKeysByInterval.get(window2.interval);
1513
+ const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window) => {
1514
+ const edgesBySymbol = edgesByInterval.get(window.interval);
1515
+ const coverageKeys = coverageKeysByInterval.get(window.interval);
3119
1516
  const backfillWindows = buildBackfillWindows({
3120
- fromMs: window2.fromMs,
3121
- toMs: window2.toMs,
1517
+ fromMs: window.fromMs,
1518
+ toMs: window.toMs,
3122
1519
  batchMs,
3123
- intervalMs: window2.intervalMs
1520
+ intervalMs: window.intervalMs
3124
1521
  });
3125
1522
  return symbols.every(
3126
1523
  (symbol) => backfillWindows.every((backfillWindow) => {
3127
1524
  const normalizedSymbol = symbol.toUpperCase();
3128
- const coverageRanges = coverageRangesByInterval.get(window2.interval)?.get(normalizedSymbol) ?? [];
1525
+ const coverageRanges = coverageRangesByInterval.get(window.interval)?.get(normalizedSymbol) ?? [];
3129
1526
  const dataCovered = hasDerivativesWindowCoverage({
3130
1527
  edges: edgesBySymbol?.get(normalizedSymbol),
3131
1528
  fromMs: backfillWindow.fromMs,
@@ -3134,26 +1531,26 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3134
1531
  ranges: coverageRanges,
3135
1532
  fromMs: backfillWindow.fromMs,
3136
1533
  toMs: backfillWindow.toMs,
3137
- intervalMs: window2.intervalMs
1534
+ intervalMs: window.intervalMs
3138
1535
  }) == null || coverageKeys?.has(
3139
1536
  coverageKey({
3140
1537
  symbol: normalizedSymbol,
3141
- interval: window2.interval,
1538
+ interval: window.interval,
3142
1539
  fromMs: backfillWindow.fromMs,
3143
1540
  toMs: backfillWindow.toMs
3144
1541
  })
3145
1542
  );
3146
1543
  const confirmedLiquidationWindow = (0, import_indicators2.resolveCoinalyzeConfirmedIntradayCoverage)({
3147
- interval: window2.interval,
1544
+ interval: window.interval,
3148
1545
  fromMs: backfillWindow.fromMs,
3149
1546
  toMs: backfillWindow.toMs,
3150
1547
  nowMs: coverageNowMs
3151
1548
  });
3152
1549
  const liquidationCovered = confirmedLiquidationWindow == null || resolveDerivativesContextMissingCoverageFetchFromMs({
3153
- ranges: liquidationCoverageRangesByInterval.get(window2.interval)?.get(normalizedSymbol) ?? [],
1550
+ ranges: liquidationCoverageRangesByInterval.get(window.interval)?.get(normalizedSymbol) ?? [],
3154
1551
  fromMs: confirmedLiquidationWindow.fromMs,
3155
1552
  toMs: confirmedLiquidationWindow.toMs,
3156
- intervalMs: window2.intervalMs
1553
+ intervalMs: window.intervalMs
3157
1554
  }) == null;
3158
1555
  return dataCovered && liquidationCovered;
3159
1556
  })
@@ -3203,11 +1600,11 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3203
1600
  );
3204
1601
  const symbolBatches = chunkArray(matches, symbolBatchSize);
3205
1602
  const windowsPerPair = intervalWindows.reduce(
3206
- (sum, window2) => sum + countBackfillWindows({
3207
- fromMs: window2.fromMs,
3208
- toMs: window2.toMs,
1603
+ (sum, window) => sum + countBackfillWindows({
1604
+ fromMs: window.fromMs,
1605
+ toMs: window.toMs,
3209
1606
  batchMs,
3210
- intervalMs: window2.intervalMs
1607
+ intervalMs: window.intervalMs
3211
1608
  }),
3212
1609
  0
3213
1610
  );
@@ -3230,30 +1627,30 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3230
1627
  `derivatives context backfill: symbols=${matches.length}, requestedSymbols=${requestedSymbols.length}, unmatched=${unmatched.length}, intervals=${intervals.join(",")}, window=${new Date(fromMs).toISOString()}..${new Date(safeEndMs).toISOString()}, testStart=${new Date(safeStartMs).toISOString()}`
3231
1628
  )
3232
1629
  );
3233
- for (const window2 of intervalWindows) {
3234
- const { interval: interval2, intervalMs: intervalMs2 } = window2;
3235
- const edgesBySymbol = edgesByInterval.get(interval2) ?? await (0, import_timescale2.getDerivativesDataEdgesForSymbols)(
1630
+ for (const window of intervalWindows) {
1631
+ const { interval, intervalMs } = window;
1632
+ const edgesBySymbol = edgesByInterval.get(interval) ?? await (0, import_derivatives.getDerivativesDataEdgesForSymbols)(
3236
1633
  matches.map((item) => item.symbol),
3237
- interval2
1634
+ interval
3238
1635
  );
3239
- const coverageKeys = coverageKeysByInterval.get(interval2) ?? /* @__PURE__ */ new Set();
3240
- coverageKeysByInterval.set(interval2, coverageKeys);
3241
- const coverageRangesBySymbol = coverageRangesByInterval.get(interval2) ?? /* @__PURE__ */ new Map();
3242
- coverageRangesByInterval.set(interval2, coverageRangesBySymbol);
3243
- const liquidationCoverageRangesBySymbol = liquidationCoverageRangesByInterval.get(interval2) ?? /* @__PURE__ */ new Map();
1636
+ const coverageKeys = coverageKeysByInterval.get(interval) ?? /* @__PURE__ */ new Set();
1637
+ coverageKeysByInterval.set(interval, coverageKeys);
1638
+ const coverageRangesBySymbol = coverageRangesByInterval.get(interval) ?? /* @__PURE__ */ new Map();
1639
+ coverageRangesByInterval.set(interval, coverageRangesBySymbol);
1640
+ const liquidationCoverageRangesBySymbol = liquidationCoverageRangesByInterval.get(interval) ?? /* @__PURE__ */ new Map();
3244
1641
  liquidationCoverageRangesByInterval.set(
3245
- interval2,
1642
+ interval,
3246
1643
  liquidationCoverageRangesBySymbol
3247
1644
  );
3248
1645
  for (let batchIdx = 0; batchIdx < symbolBatches.length; batchIdx += 1) {
3249
1646
  const batch = symbolBatches[batchIdx];
3250
- let cursor = window2.fromMs;
3251
- while (cursor < window2.toMs) {
3252
- const toMs = Math.min(window2.toMs, cursor + batchMs);
1647
+ let cursor = window.fromMs;
1648
+ while (cursor < window.toMs) {
1649
+ const toMs = Math.min(window.toMs, cursor + batchMs);
3253
1650
  const missingRanges = batch.map((item) => {
3254
1651
  const key = coverageKey({
3255
1652
  symbol: item.symbol,
3256
- interval: interval2,
1653
+ interval,
3257
1654
  fromMs: cursor,
3258
1655
  toMs
3259
1656
  });
@@ -3261,8 +1658,8 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3261
1658
  const requiredFromMs = resolveDerivativesContextRequiredFetchFromMs(
3262
1659
  {
3263
1660
  mode,
3264
- interval: interval2,
3265
- intervalMs: intervalMs2,
1661
+ interval,
1662
+ intervalMs,
3266
1663
  fromMs: cursor,
3267
1664
  toMs,
3268
1665
  nowMs: coverageNowMs,
@@ -3307,7 +1704,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3307
1704
  metric: "oi",
3308
1705
  marketSymbols,
3309
1706
  apiKey,
3310
- interval: interval2,
1707
+ interval,
3311
1708
  fromMs: group.fromMs,
3312
1709
  toMs
3313
1710
  });
@@ -3316,7 +1713,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3316
1713
  metric: "funding",
3317
1714
  marketSymbols,
3318
1715
  apiKey,
3319
- interval: interval2,
1716
+ interval,
3320
1717
  fromMs: group.fromMs,
3321
1718
  toMs
3322
1719
  });
@@ -3325,7 +1722,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3325
1722
  metric: "liq",
3326
1723
  marketSymbols,
3327
1724
  apiKey,
3328
- interval: interval2,
1725
+ interval,
3329
1726
  fromMs: group.fromMs,
3330
1727
  toMs
3331
1728
  });
@@ -3337,7 +1734,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3337
1734
  fundingRaw: fundingMap.get(marketSymbol) ?? [],
3338
1735
  liqRaw: liquidationRowsByMarket.get(marketSymbol) ?? []
3339
1736
  });
3340
- return (0, import_indicators2.coinalyzePointsToRows)(points, interval2, "coinalyze");
1737
+ return (0, import_indicators2.coinalyzePointsToRows)(points, interval, "coinalyze");
3341
1738
  });
3342
1739
  missingClosedSymbols = mode === "signals" ? getMissingClosedDerivativesSymbols({
3343
1740
  symbols: missingBatch.map((item) => item.symbol),
@@ -3351,15 +1748,15 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3351
1748
  }
3352
1749
  if (missingClosedSymbols.length) {
3353
1750
  throw new Error(
3354
- `Coinalyze closed ${interval2} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
1751
+ `Coinalyze closed ${interval} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
3355
1752
  );
3356
1753
  }
3357
1754
  if (rows.length) {
3358
- await (0, import_timescale2.upsertDerivatives)(rows);
1755
+ await (0, import_derivatives.upsertDerivatives)(rows);
3359
1756
  totalRows += rows.length;
3360
1757
  }
3361
1758
  const confirmedLiquidationWindow = (0, import_indicators2.resolveCoinalyzeConfirmedIntradayCoverage)({
3362
- interval: interval2,
1759
+ interval,
3363
1760
  fromMs: group.fromMs,
3364
1761
  toMs,
3365
1762
  nowMs: coverageNowMs
@@ -3377,13 +1774,13 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3377
1774
  source: "coinalyze",
3378
1775
  metric: "liquidation",
3379
1776
  symbol: item.symbol,
3380
- interval: interval2,
1777
+ interval,
3381
1778
  fromMs: confirmedLiquidationWindow.fromMs,
3382
1779
  toMs: confirmedLiquidationWindow.toMs,
3383
1780
  eventRowsCount
3384
1781
  };
3385
1782
  });
3386
- await (0, import_timescale2.applyDerivativesMetricCoverage)(metricCoverageRows);
1783
+ await (0, import_derivatives.applyDerivativesMetricCoverage)(metricCoverageRows);
3387
1784
  for (const coverageRow of metricCoverageRows) {
3388
1785
  const symbol = coverageRow.symbol.toUpperCase();
3389
1786
  const ranges = liquidationCoverageRangesBySymbol.get(symbol) ?? [];
@@ -3409,13 +1806,13 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3409
1806
  return {
3410
1807
  source: "coinalyze",
3411
1808
  symbol: item.symbol,
3412
- interval: interval2,
1809
+ interval,
3413
1810
  fromMs: cursor,
3414
1811
  toMs,
3415
1812
  rowsCount
3416
1813
  };
3417
1814
  });
3418
- await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
1815
+ await (0, import_derivatives.upsertDerivativesBackfillCoverage)(coverageRows);
3419
1816
  for (const coverageRow of coverageRows) {
3420
1817
  const symbol = coverageRow.symbol.toUpperCase();
3421
1818
  edgesBySymbol.set(
@@ -3425,7 +1822,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3425
1822
  coverageKeys.add(
3426
1823
  coverageKey({
3427
1824
  symbol,
3428
- interval: interval2,
1825
+ interval,
3429
1826
  fromMs: cursor,
3430
1827
  toMs
3431
1828
  })
@@ -3441,20 +1838,20 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3441
1838
  failedWindows += 1;
3442
1839
  console.error(
3443
1840
  import_chalk2.default.red(
3444
- `derivatives context backfill window failed batch=${batchIdx + 1}/${symbolBatches.length} interval=${interval2} ${new Date(cursor).toISOString()}..${new Date(toMs).toISOString()}: ${error}`
1841
+ `derivatives context backfill window failed batch=${batchIdx + 1}/${symbolBatches.length} interval=${interval} ${new Date(cursor).toISOString()}..${new Date(toMs).toISOString()}: ${error}`
3445
1842
  )
3446
1843
  );
3447
1844
  } finally {
3448
1845
  bar.tick(1, {
3449
1846
  batch: import_chalk2.default.gray(
3450
- `${batchIdx + 1}/${symbolBatches.length} ${interval2}`
1847
+ `${batchIdx + 1}/${symbolBatches.length} ${interval}`
3451
1848
  ),
3452
1849
  rows: totalRows,
3453
1850
  fail: failedWindows,
3454
1851
  skip: skippedWindows
3455
1852
  });
3456
1853
  }
3457
- cursor = toMs + intervalMs2;
1854
+ cursor = toMs + intervalMs;
3458
1855
  }
3459
1856
  }
3460
1857
  }
@@ -3492,7 +1889,8 @@ var backfillDerivativesContextForSignals = async (params) => backfillDerivatives
3492
1889
  // src/lib/coinMarketCapContextBackfill.ts
3493
1890
  var import_chalk3 = __toESM(require("chalk"));
3494
1891
  var import_async2 = require("@tradejs/core/async");
3495
- var import_timescale3 = require("@tradejs/infra/timescale");
1892
+ var import_marketContext2 = require("@tradejs/infra/timescale/marketContext");
1893
+ var import_client3 = require("@tradejs/infra/timescale/client");
3496
1894
  var import_userSettings2 = require("@tradejs/infra/userSettings");
3497
1895
  var DAY_MS3 = 864e5;
3498
1896
  var DEFAULT_CONTEXT_MAX_AGE_MS = 48 * 60 * 6e4;
@@ -3644,10 +2042,10 @@ var resolveCoinMarketCapBackfillWindow = (params) => {
3644
2042
  toMs: dayStartUtc(params.endMs)
3645
2043
  };
3646
2044
  };
3647
- var hasIntervalCoverage = (coverage, fromMs, toMs, intervalMs2) => {
2045
+ var hasIntervalCoverage = (coverage, fromMs, toMs, intervalMs) => {
3648
2046
  if (!coverage) return false;
3649
- const expectedRows = Math.max(1, Math.floor((toMs - fromMs) / intervalMs2));
3650
- return coverage.firstMs <= fromMs + intervalMs2 && coverage.lastMs >= toMs - intervalMs2 && coverage.rows >= Math.floor(expectedRows * 0.9);
2047
+ const expectedRows = Math.max(1, Math.floor((toMs - fromMs) / intervalMs));
2048
+ return coverage.firstMs <= fromMs + intervalMs && coverage.lastMs >= toMs - intervalMs && coverage.rows >= Math.floor(expectedRows * 0.9);
3651
2049
  };
3652
2050
  var hasDailyCoverage = (coverage, fromMs, toMs) => hasIntervalCoverage(coverage, fromMs, toMs, DAY_MS3);
3653
2051
  var coverageKey2 = (params) => [
@@ -3756,7 +2154,7 @@ var logBackfillSourceDone = (params) => {
3756
2154
  )
3757
2155
  );
3758
2156
  };
3759
- var markBackfillCoverage = (rows) => (0, import_timescale3.upsertMarketContextBackfillCoverage)(rows);
2157
+ var markBackfillCoverage = (rows) => (0, import_marketContext2.upsertMarketContextBackfillCoverage)(rows);
3760
2158
  var coinMarketCapFetch = async (params) => {
3761
2159
  const url = new URL(`${getBaseUrl()}${params.path}`);
3762
2160
  for (const [key, value] of Object.entries(params.searchParams)) {
@@ -3892,7 +2290,7 @@ var normalizeAssetDataItems = (payload) => {
3892
2290
  }
3893
2291
  return [];
3894
2292
  };
3895
- var coinMarketCapHistoricalQuotesPayloadToRows = (payload, interval2 = "1d") => {
2293
+ var coinMarketCapHistoricalQuotesPayloadToRows = (payload, interval = "1d") => {
3896
2294
  return normalizeAssetDataItems(payload).flatMap((asset) => {
3897
2295
  const cmcId = toIntOrNull(asset.id);
3898
2296
  const symbolRaw = String(asset.symbol ?? "").trim().toUpperCase();
@@ -3911,7 +2309,7 @@ var coinMarketCapHistoricalQuotesPayloadToRows = (payload, interval2 = "1d") =>
3911
2309
  source: SOURCE_REFERENCE,
3912
2310
  symbol: target.symbol,
3913
2311
  cmcId,
3914
- interval: interval2,
2312
+ interval,
3915
2313
  ts,
3916
2314
  openUsd: null,
3917
2315
  highUsd: null,
@@ -3923,7 +2321,7 @@ var coinMarketCapHistoricalQuotesPayloadToRows = (payload, interval2 = "1d") =>
3923
2321
  }).filter((row) => row != null);
3924
2322
  });
3925
2323
  };
3926
- var coinMarketCapExchangeQuotesPayloadToLiquidityRows = (payload, interval2 = "1d") => {
2324
+ var coinMarketCapExchangeQuotesPayloadToLiquidityRows = (payload, interval = "1d") => {
3927
2325
  const data = getRecord(payload).data;
3928
2326
  const exchangeItems = Array.isArray(data) ? data : Object.values(getRecord(data));
3929
2327
  const rowsByTs = /* @__PURE__ */ new Map();
@@ -3964,7 +2362,7 @@ var coinMarketCapExchangeQuotesPayloadToLiquidityRows = (payload, interval2 = "1
3964
2362
  );
3965
2363
  return {
3966
2364
  source: SOURCE_EXCHANGE_LIQUIDITY,
3967
- interval: interval2,
2365
+ interval,
3968
2366
  ts: new Date(ts),
3969
2367
  exchangesCount: exchanges.length,
3970
2368
  totalVolumeUsd,
@@ -4007,7 +2405,7 @@ var toCmcIndexWeightPct = (value) => {
4007
2405
  }
4008
2406
  return toFiniteNumberOrNull(value);
4009
2407
  };
4010
- var coinMarketCapIndexPayloadToRows = (payload, indexSlug, interval2 = "1d") => {
2408
+ var coinMarketCapIndexPayloadToRows = (payload, indexSlug, interval = "1d") => {
4011
2409
  const data = getRecord(payload).data;
4012
2410
  const items = Array.isArray(data) ? data : [];
4013
2411
  return items.map((item) => {
@@ -4036,7 +2434,7 @@ var coinMarketCapIndexPayloadToRows = (payload, indexSlug, interval2 = "1d") =>
4036
2434
  return {
4037
2435
  source: SOURCE_INDEX,
4038
2436
  indexSlug,
4039
- interval: interval2,
2437
+ interval,
4040
2438
  ts,
4041
2439
  value,
4042
2440
  constituentsCount: constituents.length,
@@ -4085,7 +2483,7 @@ var backfillCoinMarketCapContext = async (params) => {
4085
2483
  if (toMs <= fromMs) return skippedResult();
4086
2484
  const exchangeLiquidityEnabled = isExchangeLiquidityBackfillEnabled();
4087
2485
  const fearGreedEnabled = isFearGreedBackfillEnabled();
4088
- await (0, import_timescale3.waitForDbReady)();
2486
+ await (0, import_client3.waitForDbReady)();
4089
2487
  const [
4090
2488
  globalDailyCoverage,
4091
2489
  referenceDailyCoverage,
@@ -4098,66 +2496,66 @@ var backfillCoinMarketCapContext = async (params) => {
4098
2496
  fearGreedBackfillCoverage,
4099
2497
  indexBackfillCoverage
4100
2498
  ] = await Promise.all([
4101
- (0, import_timescale3.getMarketGlobalContextCoverage)({
2499
+ (0, import_marketContext2.getMarketGlobalContextCoverage)({
4102
2500
  source: SOURCE_GLOBAL_DAILY,
4103
2501
  startMs: fromMs,
4104
2502
  endMs: toMs
4105
2503
  }),
4106
- (0, import_timescale3.getMarketReferenceAssetContextCoverage)({
2504
+ (0, import_marketContext2.getMarketReferenceAssetContextCoverage)({
4107
2505
  source: SOURCE_REFERENCE,
4108
2506
  symbols: REFERENCE_ASSETS.map((item) => item.symbol),
4109
2507
  interval: "1d",
4110
2508
  startMs: fromMs,
4111
2509
  endMs: toMs
4112
2510
  }),
4113
- exchangeLiquidityEnabled ? (0, import_timescale3.getMarketCmcExchangeLiquidityContextCoverage)({
2511
+ exchangeLiquidityEnabled ? (0, import_marketContext2.getMarketCmcExchangeLiquidityContextCoverage)({
4114
2512
  source: SOURCE_EXCHANGE_LIQUIDITY,
4115
2513
  interval: "1d",
4116
2514
  startMs: fromMs,
4117
2515
  endMs: toMs
4118
2516
  }) : Promise.resolve(null),
4119
- fearGreedEnabled ? (0, import_timescale3.getMarketCmcFearGreedContextCoverage)({
2517
+ fearGreedEnabled ? (0, import_marketContext2.getMarketCmcFearGreedContextCoverage)({
4120
2518
  source: SOURCE_FEAR_GREED,
4121
2519
  interval: "1d",
4122
2520
  startMs: fromMs,
4123
2521
  endMs: toMs
4124
2522
  }) : Promise.resolve(null),
4125
- (0, import_timescale3.getMarketCmcIndexContextCoverage)({
2523
+ (0, import_marketContext2.getMarketCmcIndexContextCoverage)({
4126
2524
  source: SOURCE_INDEX,
4127
2525
  indexSlugs: CMC_INDEXES.map((index) => index.slug),
4128
2526
  interval: "1d",
4129
2527
  startMs: fromMs,
4130
2528
  endMs: toMs
4131
2529
  }),
4132
- (0, import_timescale3.getMarketContextBackfillCoverage)({
2530
+ (0, import_marketContext2.getMarketContextBackfillCoverage)({
4133
2531
  source: SOURCE_GLOBAL_DAILY,
4134
2532
  scopes: [COVERAGE_SCOPE_ALL],
4135
2533
  interval: "1d",
4136
2534
  fromMs,
4137
2535
  toMs
4138
2536
  }),
4139
- (0, import_timescale3.getMarketContextBackfillCoverage)({
2537
+ (0, import_marketContext2.getMarketContextBackfillCoverage)({
4140
2538
  source: SOURCE_REFERENCE,
4141
2539
  scopes: REFERENCE_ASSETS.map((item) => item.symbol),
4142
2540
  interval: "1d",
4143
2541
  fromMs,
4144
2542
  toMs
4145
2543
  }),
4146
- exchangeLiquidityEnabled ? (0, import_timescale3.getMarketContextBackfillCoverage)({
2544
+ exchangeLiquidityEnabled ? (0, import_marketContext2.getMarketContextBackfillCoverage)({
4147
2545
  source: SOURCE_EXCHANGE_LIQUIDITY,
4148
2546
  scopes: [COVERAGE_SCOPE_ALL],
4149
2547
  interval: "1d",
4150
2548
  fromMs,
4151
2549
  toMs
4152
2550
  }) : Promise.resolve([]),
4153
- fearGreedEnabled ? (0, import_timescale3.getMarketContextBackfillCoverage)({
2551
+ fearGreedEnabled ? (0, import_marketContext2.getMarketContextBackfillCoverage)({
4154
2552
  source: SOURCE_FEAR_GREED,
4155
2553
  scopes: [COVERAGE_SCOPE_ALL],
4156
2554
  interval: "1d",
4157
2555
  fromMs,
4158
2556
  toMs
4159
2557
  }) : Promise.resolve([]),
4160
- (0, import_timescale3.getMarketContextBackfillCoverage)({
2558
+ (0, import_marketContext2.getMarketContextBackfillCoverage)({
4161
2559
  source: SOURCE_INDEX,
4162
2560
  scopes: CMC_INDEXES.map((index) => index.slug),
4163
2561
  interval: "1d",
@@ -4348,7 +2746,7 @@ var backfillCoinMarketCapContext = async (params) => {
4348
2746
  }
4349
2747
  });
4350
2748
  const rows = coinMarketCapGlobalPayloadToRows(payload, SOURCE_GLOBAL_DAILY);
4351
- await (0, import_timescale3.upsertMarketGlobalContextRows)(rows);
2749
+ await (0, import_marketContext2.upsertMarketGlobalContextRows)(rows);
4352
2750
  await markBackfillCoverage([
4353
2751
  {
4354
2752
  source: SOURCE_GLOBAL_DAILY,
@@ -4382,7 +2780,7 @@ var backfillCoinMarketCapContext = async (params) => {
4382
2780
  }
4383
2781
  });
4384
2782
  const rows = coinMarketCapHistoricalQuotesPayloadToRows(payload, "1d");
4385
- await (0, import_timescale3.upsertMarketReferenceAssetContextRows)(rows);
2783
+ await (0, import_marketContext2.upsertMarketReferenceAssetContextRows)(rows);
4386
2784
  await markBackfillCoverage(
4387
2785
  REFERENCE_ASSETS.map((asset) => ({
4388
2786
  source: SOURCE_REFERENCE,
@@ -4421,7 +2819,7 @@ var backfillCoinMarketCapContext = async (params) => {
4421
2819
  payload,
4422
2820
  "1d"
4423
2821
  );
4424
- await (0, import_timescale3.upsertMarketCmcExchangeLiquidityContextRows)(rows);
2822
+ await (0, import_marketContext2.upsertMarketCmcExchangeLiquidityContextRows)(rows);
4425
2823
  await markBackfillCoverage([
4426
2824
  {
4427
2825
  source: SOURCE_EXCHANGE_LIQUIDITY,
@@ -4466,7 +2864,7 @@ var backfillCoinMarketCapContext = async (params) => {
4466
2864
  const oldestPageTs = Math.min(...pageRows.map((row) => row.ts.getTime()));
4467
2865
  if (oldestPageTs < fromMs || pageRows.length < pageSize) break;
4468
2866
  }
4469
- await (0, import_timescale3.upsertMarketCmcFearGreedContextRows)(rows);
2867
+ await (0, import_marketContext2.upsertMarketCmcFearGreedContextRows)(rows);
4470
2868
  await markBackfillCoverage([
4471
2869
  {
4472
2870
  source: SOURCE_FEAR_GREED,
@@ -4500,7 +2898,7 @@ var backfillCoinMarketCapContext = async (params) => {
4500
2898
  }))
4501
2899
  );
4502
2900
  const rows = rowsByIndex.flatMap((item) => item.result.rows);
4503
- await (0, import_timescale3.upsertMarketCmcIndexContextRows)(rows);
2901
+ await (0, import_marketContext2.upsertMarketCmcIndexContextRows)(rows);
4504
2902
  await markBackfillCoverage(
4505
2903
  rowsByIndex.map(({ index, result }) => ({
4506
2904
  source: SOURCE_INDEX,
@@ -4552,7 +2950,7 @@ var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapCo
4552
2950
 
4553
2951
  // src/lib/hyperliquidWhaleBackfill.ts
4554
2952
  var import_progress3 = __toESM(require("progress"));
4555
- var import_timescale4 = require("@tradejs/infra/timescale");
2953
+ var import_hyperliquidWhales = require("@tradejs/infra/timescale/hyperliquidWhales");
4556
2954
  var import_strategies2 = require("@tradejs/node/strategies");
4557
2955
 
4558
2956
  // src/lib/hyperliquidWhaleData.ts
@@ -4807,7 +3205,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4807
3205
  };
4808
3206
  const fromMs = Math.floor(params.startMs / HYPERLIQUID_WHALE_BUCKET_MS) * HYPERLIQUID_WHALE_BUCKET_MS;
4809
3207
  const toMs = minuteCeil(params.endMs);
4810
- const cached = await (0, import_timescale4.hasHyperliquidWhaleBackfillCoverage)({
3208
+ const cached = await (0, import_hyperliquidWhales.hasHyperliquidWhaleBackfillCoverage)({
4811
3209
  fromMs,
4812
3210
  toMs,
4813
3211
  ...identity
@@ -4856,7 +3254,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4856
3254
  items: whales.addresses,
4857
3255
  concurrency,
4858
3256
  worker: async (address) => {
4859
- const previous = await (0, import_timescale4.getHyperliquidWhaleWalletCoverage)({
3257
+ const previous = await (0, import_hyperliquidWhales.getHyperliquidWhaleWalletCoverage)({
4860
3258
  address,
4861
3259
  fromMs,
4862
3260
  toMs,
@@ -4883,8 +3281,8 @@ var backfillHyperliquidWhaleContext = async (params) => {
4883
3281
  identity
4884
3282
  })
4885
3283
  ).filter((row) => row != null);
4886
- await (0, import_timescale4.upsertHyperliquidWhaleTradeEvents)(addressEvents);
4887
- await (0, import_timescale4.upsertHyperliquidWhaleWalletCoverage)({
3284
+ await (0, import_hyperliquidWhales.upsertHyperliquidWhaleTradeEvents)(addressEvents);
3285
+ await (0, import_hyperliquidWhales.upsertHyperliquidWhaleWalletCoverage)({
4888
3286
  address,
4889
3287
  fromMs,
4890
3288
  toMs,
@@ -4902,7 +3300,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4902
3300
  const normalizedError = error instanceof Error ? error : new Error(String(error));
4903
3301
  failures.push(normalizedError);
4904
3302
  failedWallets += 1;
4905
- await (0, import_timescale4.upsertHyperliquidWhaleWalletCoverage)({
3303
+ await (0, import_hyperliquidWhales.upsertHyperliquidWhaleWalletCoverage)({
4906
3304
  address,
4907
3305
  fromMs,
4908
3306
  toMs,
@@ -4921,7 +3319,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4921
3319
  );
4922
3320
  }
4923
3321
  });
4924
- const buckets = await (0, import_timescale4.rebuildHyperliquidWhaleFlowRows)({
3322
+ const buckets = await (0, import_hyperliquidWhales.rebuildHyperliquidWhaleFlowRows)({
4925
3323
  fromMs,
4926
3324
  toMs,
4927
3325
  ...identity
@@ -4937,7 +3335,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4937
3335
  }
4938
3336
  );
4939
3337
  let displayedCoverageBuckets = 0;
4940
- const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
3338
+ const coverageBuckets = await (0, import_hyperliquidWhales.rebuildHyperliquidWhaleCoverageRows)({
4941
3339
  fromMs,
4942
3340
  toMs,
4943
3341
  expectedWhales: whales.addresses.length,
@@ -5137,17 +3535,17 @@ var prepareMarketContextForRun = async (params) => {
5137
3535
  const log = params.log ?? ((message) => {
5138
3536
  console.log(import_chalk4.default.gray(message));
5139
3537
  });
5140
- const timeOperation3 = (label, operation) => timeOperation(label, operation, log);
3538
+ const timeOperation2 = (label, operation) => timeOperation(label, operation, log);
5141
3539
  const requirements = await resolveMarketContextRunRequirements(params);
5142
3540
  const readableSources = Object.entries(requirements).filter(([, requirement]) => requirement.read).map(([source]) => source);
5143
3541
  if (readableSources.length) {
5144
- await timeOperation3(
3542
+ await timeOperation2(
5145
3543
  "market context schema ensure",
5146
- () => (0, import_timescale5.ensureMarketContextSchemas)(readableSources)
3544
+ () => (0, import_marketContext3.ensureMarketContextSchemas)(readableSources)
5147
3545
  );
5148
3546
  }
5149
3547
  if (requirements.derivatives.backfill) {
5150
- await timeOperation3(
3548
+ await timeOperation2(
5151
3549
  "derivatives context backfill",
5152
3550
  () => (params.mode === "signals" ? backfillDerivativesContextForSignals : backfillDerivativesContextForBacktest)(
5153
3551
  buildDerivativesBackfillParams(params)
@@ -5155,7 +3553,7 @@ var prepareMarketContextForRun = async (params) => {
5155
3553
  );
5156
3554
  }
5157
3555
  if (requirements.hyperliquidWhales.backfill) {
5158
- await timeOperation3(
3556
+ await timeOperation2(
5159
3557
  "hyperliquid whale context backfill",
5160
3558
  () => backfillHyperliquidWhaleContext({
5161
3559
  startMs: params.preloadStartMs ?? params.startMs,
@@ -5167,13 +3565,13 @@ var prepareMarketContextForRun = async (params) => {
5167
3565
  );
5168
3566
  }
5169
3567
  if (requirements.binance.backfill) {
5170
- await timeOperation3("binance market context backfill", () => {
3568
+ await timeOperation2("binance market context backfill", () => {
5171
3569
  const backfill = params.mode === "backtest" ? backfillBinanceMarketContextForBacktest : params.mode === "signals" ? backfillBinanceMarketContextForSignals : backfillBinanceMarketContextForReplay;
5172
3570
  return backfill(buildBinanceMarketBackfillParams(params));
5173
3571
  });
5174
3572
  }
5175
3573
  if (requirements.coinmarketcap.backfill) {
5176
- await timeOperation3(
3574
+ await timeOperation2(
5177
3575
  "coinmarketcap historical context backfill",
5178
3576
  () => resolveCoinMarketCapBackfillForMode(params.mode)(
5179
3577
  buildCoinMarketCapBackfillParams(params)
@@ -5195,7 +3593,7 @@ var loadBtcReferenceConnectors = async ({
5195
3593
  connectorName,
5196
3594
  marketConnector,
5197
3595
  userName,
5198
- projectRoot: projectRoot2,
3596
+ projectRoot,
5199
3597
  shouldUseDedicatedReferences,
5200
3598
  requireDedicatedReferences = false,
5201
3599
  warn
@@ -5207,8 +3605,8 @@ var loadBtcReferenceConnectors = async ({
5207
3605
  };
5208
3606
  }
5209
3607
  const [binanceFactory, coinbaseFactory] = await Promise.all([
5210
- (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance, projectRoot2),
5211
- (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase, projectRoot2)
3608
+ (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance, projectRoot),
3609
+ (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase, projectRoot)
5212
3610
  ]);
5213
3611
  const binance = binanceFactory ? await binanceFactory({ userName }) : marketConnector;
5214
3612
  if (!binanceFactory) {
@@ -5230,7 +3628,7 @@ var updateMarketHistoryWithBtcReferences = async ({
5230
3628
  marketConnector,
5231
3629
  connectorName,
5232
3630
  btcReferences,
5233
- interval: interval2,
3631
+ interval,
5234
3632
  symbols,
5235
3633
  preloadDays,
5236
3634
  preloadStart,
@@ -5241,7 +3639,7 @@ var updateMarketHistoryWithBtcReferences = async ({
5241
3639
  await updatePrimaryMarketHistory({
5242
3640
  marketConnector,
5243
3641
  connectorName,
5244
- interval: interval2,
3642
+ interval,
5245
3643
  symbols,
5246
3644
  preloadDays,
5247
3645
  preloadStart,
@@ -5252,7 +3650,7 @@ var updateMarketHistoryWithBtcReferences = async ({
5252
3650
  await updateBtcReferenceHistory({
5253
3651
  marketConnector,
5254
3652
  btcReferences,
5255
- interval: interval2,
3653
+ interval,
5256
3654
  preloadDays,
5257
3655
  preloadStart,
5258
3656
  preloadEnd,
@@ -5263,7 +3661,7 @@ var updateMarketHistoryWithBtcReferences = async ({
5263
3661
  var updatePrimaryMarketHistory = async ({
5264
3662
  marketConnector,
5265
3663
  connectorName,
5266
- interval: interval2,
3664
+ interval,
5267
3665
  symbols,
5268
3666
  preloadDays,
5269
3667
  preloadStart,
@@ -5272,7 +3670,7 @@ var updatePrimaryMarketHistory = async ({
5272
3670
  universe = marketConnector.universe ?? "crypto"
5273
3671
  }) => {
5274
3672
  if (!symbols.length) return;
5275
- const timeOperation3 = (label, operation) => timeOperation(
3673
+ const timeOperation2 = (label, operation) => timeOperation(
5276
3674
  label,
5277
3675
  operation,
5278
3676
  log ?? ((message) => console.log(import_chalk5.default.gray(message)))
@@ -5282,11 +3680,11 @@ var updatePrimaryMarketHistory = async ({
5282
3680
  ...preloadStart != null ? { preloadStart } : {},
5283
3681
  ...preloadEnd != null ? { preloadEnd } : {}
5284
3682
  } : { connectorLabel: connectorName };
5285
- await timeOperation3(
3683
+ await timeOperation2(
5286
3684
  `update ${connectorName}`,
5287
3685
  () => (0, import_cli.update)(
5288
3686
  marketConnector,
5289
- interval2,
3687
+ interval,
5290
3688
  universe === "crypto" ? withPrimaryMarketReferenceSymbols(symbols) : symbols,
5291
3689
  preloadDays,
5292
3690
  updateOptions
@@ -5296,7 +3694,7 @@ var updatePrimaryMarketHistory = async ({
5296
3694
  var updateBtcReferenceHistory = async ({
5297
3695
  marketConnector,
5298
3696
  btcReferences,
5299
- interval: interval2,
3697
+ interval,
5300
3698
  preloadDays,
5301
3699
  preloadStart,
5302
3700
  preloadEnd,
@@ -5304,7 +3702,7 @@ var updateBtcReferenceHistory = async ({
5304
3702
  universe = marketConnector.universe ?? "crypto"
5305
3703
  }) => {
5306
3704
  if (universe !== "crypto") return;
5307
- const timeOperation3 = (label, operation) => timeOperation(
3705
+ const timeOperation2 = (label, operation) => timeOperation(
5308
3706
  label,
5309
3707
  operation,
5310
3708
  log ?? ((message) => console.log(import_chalk5.default.gray(message)))
@@ -5321,9 +3719,9 @@ var updateBtcReferenceHistory = async ({
5321
3719
  ...preloadStart != null ? { preloadStart } : {},
5322
3720
  ...preloadEnd != null ? { preloadEnd } : {}
5323
3721
  } : { connectorLabel };
5324
- await timeOperation3(
3722
+ await timeOperation2(
5325
3723
  `update ${connectorLabel}`,
5326
- () => (0, import_cli.update)(connector, interval2, ["BTCUSDT"], preloadDays, referenceOptions)
3724
+ () => (0, import_cli.update)(connector, interval, ["BTCUSDT"], preloadDays, referenceOptions)
5327
3725
  );
5328
3726
  };
5329
3727
  await updateReference({
@@ -5345,73 +3743,27 @@ var import_strategies3 = require("@tradejs/node/strategies");
5345
3743
  // src/lib/runtimeRedis.ts
5346
3744
  var import_redis = require("@tradejs/infra/redis");
5347
3745
  var import_time = require("@tradejs/core/time");
5348
- var RESERVED_STRATEGY_NAMES = /* @__PURE__ */ new Set(["charts"]);
5349
- var RESERVED_CONFIG_IDS = /* @__PURE__ */ new Set(["results"]);
5350
- var resolveStrategyConfigIdentityByKey = (userName, key) => {
5351
- const parts = key.split(":");
5352
- if (parts.length !== 5) return null;
5353
- const [users, keyUserName, strategiesKey, strategyName, configId] = parts;
5354
- if (users !== "users" || keyUserName !== userName || strategiesKey !== "strategies" || !strategyName || !configId || RESERVED_STRATEGY_NAMES.has(strategyName) || RESERVED_CONFIG_IDS.has(configId) || !/^[a-zA-Z0-9_-]+$/.test(configId)) {
5355
- return null;
5356
- }
5357
- return { strategyName, configId };
5358
- };
3746
+ var import_runtimeStrategyConfigs = require("@tradejs/infra/runtimeStrategyConfigs");
5359
3747
  var isRuntimeStrategyEnabled = (strategyConfig) => {
5360
3748
  const enabled = strategyConfig.ENABLE;
5361
3749
  return enabled !== false;
5362
3750
  };
5363
- var resolveStrategyNameByConfigKey = (userName, key) => {
5364
- return resolveStrategyConfigIdentityByKey(userName, key)?.strategyName ?? null;
5365
- };
5366
- var getRuntimeStrategyConfigKeys = async (userName) => {
5367
- const keys = await (0, import_redis.getKeys)(`${import_redis.redisKeys.strategies(userName)}:`);
5368
- return keys.filter((key) => resolveStrategyConfigIdentityByKey(userName, key)).sort((left, right) => left.localeCompare(right));
5369
- };
5370
- var loadRuntimeStrategyConfigs = async (userName, {
5371
- onInvalidConfig
5372
- } = {}) => {
5373
- const configKeys = await getRuntimeStrategyConfigKeys(userName);
5374
- const strategyConfigs = await Promise.all(
5375
- configKeys.map(async (key) => {
5376
- const strategyName = resolveStrategyNameByConfigKey(userName, key);
5377
- const identity = resolveStrategyConfigIdentityByKey(userName, key);
5378
- if (!strategyName || !identity) {
5379
- return null;
5380
- }
5381
- const strategyConfig = await (0, import_redis.getData)(
5382
- key,
5383
- null
5384
- );
5385
- if (!strategyConfig || typeof strategyConfig !== "object" || Array.isArray(strategyConfig)) {
5386
- onInvalidConfig?.(key);
5387
- return null;
5388
- }
5389
- return {
5390
- key,
5391
- strategyName,
5392
- configId: identity.configId,
5393
- strategyConfig
5394
- };
5395
- })
5396
- );
5397
- return strategyConfigs.filter(Boolean);
5398
- };
5399
3751
 
5400
3752
  // src/lib/signals/runtimeStrategies.ts
5401
3753
  var loadRuntimeStrategies = async ({
5402
3754
  userName,
5403
- projectRoot: projectRoot2,
3755
+ projectRoot,
5404
3756
  deployment,
5405
3757
  connectorName = "bybit",
5406
3758
  universe,
5407
3759
  accountId,
5408
- interval: interval2
3760
+ interval
5409
3761
  }) => {
5410
3762
  const deploymentStrategies = new Map(
5411
3763
  (deployment?.strategies ?? []).filter(({ enabled }) => enabled !== false).map((strategy) => [strategy.strategyName, strategy])
5412
3764
  );
5413
3765
  const strategyConfigs = await Promise.all(
5414
- (await loadRuntimeStrategyConfigs(userName)).map(
3766
+ (await (0, import_runtimeStrategyConfigs.loadRuntimeStrategyConfigs)(userName)).map(
5415
3767
  async ({
5416
3768
  key,
5417
3769
  strategyName,
@@ -5440,7 +3792,7 @@ var loadRuntimeStrategies = async ({
5440
3792
  });
5441
3793
  const effectiveAccountId = resolvedAccount?.id ?? requestedAccountId;
5442
3794
  const [strategyCreator, strategyResults] = await Promise.all([
5443
- (0, import_strategies3.getStrategyCreator)(strategyName, projectRoot2),
3795
+ (0, import_strategies3.getStrategyCreator)(strategyName, projectRoot),
5444
3796
  (0, import_redis2.getData)(import_redis2.redisKeys.strategyResults(userName, strategyName), {})
5445
3797
  ]);
5446
3798
  if (!strategyCreator) {
@@ -5481,7 +3833,7 @@ var loadRuntimeStrategies = async ({
5481
3833
  byStrategyAndAccount.set(conflictKey, candidate);
5482
3834
  }
5483
3835
  return active.filter(
5484
- (candidate) => (!universe || candidate.universe === universe) && (!interval2 || String(candidate.interval) === String(interval2)) && (!accountId || candidate.accountId === accountId)
3836
+ (candidate) => (!universe || candidate.universe === universe) && (!interval || String(candidate.interval) === String(interval)) && (!accountId || candidate.accountId === accountId)
5485
3837
  );
5486
3838
  };
5487
3839
 
@@ -5697,11 +4049,11 @@ var normalizeForStableJson = (value) => {
5697
4049
  }
5698
4050
  return value;
5699
4051
  };
5700
- var resolveRuntimeMaxLossValue = (config) => {
5701
- if (!config || typeof config !== "object" || Array.isArray(config)) {
4052
+ var resolveRuntimeMaxLossValue = (config2) => {
4053
+ if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) {
5702
4054
  return null;
5703
4055
  }
5704
- const strategyConfig = config.strategyConfig;
4056
+ const strategyConfig = config2.strategyConfig;
5705
4057
  if (!strategyConfig || typeof strategyConfig !== "object" || Array.isArray(strategyConfig)) {
5706
4058
  return null;
5707
4059
  }
@@ -5715,8 +4067,8 @@ var gitLineageCache = /* @__PURE__ */ new Map();
5715
4067
  var gateFingerprintCache = /* @__PURE__ */ new Map();
5716
4068
  var binanceBreadthFingerprintCache = /* @__PURE__ */ new Map();
5717
4069
  var snapshotFingerprintCache = /* @__PURE__ */ new Map();
5718
- var resolveGitLineage = (projectRoot2) => {
5719
- const cached = gitLineageCache.get(projectRoot2);
4070
+ var resolveGitLineage = (projectRoot) => {
4071
+ const cached = gitLineageCache.get(projectRoot);
5720
4072
  if (cached) {
5721
4073
  return cached;
5722
4074
  }
@@ -5726,12 +4078,12 @@ var resolveGitLineage = (projectRoot2) => {
5726
4078
  gitSha: envSha,
5727
4079
  gitDirty: false
5728
4080
  };
5729
- gitLineageCache.set(projectRoot2, result);
4081
+ gitLineageCache.set(projectRoot, result);
5730
4082
  return result;
5731
4083
  }
5732
4084
  try {
5733
4085
  const gitSha = (0, import_node_child_process.execFileSync)("git", ["rev-parse", "HEAD"], {
5734
- cwd: projectRoot2,
4086
+ cwd: projectRoot,
5735
4087
  encoding: "utf8",
5736
4088
  stdio: ["ignore", "pipe", "ignore"]
5737
4089
  }).trim();
@@ -5739,7 +4091,7 @@ var resolveGitLineage = (projectRoot2) => {
5739
4091
  "git",
5740
4092
  ["status", "--porcelain", "--untracked-files=normal"],
5741
4093
  {
5742
- cwd: projectRoot2,
4094
+ cwd: projectRoot,
5743
4095
  encoding: "utf8",
5744
4096
  stdio: ["ignore", "pipe", "ignore"]
5745
4097
  }
@@ -5748,14 +4100,14 @@ var resolveGitLineage = (projectRoot2) => {
5748
4100
  gitSha: gitSha || null,
5749
4101
  gitDirty: status.length > 0
5750
4102
  };
5751
- gitLineageCache.set(projectRoot2, result);
4103
+ gitLineageCache.set(projectRoot, result);
5752
4104
  return result;
5753
4105
  } catch {
5754
4106
  const result = {
5755
4107
  gitSha: null,
5756
4108
  gitDirty: null
5757
4109
  };
5758
- gitLineageCache.set(projectRoot2, result);
4110
+ gitLineageCache.set(projectRoot, result);
5759
4111
  return result;
5760
4112
  }
5761
4113
  };
@@ -5766,13 +4118,13 @@ var readOptionalFile = async (filePath) => {
5766
4118
  return null;
5767
4119
  }
5768
4120
  };
5769
- var resolveBinanceBreadthFingerprint = async (projectRoot2) => {
5770
- if (binanceBreadthFingerprintCache.has(projectRoot2)) {
5771
- return binanceBreadthFingerprintCache.get(projectRoot2) ?? null;
4121
+ var resolveBinanceBreadthFingerprint = async (projectRoot) => {
4122
+ if (binanceBreadthFingerprintCache.has(projectRoot)) {
4123
+ return binanceBreadthFingerprintCache.get(projectRoot) ?? null;
5772
4124
  }
5773
4125
  const content = await readOptionalFile(
5774
4126
  import_node_path.default.join(
5775
- projectRoot2,
4127
+ projectRoot,
5776
4128
  "packages/node/src/config/binanceBreadthUniverses.json"
5777
4129
  )
5778
4130
  );
@@ -5785,15 +4137,15 @@ var resolveBinanceBreadthFingerprint = async (projectRoot2) => {
5785
4137
  result = null;
5786
4138
  }
5787
4139
  }
5788
- binanceBreadthFingerprintCache.set(projectRoot2, result);
4140
+ binanceBreadthFingerprintCache.set(projectRoot, result);
5789
4141
  return result;
5790
4142
  };
5791
- var resolveSnapshotFingerprint = async (projectRoot2, relativePath) => {
5792
- const cacheKey = `${projectRoot2}:${relativePath}`;
4143
+ var resolveSnapshotFingerprint = async (projectRoot, relativePath) => {
4144
+ const cacheKey = `${projectRoot}:${relativePath}`;
5793
4145
  if (snapshotFingerprintCache.has(cacheKey)) {
5794
4146
  return snapshotFingerprintCache.get(cacheKey) ?? null;
5795
4147
  }
5796
- const content = await readOptionalFile(import_node_path.default.join(projectRoot2, relativePath));
4148
+ const content = await readOptionalFile(import_node_path.default.join(projectRoot, relativePath));
5797
4149
  let result = null;
5798
4150
  if (content) {
5799
4151
  try {
@@ -5807,11 +4159,11 @@ var resolveSnapshotFingerprint = async (projectRoot2, relativePath) => {
5807
4159
  return result;
5808
4160
  };
5809
4161
  var resolveGateFingerprint = async ({
5810
- projectRoot: projectRoot2,
4162
+ projectRoot,
5811
4163
  strategyName,
5812
4164
  gitSha
5813
4165
  }) => {
5814
- const cacheKey = `${projectRoot2}:${strategyName}:${gitSha ?? "unknown"}`;
4166
+ const cacheKey = `${projectRoot}:${strategyName}:${gitSha ?? "unknown"}`;
5815
4167
  const cached = gateFingerprintCache.get(cacheKey);
5816
4168
  if (cached) {
5817
4169
  return cached;
@@ -5827,7 +4179,7 @@ var resolveGateFingerprint = async ({
5827
4179
  const optionalEntries = await Promise.all(
5828
4180
  relativeCandidates.map(async (relativePath) => {
5829
4181
  const content = await readOptionalFile(
5830
- import_node_path.default.join(projectRoot2, relativePath)
4182
+ import_node_path.default.join(projectRoot, relativePath)
5831
4183
  );
5832
4184
  return content == null ? null : { relativePath, content };
5833
4185
  })
@@ -5853,19 +4205,19 @@ var resolveGateFingerprint = async ({
5853
4205
  return fingerprint;
5854
4206
  };
5855
4207
  var buildRuntimeLineage = async ({
5856
- projectRoot: projectRoot2,
4208
+ projectRoot,
5857
4209
  strategyName,
5858
- config,
4210
+ config: config2,
5859
4211
  runContext,
5860
4212
  env = process.env
5861
4213
  }) => {
5862
- const git = resolveGitLineage(projectRoot2);
4214
+ const git = resolveGitLineage(projectRoot);
5863
4215
  const hyperliquidPerpUniverseFingerprint = typeof import_strategies4.getHyperliquidPerpUniverseSnapshot === "function" ? (0, import_strategies4.getHyperliquidPerpUniverseSnapshot)().fingerprint : await resolveSnapshotFingerprint(
5864
- projectRoot2,
4216
+ projectRoot,
5865
4217
  "packages/node/src/config/hyperliquidPerpUniverse.json"
5866
4218
  );
5867
4219
  const hyperliquidWhaleRegistryFingerprint = typeof import_strategies4.getHyperliquidWhaleRegistrySnapshot === "function" ? (0, import_strategies4.getHyperliquidWhaleRegistrySnapshot)().fingerprint : await resolveSnapshotFingerprint(
5868
- projectRoot2,
4220
+ projectRoot,
5869
4221
  "packages/node/src/config/hyperliquidWhales.json"
5870
4222
  );
5871
4223
  const context = {
@@ -5873,7 +4225,7 @@ var buildRuntimeLineage = async ({
5873
4225
  RUNTIME_CONTEXT_ENV_KEYS.map((key) => [key, env[key] ?? null])
5874
4226
  ),
5875
4227
  ...RUNTIME_CONTEXT_DATA_MODEL,
5876
- binanceBreadthUniverseFingerprint: await resolveBinanceBreadthFingerprint(projectRoot2),
4228
+ binanceBreadthUniverseFingerprint: await resolveBinanceBreadthFingerprint(projectRoot),
5877
4229
  hyperliquidPerpUniverseFingerprint,
5878
4230
  hyperliquidWhaleRegistryFingerprint,
5879
4231
  ...runContext
@@ -5882,13 +4234,13 @@ var buildRuntimeLineage = async ({
5882
4234
  schemaVersion: 1,
5883
4235
  ...git,
5884
4236
  gateFingerprint: await resolveGateFingerprint({
5885
- projectRoot: projectRoot2,
4237
+ projectRoot,
5886
4238
  strategyName,
5887
4239
  gitSha: git.gitSha
5888
4240
  }),
5889
- configFingerprint: fingerprintRuntimeValue(config),
4241
+ configFingerprint: fingerprintRuntimeValue(config2),
5890
4242
  contextFingerprint: fingerprintRuntimeValue(context),
5891
- maxLossValue: resolveRuntimeMaxLossValue(config)
4243
+ maxLossValue: resolveRuntimeMaxLossValue(config2)
5892
4244
  };
5893
4245
  };
5894
4246
  var runtimeLineageKey = (lineage) => [
@@ -6078,23 +4430,6 @@ var getTelegramDeliverableSignals = (signals2) => signals2.filter(
6078
4430
  (signal) => signal.orderStatus !== "skipped" && signal.orderStatus !== "canceled"
6079
4431
  );
6080
4432
 
6081
- // src/lib/runtimeModeConfig.ts
6082
- var buildRuntimeModeStrategyConfig = ({
6083
- strategyConfig,
6084
- env,
6085
- interval: interval2,
6086
- makeOrders,
6087
- recordRuntimeTrades,
6088
- aiReplayAnalyses
6089
- }) => ({
6090
- ...strategyConfig,
6091
- ENV: env,
6092
- MAKE_ORDERS: makeOrders,
6093
- INTERVAL: interval2,
6094
- ...typeof recordRuntimeTrades === "boolean" ? { RECORD_RUNTIME_TRADES: recordRuntimeTrades } : {},
6095
- ...aiReplayAnalyses?.length ? { AI_REPLAY_ANALYSES: aiReplayAnalyses } : {}
6096
- });
6097
-
6098
4433
  // src/lib/signals/runtimeLifecycle.ts
6099
4434
  var stableStringify = (value) => {
6100
4435
  if (value == null || typeof value !== "object") {
@@ -6112,13 +4447,13 @@ var buildSignalsStrategyLifecycleKey = ({
6112
4447
  accountId,
6113
4448
  deploymentId,
6114
4449
  symbol,
6115
- interval: interval2,
4450
+ interval,
6116
4451
  strategyName,
6117
4452
  configId
6118
4453
  }) => {
6119
4454
  const namedConfigId = configId && configId !== "config" ? configId : void 0;
6120
4455
  if (!universe && !accountId && !deploymentId) {
6121
- return [connectorName, symbol, interval2, strategyName, namedConfigId].filter(Boolean).join(":");
4456
+ return [connectorName, symbol, interval, strategyName, namedConfigId].filter(Boolean).join(":");
6122
4457
  }
6123
4458
  return [
6124
4459
  connectorName,
@@ -6126,17 +4461,17 @@ var buildSignalsStrategyLifecycleKey = ({
6126
4461
  accountId ?? "default",
6127
4462
  deploymentId ?? "default",
6128
4463
  symbol,
6129
- interval2,
4464
+ interval,
6130
4465
  strategyName,
6131
4466
  namedConfigId
6132
4467
  ].filter(Boolean).join(":");
6133
4468
  };
6134
4469
  var createSignalsStrategyLifecycle = ({
6135
- intervalMs: intervalMs2,
4470
+ intervalMs,
6136
4471
  maxLiveBars,
6137
4472
  releaseState = () => void 0
6138
4473
  }) => {
6139
- if (!Number.isFinite(intervalMs2) || intervalMs2 <= 0) {
4474
+ if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
6140
4475
  throw new Error("Signals strategy lifecycle requires a positive interval");
6141
4476
  }
6142
4477
  if (!Number.isFinite(maxLiveBars) || maxLiveBars <= 0) {
@@ -6147,7 +4482,7 @@ var createSignalsStrategyLifecycle = ({
6147
4482
  const evaluate = async ({
6148
4483
  key,
6149
4484
  timestamp,
6150
- config,
4485
+ config: config2,
6151
4486
  btcBinanceData,
6152
4487
  btcCoinbaseData,
6153
4488
  onRuntimeClose,
@@ -6157,7 +4492,7 @@ var createSignalsStrategyLifecycle = ({
6157
4492
  if (!Number.isFinite(timestamp)) {
6158
4493
  throw new Error(`Signals strategy lifecycle received ${timestamp}`);
6159
4494
  }
6160
- const configFingerprint = stableStringify(config);
4495
+ const configFingerprint = stableStringify(config2);
6161
4496
  const current = entries.get(key);
6162
4497
  if (current) {
6163
4498
  if (timestamp === current.lastTimestamp) {
@@ -6170,7 +4505,7 @@ var createSignalsStrategyLifecycle = ({
6170
4505
  let action = "created";
6171
4506
  if (current && current.configFingerprint !== configFingerprint) {
6172
4507
  action = "rebuilt_config";
6173
- } else if (current && timestamp !== current.lastTimestamp + intervalMs2) {
4508
+ } else if (current && timestamp !== current.lastTimestamp + intervalMs) {
6174
4509
  action = "rebuilt_gap";
6175
4510
  } else if (current && current.processedBars >= normalizedMaxLiveBars) {
6176
4511
  action = "rebuilt_limit";
@@ -6226,18 +4561,18 @@ var createSignalsStrategyLifecycle = ({
6226
4561
  // src/lib/signals/daemon.ts
6227
4562
  var getNextSignalsCycleDelay = ({
6228
4563
  now,
6229
- intervalMs: intervalMs2,
4564
+ intervalMs,
6230
4565
  settleDelayMs
6231
4566
  }) => {
6232
- const nextBoundary = (Math.floor(now / intervalMs2) + 1) * intervalMs2;
4567
+ const nextBoundary = (Math.floor(now / intervalMs) + 1) * intervalMs;
6233
4568
  return Math.max(0, nextBoundary + settleDelayMs - now);
6234
4569
  };
6235
4570
  var getCurrentSignalsCycleDelay = ({
6236
4571
  now,
6237
- intervalMs: intervalMs2,
4572
+ intervalMs,
6238
4573
  settleDelayMs
6239
4574
  }) => {
6240
- const currentBoundary = Math.floor(now / intervalMs2) * intervalMs2;
4575
+ const currentBoundary = Math.floor(now / intervalMs) * intervalMs;
6241
4576
  return Math.max(0, currentBoundary + settleDelayMs - now);
6242
4577
  };
6243
4578
  var getSignalsHeartbeatStatus = ({
@@ -6264,7 +4599,7 @@ var waitForNextCycle = (delayMs, signal) => new Promise((resolve) => {
6264
4599
  });
6265
4600
  var runSignalsDaemon = async ({
6266
4601
  runCycle,
6267
- intervalMs: intervalMs2,
4602
+ intervalMs,
6268
4603
  settleDelayMs,
6269
4604
  signal,
6270
4605
  onCycleError,
@@ -6273,7 +4608,7 @@ var runSignalsDaemon = async ({
6273
4608
  }) => {
6274
4609
  const initialDelay = getCurrentSignalsCycleDelay({
6275
4610
  now: now(),
6276
- intervalMs: intervalMs2,
4611
+ intervalMs,
6277
4612
  settleDelayMs
6278
4613
  });
6279
4614
  if (initialDelay > 0) {
@@ -6283,7 +4618,7 @@ var runSignalsDaemon = async ({
6283
4618
  const cycleStartedAt = now();
6284
4619
  const nextCycleAt = cycleStartedAt + getNextSignalsCycleDelay({
6285
4620
  now: cycleStartedAt,
6286
- intervalMs: intervalMs2,
4621
+ intervalMs,
6287
4622
  settleDelayMs
6288
4623
  });
6289
4624
  try {
@@ -6301,7 +4636,7 @@ var runSignalsDaemon = async ({
6301
4636
  // src/lib/signals/klineFeed.ts
6302
4637
  var import_connectors5 = require("@tradejs/connectors");
6303
4638
  var import_logger3 = require("@tradejs/infra/logger");
6304
- var import_timescale6 = require("@tradejs/infra/timescale");
4639
+ var import_candles = require("@tradejs/infra/timescale/candles");
6305
4640
 
6306
4641
  // src/lib/marketData/klineEvents.ts
6307
4642
  var import_ioredis = __toESM(require("ioredis"));
@@ -6315,15 +4650,15 @@ var normalizeSymbols2 = (symbols) => [...new Set(symbols.map((symbol) => symbol.
6315
4650
  Boolean
6316
4651
  );
6317
4652
  var createSignalsKlineFeed = async ({
6318
- config,
6319
- interval: interval2,
4653
+ config: config2,
4654
+ interval,
6320
4655
  universe,
6321
4656
  publish = publishMarketKlineEvent,
6322
4657
  persist = async (rows) => {
6323
- const intervalMinutes = Number(interval2);
6324
- await (0, import_timescale6.upsertCandles)(
4658
+ const intervalMinutes = Number(interval);
4659
+ await (0, import_candles.upsertCandles)(
6325
4660
  rows.flatMap(
6326
- ({ symbol, candle }) => (0, import_timescale6.toRows)("bybit", symbol, intervalMinutes, [candle])
4661
+ ({ symbol, candle }) => (0, import_candles.toRows)("bybit", symbol, intervalMinutes, [candle])
6327
4662
  )
6328
4663
  );
6329
4664
  },
@@ -6366,14 +4701,14 @@ var createSignalsKlineFeed = async ({
6366
4701
  }, FLUSH_DELAY_MS);
6367
4702
  };
6368
4703
  const stream = await streamFactory({
6369
- config,
4704
+ config: config2,
6370
4705
  onEvent: (event) => {
6371
- if (event.interval !== interval2) return;
4706
+ if (event.interval !== interval) return;
6372
4707
  void publish({
6373
4708
  provider: "bybit",
6374
4709
  universe,
6375
4710
  symbol: event.symbol,
6376
- interval: interval2,
4711
+ interval,
6377
4712
  candle: event.candle,
6378
4713
  confirm: event.confirm,
6379
4714
  receivedAt: event.receivedAt
@@ -6392,7 +4727,7 @@ var createSignalsKlineFeed = async ({
6392
4727
  });
6393
4728
  return {
6394
4729
  setSubscriptions: (symbols) => {
6395
- stream.setSubscriptions(normalizeSymbols2(symbols), interval2);
4730
+ stream.setSubscriptions(normalizeSymbols2(symbols), interval);
6396
4731
  },
6397
4732
  waitForClosed: async ({ symbols, timestamp, timeoutMs, signal }) => {
6398
4733
  const expected = normalizeSymbols2(symbols);
@@ -6430,197 +4765,82 @@ var createSignalsKlineFeed = async ({
6430
4765
  };
6431
4766
  };
6432
4767
 
6433
- // src/scripts/signals.ts
6434
- import_args.default.option(["t", "tickers"], "Selected tickers");
6435
- import_args.default.option(["e", "exclude"], "Exclude tickers from tests");
6436
- import_args.default.option(["l", "tickersLimit"], "Tickers limit");
6437
- import_args.default.option(["f", "timeframe"], "Timeframe", 15);
6438
- import_args.default.option(["m", "makeOrders"], "Make orders");
6439
- import_args.default.option(["N", "notify"], "Send message in Telegram", false);
6440
- import_args.default.option(["S", "skipScreenshots"], "Skip screenshot generation", false);
6441
- import_args.default.option(["u", "updateOnly"], "Only update tickers history", false);
6442
- import_args.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
6443
- import_args.default.option(["L", "showTickersList"], "Just show only ticker list", false);
6444
- import_args.default.option(
6445
- ["p", "parallel"],
6446
- "Signal evaluation worker count",
6447
- Number(process.env.SIGNALS_PARALLEL || 4)
6448
- );
6449
- import_args.default.option(
6450
- ["R", "showSkipStats"],
6451
- "Show aggregated skip stats by strategy",
6452
- false
6453
- );
6454
- import_args.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
6455
- import_args.default.option(["U", "user"], "Use user confg", "root");
6456
- import_args.default.option(["w", "watch"], "Keep signals running on candle boundaries", false);
6457
- import_args.default.option(
6458
- ["d", "settleDelayMs"],
6459
- "Delay after candle close before a daemon cycle",
6460
- Number(process.env.SIGNALS_DAEMON_SETTLE_DELAY_MS || 5e3)
6461
- );
6462
- import_args.default.option(
6463
- ["o", "connector"],
6464
- "Connector provider or name for signals (e.g. bybit, binance, coinbase, custom)",
6465
- "bybit"
6466
- );
6467
- import_args.default.option(["V", "universe"], "Market universe (crypto or tradfi)", "crypto");
6468
- import_args.default.option(["A", "account"], "Trading account id");
6469
- import_args.default.option(["D", "deployment"], "Runtime deployment id");
6470
- var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
6471
- var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
6472
- var flags = import_args.default.parse(process.argv);
6473
- var interval = flags.timeframe.toString();
6474
- var intervalMs = Number(interval) * 6e4;
6475
- var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
6476
- var resolvePositiveInteger = (value, fallback) => {
6477
- const parsed = Number(value);
6478
- if (!Number.isFinite(parsed)) {
6479
- return fallback;
6480
- }
6481
- const normalized = Math.floor(parsed);
6482
- return normalized > 0 ? normalized : fallback;
6483
- };
6484
- var resolveNonNegativeInteger = (value, fallback) => {
6485
- const parsed = Number(value);
6486
- if (!Number.isFinite(parsed)) {
6487
- return fallback;
6488
- }
6489
- return Math.max(0, Math.floor(parsed));
6490
- };
6491
- var resolveSignalsDaemonMaxLiveBars = (runtimeInterval = interval) => {
6492
- const intervalMinutes = Number(runtimeInterval);
6493
- const preloadBars = Math.ceil(
6494
- import_constants3.SIGNALS_CLI_PRELOAD_DAYS * 24 * 60 / intervalMinutes
6495
- );
6496
- return resolvePositiveInteger(
6497
- process.env.SIGNALS_DAEMON_MAX_LIVE_BARS,
6498
- preloadBars
6499
- );
6500
- };
6501
- var isSignalsKlineWsEnabled = () => !["0", "false", "off", "no"].includes(
6502
- String(process.env.SIGNALS_KLINE_WS_ENABLED ?? "true").trim().toLowerCase()
6503
- );
6504
- var resolveSignalsKlineWsWaitMs = () => resolveNonNegativeInteger(process.env.SIGNALS_KLINE_WS_WAIT_MS, 1e4);
6505
- var createDefaultSignalsLifecycle = (runtimeInterval = interval) => createSignalsStrategyLifecycle({
6506
- intervalMs: Number(runtimeInterval) * 6e4,
6507
- maxLiveBars: resolveSignalsDaemonMaxLiveBars(runtimeInterval),
6508
- releaseState: import_strategies5.releaseStrategyReplayCache
4768
+ // src/lib/signals/tickerEvaluator.ts
4769
+ var import_strategies5 = require("@tradejs/node/strategies");
4770
+ var import_logger4 = require("@tradejs/infra/logger");
4771
+
4772
+ // src/lib/runtimeModeConfig.ts
4773
+ var buildRuntimeModeStrategyConfig = ({
4774
+ strategyConfig,
4775
+ env,
4776
+ interval,
4777
+ makeOrders,
4778
+ recordRuntimeTrades,
4779
+ aiReplayAnalyses
4780
+ }) => ({
4781
+ ...strategyConfig,
4782
+ ENV: env,
4783
+ MAKE_ORDERS: makeOrders,
4784
+ INTERVAL: interval,
4785
+ ...typeof recordRuntimeTrades === "boolean" ? { RECORD_RUNTIME_TRADES: recordRuntimeTrades } : {},
4786
+ ...aiReplayAnalyses?.length ? { AI_REPLAY_ANALYSES: aiReplayAnalyses } : {}
6509
4787
  });
6510
- var timeOperation2 = (label, operation) => timeOperation(
6511
- label,
6512
- operation,
6513
- (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
6514
- );
6515
- var formatSlowSignalsWarning = (params) => [
6516
- "<b>Slow yarn signals run</b>",
6517
- `Duration: <b>${formatDuration2(params.durationMs)}</b>`,
6518
- `Threshold: <b>${formatDuration2(SLOW_SIGNALS_WARNING_MS)}</b>`,
6519
- `Status: <b>${params.status}</b>`,
6520
- `Found signals: <b>${params.found}</b>`
6521
- ].join("\n");
6522
- var resolveSignalsConnectorName = async (value) => {
6523
- const connectorName = await (0, import_connectors6.resolveConnectorName)(value, projectRoot);
6524
- if (connectorName) {
6525
- return connectorName;
6526
- }
6527
- import_logger4.logger.warn(
6528
- 'Unknown connector "%s". Fallback to %s.',
6529
- String(value || "").trim() || String(value),
6530
- import_connectors6.DEFAULT_CONNECTOR_NAME
6531
- );
6532
- return import_connectors6.DEFAULT_CONNECTOR_NAME;
6533
- };
6534
- var createSignalsSession = async (lifecycle, scope = {}) => {
6535
- const deployment = flags.deployment ? await (0, import_tradingAccounts2.getRuntimeDeployment)(flags.user, String(flags.deployment)) : null;
6536
- if (flags.deployment && !deployment) {
6537
- throw new Error(`Runtime deployment not found: ${flags.deployment}`);
6538
- }
6539
- if (deployment && !deployment.enabled) {
6540
- throw new Error(`Runtime deployment is disabled: ${deployment.id}`);
6541
- }
6542
- const requestedRuntimeInterval = scope.interval ?? interval;
6543
- const runtimeInterval = deployment?.interval ?? requestedRuntimeInterval;
6544
- const runtimeIntervalMs = Number(runtimeInterval) * 6e4;
6545
- if (!Number.isFinite(runtimeIntervalMs) || runtimeIntervalMs <= 0) {
6546
- throw new Error(`Invalid runtime timeframe: ${runtimeInterval}`);
6547
- }
6548
- if (deployment && String(deployment.interval) !== String(requestedRuntimeInterval)) {
6549
- throw new Error(
6550
- `Deployment ${deployment.id} requires timeframe ${deployment.interval}; received ${requestedRuntimeInterval}`
6551
- );
6552
- }
6553
- const connectorName = await resolveSignalsConnectorName(
6554
- deployment?.connectorName ?? scope.connectorName ?? flags.connector
6555
- );
6556
- const universe = deployment?.universe ?? scope.universe ?? flags.universe;
6557
- const requestedAccountId = deployment?.accountId ?? scope.accountId ?? flags.account;
6558
- const connectorFactory = await (0, import_connectors6.getConnectorCreatorByName)(
6559
- connectorName,
6560
- projectRoot
6561
- );
6562
- if (!connectorFactory) {
6563
- throw new Error(`Connector "${connectorName}" is not registered`);
6564
- }
6565
- const marketConnector = await connectorFactory({
6566
- userName: flags.user,
6567
- universe,
6568
- accountId: requestedAccountId,
6569
- deploymentId: deployment?.id
6570
- });
6571
- const btcReferences = await loadBtcReferenceConnectors({
6572
- connectorName,
6573
- marketConnector,
6574
- userName: flags.user,
6575
- projectRoot,
6576
- shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors6.DEFAULT_CONNECTOR_NAME.toLowerCase(),
6577
- warn: (message) => import_logger4.logger.warn(message)
6578
- });
6579
- return {
4788
+
4789
+ // src/lib/signals/tickerEvaluator.ts
4790
+ var createSignalsTickerEvaluator = ({
4791
+ userName,
4792
+ makeOrders,
4793
+ projectRoot,
4794
+ context
4795
+ }) => async (symbol, instrument) => {
4796
+ const {
6580
4797
  connectorName,
4798
+ connector,
4799
+ btcBinanceData,
4800
+ btcCoinbaseData,
4801
+ primaryBtcClosedData,
4802
+ primaryEthClosedData,
4803
+ primaryEthByTimestamp,
4804
+ runtimeStrategies,
4805
+ strategyStats,
4806
+ runtimeCloseNotifications,
4807
+ lifecycle,
4808
+ preloadStart,
4809
+ currentTimestamp,
4810
+ persistStrategyState,
6581
4811
  universe,
6582
- accountId: marketConnector.accountId ?? requestedAccountId,
6583
- interval: runtimeInterval,
6584
- intervalMs: runtimeIntervalMs,
6585
- deployment,
6586
- startedAt: Date.now(),
6587
- marketConnector,
6588
- btcReferences,
6589
- lifecycle
6590
- };
6591
- };
6592
- var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCoinbaseData, primaryBtcClosedData, primaryEthClosedData, primaryEthByTimestamp, runtimeStrategies, strategyStats, runtimeCloseNotifications, lifecycle, preloadStart, currentTimestamp, persistStrategyState, universe, interval2, intervalMs2, accountId, deploymentId, instrument, runtimeScopeUniverse, saveRuntimeSignalEvaluation, saveRuntimeSignal) => {
6593
- const strategySignals = [];
6594
- const loadCached = (cachedSymbol) => connector.kline({
6595
- symbol: cachedSymbol,
4812
+ interval,
4813
+ intervalMs,
4814
+ accountId,
4815
+ deploymentId,
4816
+ runtimeScopeUniverse,
4817
+ saveRuntimeSignalEvaluation,
4818
+ saveRuntimeSignal
4819
+ } = context;
4820
+ const cachedData = universe === "crypto" && symbol === "BTCUSDT" ? primaryBtcClosedData : universe === "crypto" && symbol === "ETHUSDT" ? primaryEthClosedData : await connector.kline({
4821
+ symbol,
6596
4822
  start: preloadStart,
6597
4823
  end: currentTimestamp,
6598
4824
  cacheOnly: true,
6599
- interval: interval2
4825
+ interval
6600
4826
  });
6601
- const cachedData = universe === "crypto" && symbol === "BTCUSDT" ? primaryBtcClosedData : universe === "crypto" && symbol === "ETHUSDT" ? primaryEthClosedData : await loadCached(symbol);
6602
4827
  const closedData = getClosedCandlesForInterval(
6603
4828
  cachedData,
6604
4829
  currentTimestamp,
6605
- intervalMs2
6606
- );
6607
- const closedBtcData = primaryBtcClosedData;
6608
- const closedEthData = primaryEthClosedData;
6609
- const { alignedCoinCandles, alignedBtcCandles } = universe === "crypto" ? alignSymbolWithBtcReference(closedData, closedBtcData) : { alignedCoinCandles: closedData, alignedBtcCandles: closedData };
6610
- const alignedEthCandles = alignedCoinCandles.map((candle) => primaryEthByTimestamp.get(candle.timestamp)).filter(
6611
- (candle) => Boolean(candle)
4830
+ intervalMs
6612
4831
  );
4832
+ const { alignedCoinCandles, alignedBtcCandles } = universe === "crypto" ? alignSymbolWithBtcReference(closedData, primaryBtcClosedData) : { alignedCoinCandles: closedData, alignedBtcCandles: closedData };
4833
+ const alignedEthCandles = alignedCoinCandles.map((candle) => primaryEthByTimestamp.get(candle.timestamp)).filter((candle) => Boolean(candle));
6613
4834
  const lastCandle = alignedCoinCandles.at(-1);
6614
4835
  const btcLastCandle = alignedBtcCandles.at(-1);
6615
- const ethLastCandle = lastCandle == null ? void 0 : primaryEthByTimestamp.get(lastCandle.timestamp);
6616
- if (!lastCandle || !btcLastCandle) {
6617
- return strategySignals;
6618
- }
4836
+ const ethLastCandle = lastCandle ? primaryEthByTimestamp.get(lastCandle.timestamp) : void 0;
4837
+ if (!lastCandle || !btcLastCandle) return [];
6619
4838
  const previousData = alignedCoinCandles.slice(0, -1);
6620
4839
  const previousBtcData = alignedBtcCandles.slice(0, -1);
6621
4840
  const previousEthData = alignedEthCandles.filter(
6622
4841
  (candle) => candle.timestamp < lastCandle.timestamp
6623
4842
  );
4843
+ const strategySignals = [];
6624
4844
  for (const runtimeStrategy of runtimeStrategies) {
6625
4845
  const {
6626
4846
  strategyName,
@@ -6630,23 +4850,20 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6630
4850
  strategyConfig,
6631
4851
  strategyResults
6632
4852
  } = runtimeStrategy;
4853
+ const symbolResultConfig = strategyResults?.[symbol]?.config ?? null;
6633
4854
  const runtimeConfig = buildRuntimeModeStrategyConfig({
6634
4855
  strategyConfig,
6635
4856
  env: "CRON",
6636
- interval: interval2,
6637
- makeOrders: flags.makeOrders
4857
+ interval,
4858
+ makeOrders
6638
4859
  });
6639
4860
  const runtimeLineage = await buildRuntimeLineage({
6640
4861
  projectRoot,
6641
4862
  strategyName,
6642
- config: {
6643
- configId,
6644
- strategyConfig,
6645
- symbolResultConfig: strategyResults?.[symbol]?.config ?? null
6646
- },
4863
+ config: { configId, strategyConfig, symbolResultConfig },
6647
4864
  runContext: {
6648
4865
  connectorName: connectorName.toLowerCase(),
6649
- interval: String(interval2),
4866
+ interval: String(interval),
6650
4867
  universe
6651
4868
  }
6652
4869
  });
@@ -6656,40 +4873,36 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6656
4873
  accountId,
6657
4874
  deploymentId,
6658
4875
  symbol,
6659
- interval: interval2,
4876
+ interval,
6660
4877
  strategyName,
6661
4878
  configId
6662
4879
  });
6663
4880
  const stats = strategyStats.get(strategyName);
6664
- const initialDataLength = previousData.length;
6665
- const initialBtcDataLength = previousBtcData.length;
6666
- const initialEthDataLength = previousEthData.length;
4881
+ const initialLengths = [
4882
+ previousData.length,
4883
+ previousBtcData.length,
4884
+ previousEthData.length
4885
+ ];
6667
4886
  let evaluation;
6668
4887
  try {
6669
4888
  evaluation = await lifecycle.evaluate({
6670
4889
  key: lifecycleKey,
6671
4890
  timestamp: lastCandle.timestamp,
6672
- config: {
6673
- runtimeConfig,
6674
- sourceStrategyConfig,
6675
- symbolResultConfig: strategyResults?.[symbol]?.config ?? null
6676
- },
4891
+ config: { runtimeConfig, sourceStrategyConfig, symbolResultConfig },
6677
4892
  btcBinanceData,
6678
4893
  btcCoinbaseData,
6679
- onRuntimeClose: (event) => {
6680
- runtimeCloseNotifications.push(event);
6681
- },
6682
- create: async ({
4894
+ onRuntimeClose: (event) => runtimeCloseNotifications.push(event),
4895
+ create: ({
6683
4896
  btcBinanceData: lifecycleBtcBinanceData,
6684
4897
  btcCoinbaseData: lifecycleBtcCoinbaseData,
6685
4898
  onRuntimeClose
6686
4899
  }) => strategyCreator({
6687
- userName: flags.user,
4900
+ userName,
6688
4901
  connectorName,
6689
4902
  runtimeConfigId: configId,
6690
4903
  runtimeConfigSnapshot: {
6691
4904
  userConfig: sourceStrategyConfig,
6692
- symbolResultConfig: strategyResults?.[symbol]?.config ?? null
4905
+ symbolResultConfig
6693
4906
  },
6694
4907
  connector,
6695
4908
  symbol,
@@ -6712,9 +4925,9 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6712
4925
  run: (strategy) => strategy(lastCandle, btcLastCandle, ethLastCandle)
6713
4926
  });
6714
4927
  } finally {
6715
- previousData.length = initialDataLength;
6716
- previousBtcData.length = initialBtcDataLength;
6717
- previousEthData.length = initialEthDataLength;
4928
+ previousData.length = initialLengths[0];
4929
+ previousBtcData.length = initialLengths[1];
4930
+ previousEthData.length = initialLengths[2];
6718
4931
  }
6719
4932
  if (evaluation.action === "duplicate" || evaluation.action === "stale") {
6720
4933
  continue;
@@ -6727,9 +4940,7 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6727
4940
  symbol
6728
4941
  );
6729
4942
  }
6730
- if (stats) {
6731
- stats.evaluated += 1;
6732
- }
4943
+ if (stats) stats.evaluated += 1;
6733
4944
  const signal = evaluation.result;
6734
4945
  if (!signal || typeof signal === "string") {
6735
4946
  const reason = typeof signal === "string" && signal.trim() ? signal : "NO_SIGNAL";
@@ -6743,12 +4954,12 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6743
4954
  timestamp: lastCandle.timestamp,
6744
4955
  runtimeConfigId: configId
6745
4956
  }),
6746
- userName: flags.user,
4957
+ userName,
6747
4958
  strategy: strategyName,
6748
4959
  runtimeConfigId: configId,
6749
4960
  runtimeLineage,
6750
4961
  symbol,
6751
- interval: interval2,
4962
+ interval,
6752
4963
  universe,
6753
4964
  assetClass: instrument?.assetClass,
6754
4965
  accountId,
@@ -6761,18 +4972,13 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6761
4972
  });
6762
4973
  continue;
6763
4974
  }
6764
- if (stats) {
6765
- stats.signals += 1;
6766
- }
4975
+ if (stats) stats.signals += 1;
6767
4976
  signal.runtimeConfigId = configId;
6768
4977
  signal.runtimeLineage = runtimeLineage;
6769
4978
  if (configId && configId !== "config" && !signal.signalId.endsWith(`:${configId}`)) {
6770
4979
  signal.signalId = `${signal.signalId}:${configId}`;
6771
4980
  }
6772
- await (0, import_strategies6.enrichSignalWithBinanceMarketContext)({
6773
- signal,
6774
- env: "CRON"
6775
- });
4981
+ await (0, import_strategies5.enrichSignalWithBinanceMarketContext)({ signal, env: "CRON" });
6776
4982
  if (signal.orderStatus === "skipped" && typeof signal.orderSkipReason === "string" && signal.orderSkipReason.trim()) {
6777
4983
  recordStrategyReason(
6778
4984
  strategyStats,
@@ -6782,7 +4988,7 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6782
4988
  );
6783
4989
  }
6784
4990
  strategySignals.push(signal);
6785
- saveRuntimeSignal?.(flags.user, signal);
4991
+ saveRuntimeSignal?.(userName, signal);
6786
4992
  await saveRuntimeSignalEvaluation?.({
6787
4993
  evaluationId: buildRuntimeSignalEvaluationId({
6788
4994
  strategyName,
@@ -6790,12 +4996,12 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6790
4996
  timestamp: lastCandle.timestamp,
6791
4997
  runtimeConfigId: configId
6792
4998
  }),
6793
- userName: flags.user,
4999
+ userName,
6794
5000
  strategy: strategyName,
6795
5001
  runtimeConfigId: configId,
6796
5002
  runtimeLineage,
6797
5003
  symbol,
6798
- interval: interval2,
5004
+ interval,
6799
5005
  universe,
6800
5006
  assetClass: instrument?.assetClass,
6801
5007
  accountId,
@@ -6816,259 +5022,383 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6816
5022
  }
6817
5023
  return strategySignals;
6818
5024
  };
6819
- var signals = async (options = {}) => {
6820
- const startedAt = Date.now();
6821
- const signals2 = new Array();
6822
- const runtimeCloseNotifications = new Array();
6823
- let status = "completed";
6824
- let failureMessage;
6825
- let activeSession;
6826
- let projectHooks;
6827
- let afterSignalsHookContext = null;
6828
- const runtimeSignalEvaluations = createRuntimeSignalEvaluationBuffer();
6829
- try {
6830
- const session = options.session ?? await createSignalsSession(createDefaultSignalsLifecycle());
6831
- activeSession = session;
6832
- const persistStrategyState = options.session != null;
6833
- const {
5025
+
5026
+ // src/lib/signals/runner.ts
5027
+ var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
5028
+ var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
5029
+ var resolvePositiveInteger = (value, fallback) => {
5030
+ const parsed = Number(value);
5031
+ if (!Number.isFinite(parsed)) {
5032
+ return fallback;
5033
+ }
5034
+ const normalized = Math.floor(parsed);
5035
+ return normalized > 0 ? normalized : fallback;
5036
+ };
5037
+ var resolveNonNegativeInteger = (value, fallback) => {
5038
+ const parsed = Number(value);
5039
+ if (!Number.isFinite(parsed)) {
5040
+ return fallback;
5041
+ }
5042
+ return Math.max(0, Math.floor(parsed));
5043
+ };
5044
+ var createSignalsRunner = (config2) => {
5045
+ const interval = config2.interval;
5046
+ const projectRoot = config2.projectRoot?.trim() || String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
5047
+ const resolveSignalsDaemonMaxLiveBars = (runtimeInterval = interval) => {
5048
+ const intervalMinutes = Number(runtimeInterval);
5049
+ const preloadBars = Math.ceil(
5050
+ import_constants3.SIGNALS_CLI_PRELOAD_DAYS * 24 * 60 / intervalMinutes
5051
+ );
5052
+ return resolvePositiveInteger(
5053
+ process.env.SIGNALS_DAEMON_MAX_LIVE_BARS,
5054
+ preloadBars
5055
+ );
5056
+ };
5057
+ const isSignalsKlineWsEnabled = () => !["0", "false", "off", "no"].includes(
5058
+ String(process.env.SIGNALS_KLINE_WS_ENABLED ?? "true").trim().toLowerCase()
5059
+ );
5060
+ const resolveSignalsKlineWsWaitMs = () => resolveNonNegativeInteger(process.env.SIGNALS_KLINE_WS_WAIT_MS, 1e4);
5061
+ const createDefaultSignalsLifecycle = (runtimeInterval = interval) => createSignalsStrategyLifecycle({
5062
+ intervalMs: Number(runtimeInterval) * 6e4,
5063
+ maxLiveBars: resolveSignalsDaemonMaxLiveBars(runtimeInterval),
5064
+ releaseState: import_strategies6.releaseStrategyReplayCache
5065
+ });
5066
+ const timeOperation2 = (label, operation) => timeOperation(
5067
+ label,
5068
+ operation,
5069
+ (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5070
+ );
5071
+ const formatSlowSignalsWarning = (params) => [
5072
+ "<b>Slow yarn signals run</b>",
5073
+ `Duration: <b>${formatDuration2(params.durationMs)}</b>`,
5074
+ `Threshold: <b>${formatDuration2(SLOW_SIGNALS_WARNING_MS)}</b>`,
5075
+ `Status: <b>${params.status}</b>`,
5076
+ `Found signals: <b>${params.found}</b>`
5077
+ ].join("\n");
5078
+ const resolveSignalsConnectorName = async (value) => {
5079
+ const connectorName = await (0, import_connectors6.resolveConnectorName)(value, projectRoot);
5080
+ if (connectorName) {
5081
+ return connectorName;
5082
+ }
5083
+ import_logger5.logger.warn(
5084
+ 'Unknown connector "%s". Fallback to %s.',
5085
+ String(value || "").trim() || String(value),
5086
+ import_connectors6.DEFAULT_CONNECTOR_NAME
5087
+ );
5088
+ return import_connectors6.DEFAULT_CONNECTOR_NAME;
5089
+ };
5090
+ const createSignalsSession2 = async (lifecycle, scope = {}) => {
5091
+ const deployment = config2.deploymentId ? await (0, import_runtimeDeployments.getRuntimeDeployment)(config2.userName, config2.deploymentId) : null;
5092
+ if (config2.deploymentId && !deployment) {
5093
+ throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
5094
+ }
5095
+ if (deployment && !deployment.enabled) {
5096
+ throw new Error(`Runtime deployment is disabled: ${deployment.id}`);
5097
+ }
5098
+ const requestedRuntimeInterval = scope.interval ?? interval;
5099
+ const runtimeInterval = deployment?.interval ?? requestedRuntimeInterval;
5100
+ const runtimeIntervalMs = Number(runtimeInterval) * 6e4;
5101
+ if (!Number.isFinite(runtimeIntervalMs) || runtimeIntervalMs <= 0) {
5102
+ throw new Error(`Invalid runtime timeframe: ${runtimeInterval}`);
5103
+ }
5104
+ if (deployment && String(deployment.interval) !== String(requestedRuntimeInterval)) {
5105
+ throw new Error(
5106
+ `Deployment ${deployment.id} requires timeframe ${deployment.interval}; received ${requestedRuntimeInterval}`
5107
+ );
5108
+ }
5109
+ const connectorName = await resolveSignalsConnectorName(
5110
+ deployment?.connectorName ?? scope.connectorName ?? config2.connectorName
5111
+ );
5112
+ const universe = deployment?.universe ?? scope.universe ?? config2.universe;
5113
+ const requestedAccountId = deployment?.accountId ?? scope.accountId ?? config2.accountId;
5114
+ const connectorFactory = await (0, import_connectors6.getConnectorCreatorByName)(
6834
5115
  connectorName,
6835
- universe: sessionUniverse,
6836
- accountId,
5116
+ projectRoot
5117
+ );
5118
+ if (!connectorFactory) {
5119
+ throw new Error(`Connector "${connectorName}" is not registered`);
5120
+ }
5121
+ const marketConnector = await connectorFactory({
5122
+ userName: config2.userName,
5123
+ universe,
5124
+ accountId: requestedAccountId,
5125
+ deploymentId: deployment?.id
5126
+ });
5127
+ const btcReferences = await loadBtcReferenceConnectors({
5128
+ connectorName,
5129
+ marketConnector,
5130
+ userName: config2.userName,
5131
+ projectRoot,
5132
+ shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors6.DEFAULT_CONNECTOR_NAME.toLowerCase(),
5133
+ warn: (message) => import_logger5.logger.warn(message)
5134
+ });
5135
+ return {
5136
+ connectorName,
5137
+ universe,
5138
+ accountId: marketConnector.accountId ?? requestedAccountId,
5139
+ interval: runtimeInterval,
5140
+ intervalMs: runtimeIntervalMs,
6837
5141
  deployment,
5142
+ startedAt: Date.now(),
6838
5143
  marketConnector,
6839
5144
  btcReferences,
6840
- lifecycle,
6841
- interval: interval2,
6842
- intervalMs: intervalMs2
6843
- } = session;
6844
- const universe = sessionUniverse ?? marketConnector.universe ?? "crypto";
6845
- const tickers = await timeOperation2("tickers load", () => {
6846
- const baseArgs = [
5145
+ lifecycle
5146
+ };
5147
+ };
5148
+ const signals2 = async (options = {}) => {
5149
+ const startedAt = Date.now();
5150
+ const signals3 = new Array();
5151
+ const runtimeCloseNotifications = new Array();
5152
+ let status = "completed";
5153
+ let failureMessage;
5154
+ let activeSession;
5155
+ let projectHooks;
5156
+ let afterSignalsHookContext = null;
5157
+ const runtimeSignalEvaluations = createRuntimeSignalEvaluationBuffer();
5158
+ try {
5159
+ const session = options.session ?? await createSignalsSession2(createDefaultSignalsLifecycle());
5160
+ activeSession = session;
5161
+ const persistStrategyState = options.session != null;
5162
+ const {
5163
+ connectorName,
5164
+ universe: sessionUniverse,
5165
+ accountId,
5166
+ deployment,
6847
5167
  marketConnector,
6848
- flags.tickers || deployment?.tickers?.join(","),
6849
- flags.exclude,
6850
- flags.tickersLimit,
6851
- flags.chunk
6852
- ];
6853
- return sessionUniverse || accountId || deployment ? (0, import_cli2.getTickers)(...baseArgs, {
5168
+ btcReferences,
5169
+ lifecycle,
5170
+ interval: interval2,
5171
+ intervalMs
5172
+ } = session;
5173
+ const universe = sessionUniverse ?? marketConnector.universe ?? "crypto";
5174
+ const tickers = await timeOperation2("tickers load", () => {
5175
+ const baseArgs = [
5176
+ marketConnector,
5177
+ config2.tickers || deployment?.tickers?.join(","),
5178
+ config2.exclude,
5179
+ config2.tickersLimit,
5180
+ config2.chunk
5181
+ ];
5182
+ return sessionUniverse || accountId || deployment ? (0, import_cli2.getTickers)(...baseArgs, {
5183
+ universe,
5184
+ assetClasses: deployment?.assetClasses
5185
+ }) : (0, import_cli2.getTickers)(...baseArgs);
5186
+ });
5187
+ if (universe === "tradfi" && typeof marketConnector.listInstruments !== "function") {
5188
+ throw new Error("TradFi connector must implement listInstruments");
5189
+ }
5190
+ const instruments = typeof marketConnector.listInstruments === "function" ? await marketConnector.listInstruments({
5191
+ universe,
5192
+ assetClasses: deployment?.assetClasses,
5193
+ symbols: tickers
5194
+ }) : [];
5195
+ const instrumentsBySymbol = new Map(
5196
+ instruments.map((instrument) => [instrument.symbol, instrument])
5197
+ );
5198
+ if (config2.showTickersList) {
5199
+ console.log(import_chalk7.default.gray(JSON.stringify(tickers.sort(), null, 2)));
5200
+ return;
5201
+ }
5202
+ const projectConfig = await (0, import_cli2.loadTradejsConfig)(projectRoot);
5203
+ projectHooks = projectConfig.hooks;
5204
+ const currentTimestamp = (0, import_time3.getTimestamp)();
5205
+ const preloadStart = (0, import_time3.getTimestamp)(import_constants3.SIGNALS_CLI_PRELOAD_DAYS);
5206
+ if (!config2.cacheOnly && session.klineFeed) {
5207
+ const expectedSymbols = universe === "crypto" ? [.../* @__PURE__ */ new Set([...tickers, "BTCUSDT", "ETHUSDT"])] : tickers;
5208
+ session.klineFeed.setSubscriptions(expectedSymbols);
5209
+ const targetTimestamp = Math.floor(currentTimestamp / intervalMs) * intervalMs - intervalMs;
5210
+ const missingSymbols = await timeOperation2(
5211
+ "websocket candle readiness",
5212
+ () => session.klineFeed.waitForClosed({
5213
+ symbols: expectedSymbols,
5214
+ timestamp: targetTimestamp,
5215
+ timeoutMs: resolveSignalsKlineWsWaitMs()
5216
+ })
5217
+ );
5218
+ await session.klineFeed.flush();
5219
+ import_logger5.logger.info(
5220
+ import_chalk7.default.gray(
5221
+ `websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
5222
+ )
5223
+ );
5224
+ await updatePrimaryMarketHistory({
5225
+ marketConnector,
5226
+ connectorName,
5227
+ interval: interval2,
5228
+ symbols: missingSymbols,
5229
+ preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
5230
+ universe,
5231
+ log: (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5232
+ });
5233
+ await updateBtcReferenceHistory({
5234
+ marketConnector,
5235
+ btcReferences,
5236
+ interval: interval2,
5237
+ preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
5238
+ universe,
5239
+ log: (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5240
+ });
5241
+ } else if (!config2.cacheOnly) {
5242
+ await updateMarketHistoryWithBtcReferences({
5243
+ marketConnector,
5244
+ connectorName,
5245
+ btcReferences,
5246
+ interval: interval2,
5247
+ symbols: tickers,
5248
+ preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
5249
+ universe,
5250
+ log: (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5251
+ });
5252
+ }
5253
+ await prepareMarketContextForRun({
5254
+ mode: "signals",
5255
+ userName: config2.userName,
5256
+ projectRoot,
5257
+ symbols: tickers,
6854
5258
  universe,
6855
- assetClasses: deployment?.assetClasses
6856
- }) : (0, import_cli2.getTickers)(...baseArgs);
6857
- });
6858
- if (universe === "tradfi" && typeof marketConnector.listInstruments !== "function") {
6859
- throw new Error("TradFi connector must implement listInstruments");
6860
- }
6861
- const instruments = typeof marketConnector.listInstruments === "function" ? await marketConnector.listInstruments({
6862
- universe,
6863
- assetClasses: deployment?.assetClasses,
6864
- symbols: tickers
6865
- }) : [];
6866
- const instrumentsBySymbol = new Map(
6867
- instruments.map((instrument) => [instrument.symbol, instrument])
6868
- );
6869
- if (flags.showTickersList) {
6870
- console.log(import_chalk7.default.gray(JSON.stringify(tickers.sort(), null, 2)));
6871
- return;
6872
- }
6873
- const projectConfig = await (0, import_cli2.loadTradejsConfig)(projectRoot);
6874
- projectHooks = projectConfig.hooks;
6875
- const currentTimestamp = (0, import_time3.getTimestamp)();
6876
- const preloadStart = (0, import_time3.getTimestamp)(import_constants3.SIGNALS_CLI_PRELOAD_DAYS);
6877
- if (!flags.cacheOnly && session.klineFeed) {
6878
- const expectedSymbols = universe === "crypto" ? [.../* @__PURE__ */ new Set([...tickers, "BTCUSDT", "ETHUSDT"])] : tickers;
6879
- session.klineFeed.setSubscriptions(expectedSymbols);
6880
- const targetTimestamp = Math.floor(currentTimestamp / intervalMs2) * intervalMs2 - intervalMs2;
6881
- const missingSymbols = await timeOperation2(
6882
- "websocket candle readiness",
6883
- () => session.klineFeed.waitForClosed({
6884
- symbols: expectedSymbols,
6885
- timestamp: targetTimestamp,
6886
- timeoutMs: resolveSignalsKlineWsWaitMs()
6887
- })
5259
+ interval: interval2,
5260
+ startMs: currentTimestamp,
5261
+ endMs: currentTimestamp,
5262
+ preloadStartMs: preloadStart,
5263
+ cacheOnly: config2.cacheOnly,
5264
+ log: (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5265
+ });
5266
+ if (config2.updateOnly) {
5267
+ return;
5268
+ }
5269
+ const [
5270
+ btcBinanceData,
5271
+ btcCoinbaseData,
5272
+ primaryBtcCachedData,
5273
+ primaryEthCachedData
5274
+ ] = universe === "crypto" ? await timeOperation2(
5275
+ "reference candles load",
5276
+ () => Promise.all([
5277
+ btcReferences.binance.kline({
5278
+ symbol: "BTCUSDT",
5279
+ start: preloadStart,
5280
+ end: currentTimestamp,
5281
+ cacheOnly: true,
5282
+ interval: interval2
5283
+ }),
5284
+ btcReferences.coinbase.kline({
5285
+ symbol: "BTCUSDT",
5286
+ start: preloadStart,
5287
+ end: currentTimestamp,
5288
+ cacheOnly: true,
5289
+ interval: interval2
5290
+ }),
5291
+ marketConnector.kline({
5292
+ symbol: "BTCUSDT",
5293
+ start: preloadStart,
5294
+ end: currentTimestamp,
5295
+ cacheOnly: true,
5296
+ interval: interval2
5297
+ }),
5298
+ marketConnector.kline({
5299
+ symbol: "ETHUSDT",
5300
+ start: preloadStart,
5301
+ end: currentTimestamp,
5302
+ cacheOnly: true,
5303
+ interval: interval2
5304
+ })
5305
+ ])
5306
+ ) : [[], [], [], []];
5307
+ const primaryBtcClosedData = getClosedCandlesForInterval(
5308
+ primaryBtcCachedData,
5309
+ currentTimestamp,
5310
+ intervalMs
6888
5311
  );
6889
- await session.klineFeed.flush();
6890
- import_logger4.logger.info(
6891
- import_chalk7.default.gray(
6892
- `websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
6893
- )
5312
+ const primaryEthClosedData = getClosedCandlesForInterval(
5313
+ primaryEthCachedData,
5314
+ currentTimestamp,
5315
+ intervalMs
6894
5316
  );
6895
- await updatePrimaryMarketHistory({
6896
- marketConnector,
5317
+ const primaryEthByTimestamp = new Map(
5318
+ primaryEthClosedData.map((candle) => [candle.timestamp, candle])
5319
+ );
5320
+ const runtimeStrategies = await loadRuntimeStrategies({
5321
+ userName: config2.userName,
5322
+ projectRoot,
5323
+ deployment,
6897
5324
  connectorName,
6898
- interval: interval2,
6899
- symbols: missingSymbols,
6900
- preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
6901
- universe,
6902
- log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
6903
- });
6904
- await updateBtcReferenceHistory({
6905
- marketConnector,
6906
- btcReferences,
6907
- interval: interval2,
6908
- preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
6909
5325
  universe,
6910
- log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
5326
+ accountId,
5327
+ interval: interval2
6911
5328
  });
6912
- } else if (!flags.cacheOnly) {
6913
- await updateMarketHistoryWithBtcReferences({
6914
- marketConnector,
5329
+ if (!runtimeStrategies.length) {
5330
+ lifecycle.clear();
5331
+ import_logger5.logger.warn(
5332
+ "No strategy configs found by users:%s:strategies:*:config",
5333
+ config2.userName
5334
+ );
5335
+ return;
5336
+ }
5337
+ lifecycle.retain(
5338
+ new Set(
5339
+ tickers.flatMap(
5340
+ (symbol) => runtimeStrategies.map(
5341
+ ({ strategyName, configId }) => buildSignalsStrategyLifecycleKey({
5342
+ connectorName,
5343
+ universe: sessionUniverse,
5344
+ accountId,
5345
+ deploymentId: deployment?.id,
5346
+ symbol,
5347
+ interval: interval2,
5348
+ strategyName,
5349
+ configId
5350
+ })
5351
+ )
5352
+ )
5353
+ )
5354
+ );
5355
+ import_logger5.logger.info(
5356
+ import_chalk7.default.yellow(
5357
+ `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
5358
+ )
5359
+ );
5360
+ afterSignalsHookContext = {
5361
+ connector: marketConnector,
6915
5362
  connectorName,
6916
- btcReferences,
5363
+ userName: config2.userName,
6917
5364
  interval: interval2,
6918
- symbols: tickers,
6919
- preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
6920
- universe,
6921
- log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
6922
- });
6923
- }
6924
- await prepareMarketContextForRun({
6925
- mode: "signals",
6926
- userName: flags.user,
6927
- projectRoot,
6928
- symbols: tickers,
6929
- universe,
6930
- interval: interval2,
6931
- startMs: currentTimestamp,
6932
- endMs: currentTimestamp,
6933
- preloadStartMs: preloadStart,
6934
- cacheOnly: Boolean(flags.cacheOnly),
6935
- log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
6936
- });
6937
- if (flags.updateOnly) {
6938
- return;
6939
- }
6940
- const [
6941
- btcBinanceData,
6942
- btcCoinbaseData,
6943
- primaryBtcCachedData,
6944
- primaryEthCachedData
6945
- ] = universe === "crypto" ? await timeOperation2(
6946
- "reference candles load",
6947
- () => Promise.all([
6948
- btcReferences.binance.kline({
6949
- symbol: "BTCUSDT",
6950
- start: preloadStart,
6951
- end: currentTimestamp,
6952
- cacheOnly: true,
6953
- interval: interval2
6954
- }),
6955
- btcReferences.coinbase.kline({
6956
- symbol: "BTCUSDT",
6957
- start: preloadStart,
6958
- end: currentTimestamp,
6959
- cacheOnly: true,
6960
- interval: interval2
6961
- }),
6962
- marketConnector.kline({
6963
- symbol: "BTCUSDT",
6964
- start: preloadStart,
6965
- end: currentTimestamp,
6966
- cacheOnly: true,
6967
- interval: interval2
6968
- }),
6969
- marketConnector.kline({
6970
- symbol: "ETHUSDT",
6971
- start: preloadStart,
6972
- end: currentTimestamp,
6973
- cacheOnly: true,
6974
- interval: interval2
6975
- })
6976
- ])
6977
- ) : [[], [], [], []];
6978
- const primaryBtcClosedData = getClosedCandlesForInterval(
6979
- primaryBtcCachedData,
6980
- currentTimestamp,
6981
- intervalMs2
6982
- );
6983
- const primaryEthClosedData = getClosedCandlesForInterval(
6984
- primaryEthCachedData,
6985
- currentTimestamp,
6986
- intervalMs2
6987
- );
6988
- const primaryEthByTimestamp = new Map(
6989
- primaryEthClosedData.map((candle) => [candle.timestamp, candle])
6990
- );
6991
- const runtimeStrategies = await loadRuntimeStrategies({
6992
- userName: flags.user,
6993
- projectRoot,
6994
- deployment,
6995
- connectorName,
6996
- universe,
6997
- accountId,
6998
- interval: interval2
6999
- });
7000
- if (!runtimeStrategies.length) {
7001
- lifecycle.clear();
7002
- import_logger4.logger.warn(
7003
- "No strategy configs found by users:%s:strategies:*:config",
7004
- flags.user
7005
- );
7006
- return;
7007
- }
7008
- lifecycle.retain(
7009
- new Set(
7010
- tickers.flatMap(
7011
- (symbol) => runtimeStrategies.map(
7012
- ({ strategyName, configId }) => buildSignalsStrategyLifecycleKey({
7013
- connectorName,
7014
- universe: sessionUniverse,
7015
- accountId,
7016
- deploymentId: deployment?.id,
7017
- symbol,
7018
- interval: interval2,
7019
- strategyName,
7020
- configId
7021
- })
7022
- )
5365
+ tickers: [...tickers],
5366
+ runtimeStrategies: runtimeStrategies.map(
5367
+ ({ strategyName, strategyConfig }) => ({
5368
+ strategyName,
5369
+ strategyConfig
5370
+ })
7023
5371
  )
7024
- )
7025
- );
7026
- import_logger4.logger.info(
7027
- import_chalk7.default.yellow(
7028
- `loaded strategies (user=${flags.user}): ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
7029
- )
7030
- );
7031
- afterSignalsHookContext = {
7032
- connector: marketConnector,
7033
- connectorName,
7034
- userName: flags.user,
7035
- interval: interval2,
7036
- tickers: [...tickers],
7037
- runtimeStrategies: runtimeStrategies.map(
7038
- ({ strategyName, strategyConfig }) => ({
7039
- strategyName,
7040
- strategyConfig
7041
- })
7042
- )
7043
- };
7044
- const beforeSignalsResult = await invokeBeforeSignalsHooks(
7045
- projectHooks,
7046
- afterSignalsHookContext
7047
- );
7048
- if (beforeSignalsResult?.abort === true) {
7049
- import_logger4.logger.info(
7050
- "signals aborted before ticker evaluation: %s",
7051
- beforeSignalsResult.reason ?? "PROJECT_BEFORE_SIGNALS_ABORTED"
5372
+ };
5373
+ const beforeSignalsResult = await invokeBeforeSignalsHooks(
5374
+ projectHooks,
5375
+ afterSignalsHookContext
7052
5376
  );
7053
- return;
7054
- }
7055
- const strategyStats = createStrategySkipStats(runtimeStrategies);
7056
- const bar = new import_progress4.default(
7057
- ":current/:total [:bar][:percent] :found :eta(s) :symbol",
7058
- {
7059
- total: tickers.length,
7060
- width: 30
5377
+ if (beforeSignalsResult?.abort === true) {
5378
+ import_logger5.logger.info(
5379
+ "signals aborted before ticker evaluation: %s",
5380
+ beforeSignalsResult.reason ?? "PROJECT_BEFORE_SIGNALS_ABORTED"
5381
+ );
5382
+ return;
7061
5383
  }
7062
- );
7063
- import_logger4.logger.info(import_chalk7.default.yellow(`tickers: ${tickers.length}`));
7064
- const signalsParallel = resolvePositiveInteger(flags.parallel, 4);
7065
- import_logger4.logger.info(import_chalk7.default.yellow(`signal workers: ${signalsParallel}`));
7066
- await timeOperation2("strategy evaluation", async () => {
7067
- await (0, import_async3.runWithConcurrency)(tickers, signalsParallel, async (symbol) => {
7068
- const strategySignals = await findSignals(
7069
- symbol,
5384
+ const strategyStats = createStrategySkipStats(runtimeStrategies);
5385
+ const bar = new import_progress4.default(
5386
+ ":current/:total [:bar][:percent] :found :eta(s) :symbol",
5387
+ {
5388
+ total: tickers.length,
5389
+ width: 30
5390
+ }
5391
+ );
5392
+ import_logger5.logger.info(import_chalk7.default.yellow(`tickers: ${tickers.length}`));
5393
+ const signalsParallel = resolvePositiveInteger(config2.parallel, 4);
5394
+ import_logger5.logger.info(import_chalk7.default.yellow(`signal workers: ${signalsParallel}`));
5395
+ const evaluateTicker = createSignalsTickerEvaluator({
5396
+ userName: config2.userName,
5397
+ makeOrders: config2.makeOrders,
5398
+ projectRoot,
5399
+ context: {
7070
5400
  connectorName,
7071
- marketConnector,
5401
+ connector: marketConnector,
7072
5402
  btcBinanceData,
7073
5403
  btcCoinbaseData,
7074
5404
  primaryBtcClosedData,
@@ -7082,264 +5412,377 @@ var signals = async (options = {}) => {
7082
5412
  currentTimestamp,
7083
5413
  persistStrategyState,
7084
5414
  universe,
7085
- interval2,
7086
- intervalMs2,
5415
+ interval: interval2,
5416
+ intervalMs,
7087
5417
  accountId,
7088
- deployment?.id,
7089
- instrumentsBySymbol.get(symbol),
7090
- sessionUniverse,
7091
- runtimeSignalEvaluations.save,
7092
- runtimeSignalEvaluations.saveSignal
7093
- );
7094
- if (strategySignals.length > 0) {
7095
- signals2.push(...strategySignals);
5418
+ deploymentId: deployment?.id,
5419
+ runtimeScopeUniverse: sessionUniverse,
5420
+ saveRuntimeSignalEvaluation: runtimeSignalEvaluations.save,
5421
+ saveRuntimeSignal: runtimeSignalEvaluations.saveSignal
7096
5422
  }
7097
- bar.tick(1, {
7098
- found: import_chalk7.default.cyan(signals2.length),
7099
- symbol: import_chalk7.default.gray(symbol)
5423
+ });
5424
+ await timeOperation2("strategy evaluation", async () => {
5425
+ await (0, import_async3.runWithConcurrency)(tickers, signalsParallel, async (symbol) => {
5426
+ const strategySignals = await evaluateTicker(
5427
+ symbol,
5428
+ instrumentsBySymbol.get(symbol)
5429
+ );
5430
+ if (strategySignals.length > 0) {
5431
+ signals3.push(...strategySignals);
5432
+ }
5433
+ bar.tick(1, {
5434
+ found: import_chalk7.default.cyan(signals3.length),
5435
+ symbol: import_chalk7.default.gray(symbol)
5436
+ });
7100
5437
  });
7101
5438
  });
7102
- });
7103
- if (flags.notify) {
7104
- const telegramSignals = getTelegramDeliverableSignals(signals2);
7105
- if (!flags.skipScreenshots && telegramSignals.length > 0) {
7106
- await (0, import_cli2.makeScreenshots)(telegramSignals, interval2, flags.user);
5439
+ if (config2.notify) {
5440
+ const telegramSignals = getTelegramDeliverableSignals(signals3);
5441
+ if (!config2.skipScreenshots && telegramSignals.length > 0) {
5442
+ await (0, import_cli2.makeScreenshots)(telegramSignals, interval2, config2.userName);
5443
+ }
5444
+ await (0, import_cli2.sendToTG)(telegramSignals, interval2, config2.userName);
5445
+ await (0, import_cli2.sendRuntimeCloseNotificationsToTG)(
5446
+ runtimeCloseNotifications,
5447
+ config2.userName
5448
+ );
7107
5449
  }
7108
- await (0, import_cli2.sendToTG)(telegramSignals, interval2, flags.user);
7109
- await (0, import_cli2.sendRuntimeCloseNotificationsToTG)(
7110
- runtimeCloseNotifications,
7111
- flags.user
5450
+ import_logger5.logger.info(
5451
+ JSON.stringify(
5452
+ signals3.map((s) => s.symbol),
5453
+ null,
5454
+ 2
5455
+ )
7112
5456
  );
7113
- }
7114
- import_logger4.logger.info(
7115
- JSON.stringify(
7116
- signals2.map((s) => s.symbol),
7117
- null,
7118
- 2
7119
- )
7120
- );
7121
- if (flags.showSkipStats) {
7122
- logStrategySkipStats(runtimeStrategies, strategyStats);
7123
- }
7124
- } catch (error) {
7125
- status = "failed";
7126
- failureMessage = error?.message || String(error);
7127
- import_logger4.logger.error(
7128
- "signals failed: %s",
7129
- error?.message || String(error)
7130
- );
7131
- throw error;
7132
- } finally {
7133
- try {
7134
- await runtimeSignalEvaluations.flush();
5457
+ if (config2.showSkipStats) {
5458
+ logStrategySkipStats(runtimeStrategies, strategyStats);
5459
+ }
7135
5460
  } catch (error) {
7136
- import_logger4.logger.error(
7137
- "runtime signal evaluation flush failed: %s",
5461
+ status = "failed";
5462
+ failureMessage = error?.message || String(error);
5463
+ import_logger5.logger.error(
5464
+ "signals failed: %s",
7138
5465
  error?.message || String(error)
7139
5466
  );
7140
- }
7141
- const durationMs = Date.now() - startedAt;
7142
- if (activeSession?.deployment) {
7143
- await (0, import_tradingAccounts2.saveRuntimeDeploymentHeartbeat)(flags.user, {
7144
- deploymentId: activeSession.deployment.id,
7145
- status: getSignalsHeartbeatStatus({
7146
- cycleStatus: status,
7147
- continuous: options.session != null || Boolean(flags.watch)
7148
- }),
7149
- pid: process.pid,
7150
- startedAt: activeSession.startedAt,
7151
- lastCycleAt: Date.now(),
7152
- ...failureMessage ? { lastError: failureMessage } : {}
7153
- });
7154
- }
7155
- if (projectHooks && afterSignalsHookContext) {
5467
+ throw error;
5468
+ } finally {
7156
5469
  try {
7157
- await invokeAfterSignalsHooks(projectHooks, {
7158
- ...afterSignalsHookContext,
7159
- signals: [...signals2],
7160
- status,
7161
- durationMs
7162
- });
5470
+ await runtimeSignalEvaluations.flush();
7163
5471
  } catch (error) {
7164
- import_logger4.logger.error(
7165
- "afterSignals hook failed: %s",
5472
+ import_logger5.logger.error(
5473
+ "runtime signal evaluation flush failed: %s",
7166
5474
  error?.message || String(error)
7167
5475
  );
7168
5476
  }
7169
- }
7170
- if (flags.notify && durationMs > SLOW_SIGNALS_WARNING_MS) {
7171
- try {
7172
- await (0, import_cli2.sendTextToTG)(
7173
- formatSlowSignalsWarning({
7174
- durationMs,
7175
- status,
7176
- found: signals2.length
5477
+ const durationMs = Date.now() - startedAt;
5478
+ if (activeSession?.deployment) {
5479
+ await (0, import_runtimeDeployments.saveRuntimeDeploymentHeartbeat)(config2.userName, {
5480
+ deploymentId: activeSession.deployment.id,
5481
+ status: getSignalsHeartbeatStatus({
5482
+ cycleStatus: status,
5483
+ continuous: options.session != null || Boolean(config2.watch)
7177
5484
  }),
7178
- { userName: flags.user }
7179
- );
7180
- } catch (error) {
7181
- import_logger4.logger.error(
7182
- "slow signals warning failed: %s",
7183
- error?.message || String(error)
7184
- );
5485
+ pid: process.pid,
5486
+ startedAt: activeSession.startedAt,
5487
+ lastCycleAt: Date.now(),
5488
+ ...failureMessage ? { lastError: failureMessage } : {}
5489
+ });
5490
+ }
5491
+ if (projectHooks && afterSignalsHookContext) {
5492
+ try {
5493
+ await invokeAfterSignalsHooks(projectHooks, {
5494
+ ...afterSignalsHookContext,
5495
+ signals: [...signals3],
5496
+ status,
5497
+ durationMs
5498
+ });
5499
+ } catch (error) {
5500
+ import_logger5.logger.error(
5501
+ "afterSignals hook failed: %s",
5502
+ error?.message || String(error)
5503
+ );
5504
+ }
5505
+ }
5506
+ if (config2.notify && durationMs > SLOW_SIGNALS_WARNING_MS) {
5507
+ try {
5508
+ await (0, import_cli2.sendTextToTG)(
5509
+ formatSlowSignalsWarning({
5510
+ durationMs,
5511
+ status,
5512
+ found: signals3.length
5513
+ }),
5514
+ { userName: config2.userName }
5515
+ );
5516
+ } catch (error) {
5517
+ import_logger5.logger.error(
5518
+ "slow signals warning failed: %s",
5519
+ error?.message || String(error)
5520
+ );
5521
+ }
7185
5522
  }
5523
+ import_logger5.logger.info(
5524
+ import_chalk7.default.yellow(
5525
+ `signals ${status} in ${formatDuration2(durationMs)} (found=${signals3.length})`
5526
+ )
5527
+ );
5528
+ import_logger5.logger.info("");
5529
+ import_logger5.logger.info("");
5530
+ import_logger5.logger.info("");
7186
5531
  }
7187
- import_logger4.logger.info(
7188
- import_chalk7.default.yellow(
7189
- `signals ${status} in ${formatDuration2(durationMs)} (found=${signals2.length})`
7190
- )
7191
- );
7192
- import_logger4.logger.info("");
7193
- import_logger4.logger.info("");
7194
- import_logger4.logger.info("");
7195
- }
7196
- };
7197
- var loadConfiguredSignalsScopes = async (deployment) => {
7198
- const configuredStrategies = await loadRuntimeStrategies({
7199
- userName: flags.user,
7200
- projectRoot,
7201
- deployment,
7202
- connectorName: String(flags.connector)
7203
- });
7204
- const connectorName = await resolveSignalsConnectorName(
7205
- deployment?.connectorName ?? flags.connector
7206
- );
7207
- const scopes = /* @__PURE__ */ new Map();
7208
- for (const strategy of configuredStrategies) {
7209
- const key = [
7210
- connectorName,
7211
- strategy.universe,
7212
- strategy.accountId ?? "default",
7213
- strategy.interval
7214
- ].join(":");
7215
- scopes.set(key, {
7216
- connectorName,
7217
- universe: strategy.universe,
7218
- accountId: strategy.accountId,
7219
- interval: strategy.interval
5532
+ };
5533
+ const loadConfiguredSignalsScopes = async (deployment) => {
5534
+ const configuredStrategies = await loadRuntimeStrategies({
5535
+ userName: config2.userName,
5536
+ projectRoot,
5537
+ deployment,
5538
+ connectorName: config2.connectorName
7220
5539
  });
7221
- }
7222
- return scopes;
7223
- };
7224
- var signalsDaemon = async () => {
7225
- if (flags.updateOnly || flags.showTickersList) {
7226
- throw new Error(
7227
- "Signals daemon does not support updateOnly or showTickersList mode"
5540
+ const connectorName = await resolveSignalsConnectorName(
5541
+ deployment?.connectorName ?? config2.connectorName
7228
5542
  );
7229
- }
7230
- const abortController = new AbortController();
7231
- const daemonDeployment = flags.deployment ? await (0, import_tradingAccounts2.getRuntimeDeployment)(flags.user, String(flags.deployment)) : null;
7232
- if (flags.deployment && !daemonDeployment) {
7233
- throw new Error(`Runtime deployment not found: ${flags.deployment}`);
7234
- }
7235
- const sessions = /* @__PURE__ */ new Map();
7236
- const lastBoundaryByScope = /* @__PURE__ */ new Map();
7237
- const stop = (signalName) => {
7238
- import_logger4.logger.info("signals daemon stopping by %s", signalName);
7239
- abortController.abort();
5543
+ const scopes = /* @__PURE__ */ new Map();
5544
+ for (const strategy of configuredStrategies) {
5545
+ const key = [
5546
+ connectorName,
5547
+ strategy.universe,
5548
+ strategy.accountId ?? "default",
5549
+ strategy.interval
5550
+ ].join(":");
5551
+ scopes.set(key, {
5552
+ connectorName,
5553
+ universe: strategy.universe,
5554
+ accountId: strategy.accountId,
5555
+ interval: strategy.interval
5556
+ });
5557
+ }
5558
+ return scopes;
7240
5559
  };
7241
- const stopOnSigint = () => stop("SIGINT");
7242
- const stopOnSigterm = () => stop("SIGTERM");
7243
- process.once("SIGINT", stopOnSigint);
7244
- process.once("SIGTERM", stopOnSigterm);
7245
- import_logger4.logger.info(
7246
- "signals daemon started (config-driven scopes, fallback interval=%s)",
7247
- interval
7248
- );
7249
- try {
7250
- await runSignalsDaemon({
7251
- intervalMs: 6e4,
7252
- settleDelayMs: resolveNonNegativeInteger(flags.settleDelayMs, 5e3),
7253
- signal: abortController.signal,
7254
- runCycle: async () => {
7255
- const scopes = await loadConfiguredSignalsScopes(daemonDeployment);
7256
- for (const [key, staleSession] of sessions) {
7257
- if (scopes.has(key)) continue;
7258
- await staleSession.klineFeed?.close();
7259
- staleSession.lifecycle.clear();
7260
- sessions.delete(key);
7261
- lastBoundaryByScope.delete(key);
7262
- }
7263
- for (const [key, scope] of scopes) {
7264
- const scopeIntervalMs = Number(scope.interval) * 6e4;
7265
- const boundary = Math.floor(Date.now() / scopeIntervalMs) * scopeIntervalMs;
7266
- if (lastBoundaryByScope.get(key) === boundary) continue;
7267
- let session = sessions.get(key);
7268
- if (!session) {
7269
- session = await createSignalsSession(
7270
- createDefaultSignalsLifecycle(scope.interval),
7271
- scope
7272
- );
7273
- sessions.set(key, session);
7274
- }
7275
- if (!session.klineFeed && isSignalsKlineWsEnabled() && session.connectorName.toLowerCase() === "bybit") {
7276
- session.klineFeed = await createSignalsKlineFeed({
7277
- config: {
7278
- userName: flags.user,
7279
- universe: session.universe,
7280
- accountId: session.accountId,
7281
- deploymentId: session.deployment?.id
7282
- },
7283
- interval: session.interval,
7284
- universe: session.universe
7285
- });
7286
- import_logger4.logger.info(
7287
- "Bybit websocket candle feed enabled (account=%s, universe=%s, interval=%s)",
7288
- session.accountId ?? "default",
7289
- session.universe,
7290
- session.interval
7291
- );
7292
- }
7293
- try {
7294
- await signals({ session });
7295
- lastBoundaryByScope.set(key, boundary);
7296
- } catch (error) {
7297
- await session.klineFeed?.close();
7298
- session.lifecycle.clear();
5560
+ const hasExplicitSignalsScope = () => Boolean(config2.hasExplicitScope);
5561
+ const signalsConfiguredScopesOnce2 = async () => {
5562
+ if (config2.updateOnly || config2.showTickersList || config2.deploymentId || hasExplicitSignalsScope()) {
5563
+ return signals2();
5564
+ }
5565
+ const scopes = await loadConfiguredSignalsScopes();
5566
+ if (!scopes.size) return signals2();
5567
+ for (const scope of scopes.values()) {
5568
+ const session = await createSignalsSession2(
5569
+ createDefaultSignalsLifecycle(scope.interval),
5570
+ scope
5571
+ );
5572
+ try {
5573
+ await signals2({ session });
5574
+ } finally {
5575
+ await session.klineFeed?.close();
5576
+ session.lifecycle.clear();
5577
+ }
5578
+ }
5579
+ };
5580
+ const signalsDaemon2 = async () => {
5581
+ if (config2.updateOnly || config2.showTickersList) {
5582
+ throw new Error(
5583
+ "Signals daemon does not support updateOnly or showTickersList mode"
5584
+ );
5585
+ }
5586
+ const abortController = new AbortController();
5587
+ const daemonDeployment = config2.deploymentId ? await (0, import_runtimeDeployments.getRuntimeDeployment)(config2.userName, config2.deploymentId) : null;
5588
+ if (config2.deploymentId && !daemonDeployment) {
5589
+ throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
5590
+ }
5591
+ const sessions = /* @__PURE__ */ new Map();
5592
+ const lastBoundaryByScope = /* @__PURE__ */ new Map();
5593
+ const stop = (signalName) => {
5594
+ import_logger5.logger.info("signals daemon stopping by %s", signalName);
5595
+ abortController.abort();
5596
+ };
5597
+ const stopOnSigint = () => stop("SIGINT");
5598
+ const stopOnSigterm = () => stop("SIGTERM");
5599
+ process.once("SIGINT", stopOnSigint);
5600
+ process.once("SIGTERM", stopOnSigterm);
5601
+ import_logger5.logger.info(
5602
+ "signals daemon started (config-driven scopes, fallback interval=%s)",
5603
+ interval
5604
+ );
5605
+ try {
5606
+ await runSignalsDaemon({
5607
+ intervalMs: 6e4,
5608
+ settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
5609
+ signal: abortController.signal,
5610
+ runCycle: async () => {
5611
+ const scopes = await loadConfiguredSignalsScopes(daemonDeployment);
5612
+ for (const [key, staleSession] of sessions) {
5613
+ if (scopes.has(key)) continue;
5614
+ await staleSession.klineFeed?.close();
5615
+ staleSession.lifecycle.clear();
7299
5616
  sessions.delete(key);
7300
- throw error;
5617
+ lastBoundaryByScope.delete(key);
5618
+ }
5619
+ for (const [key, scope] of scopes) {
5620
+ const scopeIntervalMs = Number(scope.interval) * 6e4;
5621
+ const boundary = Math.floor(Date.now() / scopeIntervalMs) * scopeIntervalMs;
5622
+ if (lastBoundaryByScope.get(key) === boundary) continue;
5623
+ let session = sessions.get(key);
5624
+ if (!session) {
5625
+ session = await createSignalsSession2(
5626
+ createDefaultSignalsLifecycle(scope.interval),
5627
+ scope
5628
+ );
5629
+ sessions.set(key, session);
5630
+ }
5631
+ if (!session.klineFeed && isSignalsKlineWsEnabled() && session.connectorName.toLowerCase() === "bybit") {
5632
+ session.klineFeed = await createSignalsKlineFeed({
5633
+ config: {
5634
+ userName: config2.userName,
5635
+ universe: session.universe,
5636
+ accountId: session.accountId,
5637
+ deploymentId: session.deployment?.id
5638
+ },
5639
+ interval: session.interval,
5640
+ universe: session.universe
5641
+ });
5642
+ import_logger5.logger.info(
5643
+ "Bybit websocket candle feed enabled (account=%s, universe=%s, interval=%s)",
5644
+ session.accountId ?? "default",
5645
+ session.universe,
5646
+ session.interval
5647
+ );
5648
+ }
5649
+ try {
5650
+ await signals2({ session });
5651
+ lastBoundaryByScope.set(key, boundary);
5652
+ } catch (error) {
5653
+ await session.klineFeed?.close();
5654
+ session.lifecycle.clear();
5655
+ sessions.delete(key);
5656
+ throw error;
5657
+ }
7301
5658
  }
5659
+ const memory = process.memoryUsage();
5660
+ const stateKeys = [...sessions.values()].reduce(
5661
+ (sum, session) => sum + session.lifecycle.size(),
5662
+ 0
5663
+ );
5664
+ import_logger5.logger.info(
5665
+ "signals daemon resources: rss=%sMB heapUsed=%sMB heapTotal=%sMB stateKeys=%s scopes=%s",
5666
+ (memory.rss / 1024 / 1024).toFixed(1),
5667
+ (memory.heapUsed / 1024 / 1024).toFixed(1),
5668
+ (memory.heapTotal / 1024 / 1024).toFixed(1),
5669
+ stateKeys,
5670
+ sessions.size
5671
+ );
5672
+ },
5673
+ onCycleError: (error) => {
5674
+ import_logger5.logger.error(
5675
+ "signals daemon cycle failed: %s",
5676
+ error?.message || String(error)
5677
+ );
5678
+ }
5679
+ });
5680
+ } finally {
5681
+ process.removeListener("SIGINT", stopOnSigint);
5682
+ process.removeListener("SIGTERM", stopOnSigterm);
5683
+ for (const session of sessions.values()) {
5684
+ await session.klineFeed?.close();
5685
+ session.lifecycle.clear();
5686
+ if (session.deployment) {
5687
+ await (0, import_runtimeDeployments.saveRuntimeDeploymentHeartbeat)(config2.userName, {
5688
+ deploymentId: session.deployment.id,
5689
+ status: "stopped",
5690
+ pid: process.pid,
5691
+ startedAt: session.startedAt,
5692
+ lastCycleAt: Date.now()
5693
+ });
7302
5694
  }
7303
- const memory = process.memoryUsage();
7304
- const stateKeys = [...sessions.values()].reduce(
7305
- (sum, session) => sum + session.lifecycle.size(),
7306
- 0
7307
- );
7308
- import_logger4.logger.info(
7309
- "signals daemon resources: rss=%sMB heapUsed=%sMB heapTotal=%sMB stateKeys=%s scopes=%s",
7310
- (memory.rss / 1024 / 1024).toFixed(1),
7311
- (memory.heapUsed / 1024 / 1024).toFixed(1),
7312
- (memory.heapTotal / 1024 / 1024).toFixed(1),
7313
- stateKeys,
7314
- sessions.size
7315
- );
7316
- },
7317
- onCycleError: (error) => {
7318
- import_logger4.logger.error(
7319
- "signals daemon cycle failed: %s",
7320
- error?.message || String(error)
7321
- );
7322
- }
7323
- });
7324
- } finally {
7325
- process.removeListener("SIGINT", stopOnSigint);
7326
- process.removeListener("SIGTERM", stopOnSigterm);
7327
- for (const session of sessions.values()) {
7328
- await session.klineFeed?.close();
7329
- session.lifecycle.clear();
7330
- if (session.deployment) {
7331
- await (0, import_tradingAccounts2.saveRuntimeDeploymentHeartbeat)(flags.user, {
7332
- deploymentId: session.deployment.id,
7333
- status: "stopped",
7334
- pid: process.pid,
7335
- startedAt: session.startedAt,
7336
- lastCycleAt: Date.now()
7337
- });
7338
5695
  }
7339
5696
  }
7340
- }
5697
+ };
5698
+ return {
5699
+ createSession: createSignalsSession2,
5700
+ runCycle: signals2,
5701
+ runConfiguredScopesOnce: signalsConfiguredScopesOnce2,
5702
+ runDaemon: signalsDaemon2
5703
+ };
7341
5704
  };
7342
5705
 
5706
+ // src/scripts/signals.ts
5707
+ import_args.default.option(["t", "tickers"], "Selected tickers");
5708
+ import_args.default.option(["e", "exclude"], "Exclude tickers from tests");
5709
+ import_args.default.option(["l", "tickersLimit"], "Tickers limit");
5710
+ import_args.default.option(["f", "timeframe"], "Timeframe", 15);
5711
+ import_args.default.option(["m", "makeOrders"], "Make orders");
5712
+ import_args.default.option(["N", "notify"], "Send message in Telegram", false);
5713
+ import_args.default.option(["S", "skipScreenshots"], "Skip screenshot generation", false);
5714
+ import_args.default.option(["u", "updateOnly"], "Only update tickers history", false);
5715
+ import_args.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
5716
+ import_args.default.option(["L", "showTickersList"], "Just show only ticker list", false);
5717
+ import_args.default.option(
5718
+ ["p", "parallel"],
5719
+ "Signal evaluation worker count",
5720
+ Number(process.env.SIGNALS_PARALLEL || 4)
5721
+ );
5722
+ import_args.default.option(
5723
+ ["R", "showSkipStats"],
5724
+ "Show aggregated skip stats by strategy",
5725
+ false
5726
+ );
5727
+ import_args.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
5728
+ import_args.default.option(["U", "user"], "Use user confg", "root");
5729
+ import_args.default.option(["w", "watch"], "Keep signals running on candle boundaries", false);
5730
+ import_args.default.option(
5731
+ ["d", "settleDelayMs"],
5732
+ "Delay after candle close before a daemon cycle",
5733
+ Number(process.env.SIGNALS_DAEMON_SETTLE_DELAY_MS || 5e3)
5734
+ );
5735
+ import_args.default.option(
5736
+ ["o", "connector"],
5737
+ "Connector provider or name for signals (e.g. bybit, binance, coinbase, custom)",
5738
+ "bybit"
5739
+ );
5740
+ import_args.default.option(["V", "universe"], "Market universe (crypto or tradfi)", "crypto");
5741
+ import_args.default.option(["A", "account"], "Trading account id");
5742
+ import_args.default.option(["D", "deployment"], "Runtime deployment id");
5743
+ var flags = import_args.default.parse(process.argv);
5744
+ var hasExplicitScope = process.argv.some(
5745
+ (argument) => [
5746
+ "-f",
5747
+ "--timeframe",
5748
+ "-V",
5749
+ "--universe",
5750
+ "-A",
5751
+ "--account",
5752
+ "-D",
5753
+ "--deployment"
5754
+ ].some((option) => argument === option || argument.startsWith(`${option}=`))
5755
+ );
5756
+ var config = {
5757
+ projectRoot: String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd(),
5758
+ userName: String(flags.user || "root"),
5759
+ interval: String(flags.timeframe ?? 15),
5760
+ connectorName: String(flags.connector || "bybit"),
5761
+ universe: flags.universe,
5762
+ accountId: flags.account ? String(flags.account) : void 0,
5763
+ deploymentId: flags.deployment ? String(flags.deployment) : void 0,
5764
+ tickers: flags.tickers,
5765
+ exclude: flags.exclude,
5766
+ tickersLimit: flags.tickersLimit,
5767
+ chunk: flags.chunk,
5768
+ makeOrders: Boolean(flags.makeOrders),
5769
+ notify: Boolean(flags.notify),
5770
+ skipScreenshots: Boolean(flags.skipScreenshots),
5771
+ updateOnly: Boolean(flags.updateOnly),
5772
+ cacheOnly: Boolean(flags.cacheOnly),
5773
+ showTickersList: Boolean(flags.showTickersList),
5774
+ showSkipStats: Boolean(flags.showSkipStats),
5775
+ parallel: flags.parallel,
5776
+ watch: Boolean(flags.watch),
5777
+ settleDelayMs: flags.settleDelayMs,
5778
+ hasExplicitScope
5779
+ };
5780
+ var runner = createSignalsRunner(config);
5781
+ var createSignalsSession = runner.createSession;
5782
+ var signals = runner.runCycle;
5783
+ var signalsConfiguredScopesOnce = runner.runConfiguredScopesOnce;
5784
+ var signalsDaemon = runner.runDaemon;
5785
+
7343
5786
  // src/scripts/signalsDaemon.ts
7344
5787
  var main = signalsDaemon;
7345
5788
  // Annotate the CommonJS export names for ESM import in node: