@tradejs/cli 2.0.17 → 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 (42) hide show
  1. package/dist/cli.js +6122 -12724
  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/runtimeEvidenceArtifacts.js +13 -1
  13. package/dist/lib/runtimeRedis.js +6 -57
  14. package/dist/lib/runtimeStrategyBacktest.js +2 -48
  15. package/dist/scripts/aiExport.js +1 -1607
  16. package/dist/scripts/aiPocketSearch.js +1 -1607
  17. package/dist/scripts/aiTrain.js +17 -1623
  18. package/dist/scripts/backtest.js +110 -1759
  19. package/dist/scripts/binanceMarketIngest.js +5 -4
  20. package/dist/scripts/candlesMigrateProvider.js +6 -5186
  21. package/dist/scripts/cleanupMarketContext.js +4 -3
  22. package/dist/scripts/continuity.js +4 -3
  23. package/dist/scripts/derivativesIngest.js +6 -4
  24. package/dist/scripts/derivativesIngestCoinalyzeAll.js +5 -4
  25. package/dist/scripts/doctor.js +2 -5184
  26. package/dist/scripts/hyperliquidWhaleBackfill.js +8 -8
  27. package/dist/scripts/hyperliquidWhaleIngest.js +4 -4
  28. package/dist/scripts/hyperliquidWhalesUpdate.js +1 -1
  29. package/dist/scripts/migration.js +3 -3
  30. package/dist/scripts/mlExport.js +1 -1607
  31. package/dist/scripts/replay.js +291 -1807
  32. package/dist/scripts/replayRunner.js +291 -1807
  33. package/dist/scripts/replayRuntimeEvidence.js +2 -48
  34. package/dist/scripts/researchAuto.js +3 -49
  35. package/dist/scripts/results.js +1 -1607
  36. package/dist/scripts/runtimeEvidence.js +15 -49
  37. package/dist/scripts/runtimeParity.js +121 -1746
  38. package/dist/scripts/signals.js +1057 -2647
  39. package/dist/scripts/signalsDaemon.js +1051 -2608
  40. package/dist/scripts/signalsSummary.js +4 -26
  41. package/dist/workers/testerWorker.js +2 -2
  42. 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/signals.ts
1637
31
  var signals_exports = {};
1638
32
  __export(signals_exports, {
@@ -1645,25 +39,26 @@ __export(signals_exports, {
1645
39
  module.exports = __toCommonJS(signals_exports);
1646
40
  var import_config = require("dotenv/config");
1647
41
  var import_args = __toESM(require("args"));
42
+
43
+ // src/lib/signals/runner.ts
1648
44
  var import_progress4 = __toESM(require("progress"));
1649
45
  var import_chalk7 = __toESM(require("chalk"));
1650
46
  var import_connectors6 = require("@tradejs/node/connectors");
1651
47
  var import_cli2 = require("@tradejs/node/cli");
1652
48
  var import_async3 = require("@tradejs/core/async");
1653
- var import_strategies5 = require("@tradejs/core/strategies");
49
+ var import_strategies6 = require("@tradejs/core/strategies");
1654
50
  var import_constants3 = require("@tradejs/core/constants");
1655
- var import_strategies6 = require("@tradejs/node/strategies");
1656
51
  var import_time3 = require("@tradejs/core/time");
1657
- var import_logger4 = require("@tradejs/infra/logger");
1658
- var import_tradingAccounts2 = require("@tradejs/infra/tradingAccounts");
52
+ var import_logger5 = require("@tradejs/infra/logger");
53
+ var import_runtimeDeployments = require("@tradejs/infra/runtimeDeployments");
1659
54
 
1660
55
  // src/lib/marketData/windows.ts
1661
56
  var import_indicators = require("@tradejs/core/indicators");
1662
- var resolveOpenTimestamp = (timestamp, intervalMs2) => Number.isFinite(intervalMs2) && intervalMs2 > 0 ? Math.floor(timestamp / intervalMs2) * intervalMs2 : timestamp;
1663
- var getClosedCandlesForInterval = (candles, currentTimestamp, intervalMs2) => {
57
+ var resolveOpenTimestamp = (timestamp, intervalMs) => Number.isFinite(intervalMs) && intervalMs > 0 ? Math.floor(timestamp / intervalMs) * intervalMs : timestamp;
58
+ var getClosedCandlesForInterval = (candles, currentTimestamp, intervalMs) => {
1664
59
  const currentOpenTimestamp = resolveOpenTimestamp(
1665
60
  currentTimestamp,
1666
- intervalMs2
61
+ intervalMs
1667
62
  );
1668
63
  return candles.filter((candle) => candle.timestamp < currentOpenTimestamp);
1669
64
  };
@@ -1671,7 +66,7 @@ var alignSymbolWithBtcReference = (symbolCandles, btcCandles) => (0, import_indi
1671
66
 
1672
67
  // src/lib/runFormatting.ts
1673
68
  var import_date_fns = require("date-fns");
1674
- var ListIt = require_list_it();
69
+ var ListIt = require("list-it");
1675
70
  var formatDuration = (startedAt) => {
1676
71
  const seconds = Math.max(0, (Date.now() - startedAt) / 1e3);
1677
72
  if (seconds < 60) return `${seconds.toFixed(1)}s`;
@@ -1716,7 +111,7 @@ var invokeAfterSignalsHooks = async (hooks, params) => {
1716
111
 
1717
112
  // src/lib/marketContextPrepare.ts
1718
113
  var import_chalk4 = __toESM(require("chalk"));
1719
- var import_timescale5 = require("@tradejs/infra/timescale");
114
+ var import_marketContext3 = require("@tradejs/infra/timescale/marketContext");
1720
115
  var import_registry = require("@tradejs/node/registry");
1721
116
 
1722
117
  // src/lib/binanceMarketContextBackfill.ts
@@ -1725,7 +120,8 @@ var import_chalk = __toESM(require("chalk"));
1725
120
  var import_connectors = require("@tradejs/connectors");
1726
121
  var import_connectors2 = require("@tradejs/node/connectors");
1727
122
  var import_strategies = require("@tradejs/node/strategies");
1728
- var import_timescale = require("@tradejs/infra/timescale");
123
+ var import_marketContext = require("@tradejs/infra/timescale/marketContext");
124
+ var import_client = require("@tradejs/infra/timescale/client");
1729
125
 
1730
126
  // src/lib/binanceMarketData.ts
1731
127
  var MARKET_FEATURE_INTERVAL_MS = {
@@ -1779,17 +175,17 @@ var classifyBtcAltRegime = ({
1779
175
  };
1780
176
  var aggregateAggTradesToRows = ({
1781
177
  symbol,
1782
- interval: interval2,
178
+ interval,
1783
179
  trades,
1784
180
  source = "binance_agg_trades"
1785
181
  }) => {
1786
- const intervalMs2 = MARKET_FEATURE_INTERVAL_MS[interval2];
182
+ const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
1787
183
  const buckets = /* @__PURE__ */ new Map();
1788
184
  for (const trade of trades) {
1789
- const bucketTs = Math.floor(trade.timestamp / intervalMs2) * intervalMs2;
185
+ const bucketTs = Math.floor(trade.timestamp / intervalMs) * intervalMs;
1790
186
  const row = buckets.get(bucketTs) ?? {
1791
187
  symbol,
1792
- interval: interval2,
188
+ interval,
1793
189
  ts: new Date(bucketTs),
1794
190
  trades: 0,
1795
191
  buyBaseVolume: 0,
@@ -1823,7 +219,7 @@ var aggregateAggTradesToRows = ({
1823
219
  };
1824
220
  var buildKlineTradeFlowRows = ({
1825
221
  symbol,
1826
- interval: interval2,
222
+ interval,
1827
223
  candles,
1828
224
  source = "binance_klines"
1829
225
  }) => candles.map((candle) => {
@@ -1837,7 +233,7 @@ var buildKlineTradeFlowRows = ({
1837
233
  const trades = candle.trades != null && Number.isFinite(candle.trades) ? Math.max(0, Math.trunc(candle.trades)) : 0;
1838
234
  return {
1839
235
  symbol,
1840
- interval: interval2,
236
+ interval,
1841
237
  ts: new Date(candle.timestamp),
1842
238
  trades,
1843
239
  buyBaseVolume,
@@ -1855,7 +251,7 @@ var buildKlineTradeFlowRows = ({
1855
251
  }).filter((row) => row != null);
1856
252
  var buildMarketBreadthRows = ({
1857
253
  universe,
1858
- interval: interval2,
254
+ interval,
1859
255
  candlesBySymbol,
1860
256
  btcCandles,
1861
257
  source = "binance_klines"
@@ -1880,10 +276,10 @@ var buildMarketBreadthRows = ({
1880
276
  btcCandles.map((candle) => Math.max(0, candle.turnover ?? 0))
1881
277
  )
1882
278
  } : null;
1883
- const intervalMs2 = MARKET_FEATURE_INTERVAL_MS[interval2];
1884
- const bars1h = Math.max(1, Math.round(36e5 / intervalMs2));
1885
- const bars4h = Math.max(1, Math.round(144e5 / intervalMs2));
1886
- const bars24h = Math.max(1, Math.round(864e5 / intervalMs2));
279
+ const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
280
+ const bars1h = Math.max(1, Math.round(36e5 / intervalMs));
281
+ const bars4h = Math.max(1, Math.round(144e5 / intervalMs));
282
+ const bars24h = Math.max(1, Math.round(864e5 / intervalMs));
1887
283
  for (const candles of Object.values(candlesBySymbol)) {
1888
284
  for (const candle of candles) timestamps.add(candle.timestamp);
1889
285
  }
@@ -1994,7 +390,7 @@ var buildMarketBreadthRows = ({
1994
390
  const btcTurnoverShareChange24h = btcTurnoverShare24h == null || previousBtcTurnoverShare24h == null ? null : btcTurnoverShare24h - previousBtcTurnoverShare24h;
1995
391
  return {
1996
392
  universe,
1997
- interval: interval2,
393
+ interval,
1998
394
  ts: new Date(timestamp),
1999
395
  symbolsCount: returns.length,
2000
396
  advancers,
@@ -2055,17 +451,17 @@ var getReferenceSymbols = () => {
2055
451
  const symbols = (process.env.BINANCE_MARKET_CONTEXT_REFERENCE_SYMBOLS || "BTCUSDT,ETHUSDT").split(",").map((item) => item.trim().toUpperCase()).filter(Boolean);
2056
452
  return symbols.length ? [...new Set(symbols)] : ["BTCUSDT", "ETHUSDT"];
2057
453
  };
2058
- var intervalToMarketFeatureInterval = (interval2) => {
2059
- const normalized = String(interval2).trim().toLowerCase();
454
+ var intervalToMarketFeatureInterval = (interval) => {
455
+ const normalized = String(interval).trim().toLowerCase();
2060
456
  if (normalized === "1" || normalized === "1m") return "1m";
2061
457
  if (normalized === "5" || normalized === "5m") return "5m";
2062
458
  if (normalized === "60" || normalized === "1h") return "1h";
2063
459
  return "15m";
2064
460
  };
2065
- var marketIntervalToConnectorInterval = (interval2) => {
2066
- if (interval2 === "1m") return "1";
2067
- if (interval2 === "5m") return "5";
2068
- if (interval2 === "1h") return "60";
461
+ var marketIntervalToConnectorInterval = (interval) => {
462
+ if (interval === "1m") return "1";
463
+ if (interval === "5m") return "5";
464
+ if (interval === "1h") return "60";
2069
465
  return "15";
2070
466
  };
2071
467
  var resolveBinanceMarketContextBackfillWindow = ({
@@ -2088,21 +484,21 @@ var hasCoverage = ({
2088
484
  coverage,
2089
485
  startMs,
2090
486
  endMs,
2091
- intervalMs: intervalMs2
487
+ intervalMs
2092
488
  }) => {
2093
489
  if (!coverage) return false;
2094
- const expectedRows = Math.max(1, Math.floor((endMs - startMs) / intervalMs2));
2095
- return coverage.firstMs <= startMs + intervalMs2 && coverage.lastMs >= endMs - intervalMs2 && coverage.rows >= Math.floor(expectedRows * 0.9);
490
+ const expectedRows = Math.max(1, Math.floor((endMs - startMs) / intervalMs));
491
+ return coverage.firstMs <= startMs + intervalMs && coverage.lastMs >= endMs - intervalMs && coverage.rows >= Math.floor(expectedRows * 0.9);
2096
492
  };
2097
493
  var buildBreadthBackfillChunks = ({
2098
494
  startMs,
2099
495
  endMs,
2100
- intervalMs: intervalMs2,
496
+ intervalMs,
2101
497
  chunkDays
2102
498
  }) => {
2103
- const chunkMs = Math.max(intervalMs2, chunkDays * DAY_MS);
2104
- const warmupBars = Math.max(50, Math.ceil(DAY_MS * 2 / intervalMs2));
2105
- const warmupMs = warmupBars * intervalMs2;
499
+ const chunkMs = Math.max(intervalMs, chunkDays * DAY_MS);
500
+ const warmupBars = Math.max(50, Math.ceil(DAY_MS * 2 / intervalMs));
501
+ const warmupMs = warmupBars * intervalMs;
2106
502
  const chunks = [];
2107
503
  let cursor = startMs;
2108
504
  while (cursor <= endMs) {
@@ -2119,10 +515,10 @@ var buildBreadthBackfillChunks = ({
2119
515
  var buildTradeFlowBackfillChunks = ({
2120
516
  startMs,
2121
517
  endMs,
2122
- intervalMs: intervalMs2,
518
+ intervalMs,
2123
519
  chunkDays
2124
520
  }) => {
2125
- const chunkMs = Math.max(intervalMs2, chunkDays * DAY_MS);
521
+ const chunkMs = Math.max(intervalMs, chunkDays * DAY_MS);
2126
522
  const chunks = [];
2127
523
  let cursor = startMs;
2128
524
  while (cursor <= endMs) {
@@ -2135,13 +531,13 @@ var buildTradeFlowBackfillChunks = ({
2135
531
  var filterMissingBreadthBackfillChunks = ({
2136
532
  chunks,
2137
533
  coverage,
2138
- intervalMs: intervalMs2
534
+ intervalMs
2139
535
  }) => chunks.filter(
2140
536
  (chunk) => !hasCoverage({
2141
537
  coverage,
2142
538
  startMs: chunk.startMs,
2143
539
  endMs: chunk.endMs,
2144
- intervalMs: intervalMs2
540
+ intervalMs
2145
541
  })
2146
542
  );
2147
543
  var fetchAggTradesForWindow = async ({
@@ -2181,12 +577,12 @@ var fetchAggTradesForWindow = async ({
2181
577
  return rows;
2182
578
  };
2183
579
  var getBinanceConnector = async ({
2184
- projectRoot: projectRoot2,
580
+ projectRoot,
2185
581
  userName
2186
582
  }) => {
2187
583
  const creator = await (0, import_connectors2.getConnectorCreatorByName)(
2188
584
  import_connectors.ConnectorNames.Binance,
2189
- projectRoot2
585
+ projectRoot
2190
586
  );
2191
587
  if (!creator) {
2192
588
  throw new Error(
@@ -2227,13 +623,13 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2227
623
  if (!enabled || !symbols.length) {
2228
624
  return skippedBackfillResult();
2229
625
  }
2230
- const interval2 = intervalToMarketFeatureInterval(params.interval);
2231
- const intervalMs2 = MARKET_FEATURE_INTERVAL_MS[interval2];
626
+ const interval = intervalToMarketFeatureInterval(params.interval);
627
+ const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
2232
628
  const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
2233
629
  if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
2234
630
  return skippedBackfillResult();
2235
631
  }
2236
- await (0, import_timescale.waitForDbReady)();
632
+ await (0, import_client.waitForDbReady)();
2237
633
  const connector = await getBinanceConnector({
2238
634
  projectRoot: params.projectRoot,
2239
635
  userName: params.userName
@@ -2275,13 +671,13 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2275
671
  let breadthRows = 0;
2276
672
  console.log(
2277
673
  import_chalk.default.cyan(
2278
- `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()}`
674
+ `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()}`
2279
675
  )
2280
676
  );
2281
677
  if (includeTradeFlow && referenceSymbols.length) {
2282
- const coverage = await (0, import_timescale.getMarketTradeFlowCoverage)({
678
+ const coverage = await (0, import_marketContext.getMarketTradeFlowCoverage)({
2283
679
  symbols: referenceSymbols,
2284
- interval: interval2,
680
+ interval,
2285
681
  startMs: tradeFlowStartMs,
2286
682
  endMs
2287
683
  });
@@ -2290,7 +686,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2290
686
  coverage: coverage.get(symbol),
2291
687
  startMs: tradeFlowStartMs,
2292
688
  endMs,
2293
- intervalMs: intervalMs2
689
+ intervalMs
2294
690
  })
2295
691
  );
2296
692
  const bar = new import_progress.default(
@@ -2303,11 +699,11 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2303
699
  if (!missingSymbols.length) {
2304
700
  bar.tick(1, { rows: 0, skip: referenceSymbols.length, symbol: "cached" });
2305
701
  }
2306
- const connectorInterval = marketIntervalToConnectorInterval(interval2);
702
+ const connectorInterval = marketIntervalToConnectorInterval(interval);
2307
703
  const chunks = buildTradeFlowBackfillChunks({
2308
704
  startMs: tradeFlowStartMs,
2309
705
  endMs,
2310
- intervalMs: intervalMs2,
706
+ intervalMs,
2311
707
  chunkDays: tradeFlowChunkDays
2312
708
  });
2313
709
  const chunkBar = missingSymbols.length ? new import_progress.default(
@@ -2326,7 +722,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2326
722
  coverage: symbolCoverage,
2327
723
  startMs: chunk.startMs,
2328
724
  endMs: chunk.endMs,
2329
- intervalMs: intervalMs2
725
+ intervalMs
2330
726
  })) {
2331
727
  skippedTradeFlowChunks += 1;
2332
728
  chunkBar?.tick(1, {
@@ -2339,7 +735,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2339
735
  }
2340
736
  const rows = tradeFlowSource === "agg_trades" ? aggregateAggTradesToRows({
2341
737
  symbol,
2342
- interval: interval2,
738
+ interval,
2343
739
  trades: await fetchAggTradesForWindow({
2344
740
  connector,
2345
741
  symbol,
@@ -2350,7 +746,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2350
746
  })
2351
747
  }) : buildKlineTradeFlowRows({
2352
748
  symbol,
2353
- interval: interval2,
749
+ interval,
2354
750
  candles: await connector.kline({
2355
751
  symbol,
2356
752
  interval: connectorInterval,
@@ -2363,7 +759,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2363
759
  const ts = row.ts.getTime();
2364
760
  return ts >= chunk.startMs && ts <= chunk.endMs;
2365
761
  });
2366
- await (0, import_timescale.upsertMarketTradeFlowRows)(boundedRows);
762
+ await (0, import_marketContext.upsertMarketTradeFlowRows)(boundedRows);
2367
763
  tradeFlowRows += boundedRows.length;
2368
764
  chunkBar?.tick(1, {
2369
765
  rows: tradeFlowRows,
@@ -2382,18 +778,18 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2382
778
  if (includeBreadth) {
2383
779
  const breadthUniverses = (0, import_strategies.getBinanceBreadthUniverses)();
2384
780
  const breadthSymbols = breadthUniverses.at(-1)?.symbols ?? [];
2385
- const connectorInterval = marketIntervalToConnectorInterval(interval2);
781
+ const connectorInterval = marketIntervalToConnectorInterval(interval);
2386
782
  const chunks = buildBreadthBackfillChunks({
2387
783
  startMs: breadthStartMs,
2388
784
  endMs,
2389
- intervalMs: intervalMs2,
785
+ intervalMs,
2390
786
  chunkDays: breadthChunkDays
2391
787
  });
2392
788
  const plans = await Promise.all(
2393
789
  breadthUniverses.map(async (definition) => {
2394
- const coverage = await (0, import_timescale.getMarketBreadthCoverage)({
790
+ const coverage = await (0, import_marketContext.getMarketBreadthCoverage)({
2395
791
  universe: definition.universe,
2396
- interval: interval2,
792
+ interval,
2397
793
  startMs: breadthStartMs,
2398
794
  endMs
2399
795
  });
@@ -2402,11 +798,11 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2402
798
  coverage,
2403
799
  startMs: breadthStartMs,
2404
800
  endMs,
2405
- intervalMs: intervalMs2
801
+ intervalMs
2406
802
  }) || !hasBtcAltMetrics ? !hasBtcAltMetrics ? chunks : filterMissingBreadthBackfillChunks({
2407
803
  chunks,
2408
804
  coverage,
2409
- intervalMs: intervalMs2
805
+ intervalMs
2410
806
  }) : [];
2411
807
  if (!missingChunks2.length) {
2412
808
  console.log(
@@ -2485,14 +881,14 @@ var backfillBinanceMarketContext = async (params, enabled) => {
2485
881
  );
2486
882
  const rows = buildMarketBreadthRows({
2487
883
  universe: plan.definition.universe,
2488
- interval: interval2,
884
+ interval,
2489
885
  candlesBySymbol: universeCandles,
2490
886
  btcCandles
2491
887
  }).filter((row) => {
2492
888
  const ts = row.ts.getTime();
2493
889
  return ts >= chunk.startMs && ts <= chunk.endMs;
2494
890
  });
2495
- await (0, import_timescale.upsertMarketBreadthRows)(rows);
891
+ await (0, import_marketContext.upsertMarketBreadthRows)(rows);
2496
892
  breadthRows += rows.length;
2497
893
  }
2498
894
  }
@@ -2520,7 +916,8 @@ var import_progress2 = __toESM(require("progress"));
2520
916
  var import_async = require("@tradejs/core/async");
2521
917
  var import_constants = require("@tradejs/core/constants");
2522
918
  var import_indicators2 = require("@tradejs/core/indicators");
2523
- var import_timescale2 = require("@tradejs/infra/timescale");
919
+ var import_derivatives = require("@tradejs/infra/timescale/derivatives");
920
+ var import_client2 = require("@tradejs/infra/timescale/client");
2524
921
  var import_userSettings = require("@tradejs/infra/userSettings");
2525
922
  var HOUR_MS = 60 * 60 * 1e3;
2526
923
  var DAY_MS2 = 24 * HOUR_MS;
@@ -2530,7 +927,7 @@ var coinalyzeIntervalMap = {
2530
927
  "15m": "15min",
2531
928
  "1h": "1hour"
2532
929
  };
2533
- var derivativesIntervalMs = (interval2) => interval2 === "1h" ? HOUR_MS : 15 * 60 * 1e3;
930
+ var derivativesIntervalMs = (interval) => interval === "1h" ? HOUR_MS : 15 * 60 * 1e3;
2534
931
  var lastRequestTs = 0;
2535
932
  var asInt2 = (value, fallback) => {
2536
933
  const parsed = Number.parseInt(String(value ?? ""), 10);
@@ -2620,12 +1017,12 @@ var resolveDerivativesContextBackfillWindow = (params) => {
2620
1017
  };
2621
1018
  };
2622
1019
  var resolveDerivativesContextIntervalBackfillWindow = (params) => {
2623
- const intervalMs2 = derivativesIntervalMs(params.interval);
2624
- const alignedToMs = params.closedOnly ? (0, import_indicators2.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs2) * intervalMs2;
1020
+ const intervalMs = derivativesIntervalMs(params.interval);
1021
+ const alignedToMs = params.closedOnly ? (0, import_indicators2.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs) * intervalMs;
2625
1022
  return {
2626
- fromMs: Math.floor(params.fromMs / intervalMs2) * intervalMs2,
1023
+ fromMs: Math.floor(params.fromMs / intervalMs) * intervalMs,
2627
1024
  toMs: alignedToMs,
2628
- intervalMs: intervalMs2
1025
+ intervalMs
2629
1026
  };
2630
1027
  };
2631
1028
  var resolveDerivativesContextMissingFetchFromMs = (params) => {
@@ -2974,10 +1371,10 @@ var toSeriesMap = (raw, metric) => {
2974
1371
  return out;
2975
1372
  };
2976
1373
  var fetchMetricBatch = async (params) => {
2977
- const { endpoint, metric, marketSymbols, apiKey, interval: interval2, fromMs, toMs } = params;
1374
+ const { endpoint, metric, marketSymbols, apiKey, interval, fromMs, toMs } = params;
2978
1375
  const url = new URL(`${getCoinalyzeBaseUrl()}${endpoint}`);
2979
1376
  url.searchParams.set("symbols", marketSymbols.join(","));
2980
- url.searchParams.set("interval", coinalyzeIntervalMap[interval2] || interval2);
1377
+ url.searchParams.set("interval", coinalyzeIntervalMap[interval] || interval);
2981
1378
  url.searchParams.set("from", String(Math.floor(fromMs / 1e3)));
2982
1379
  url.searchParams.set("to", String(Math.floor(toMs / 1e3)));
2983
1380
  const raw = await fetchJsonWithRateLimit(url.toString(), apiKey);
@@ -3021,25 +1418,25 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3021
1418
  30
3022
1419
  );
3023
1420
  const batchMs = batchDays * DAY_MS2;
3024
- const intervalWindows = intervals.map((interval2) => ({
3025
- interval: interval2,
1421
+ const intervalWindows = intervals.map((interval) => ({
1422
+ interval,
3026
1423
  ...resolveDerivativesContextIntervalBackfillWindow({
3027
1424
  fromMs,
3028
1425
  toMs: safeEndMs,
3029
- interval: interval2,
1426
+ interval,
3030
1427
  closedOnly: mode === "signals"
3031
1428
  })
3032
1429
  })).filter((item) => item.toMs > item.fromMs);
3033
1430
  if (!intervalWindows.length) {
3034
1431
  return skippedBackfillResult2();
3035
1432
  }
3036
- await (0, import_timescale2.waitForDbReady)();
1433
+ await (0, import_client2.waitForDbReady)();
3037
1434
  const edgesByInterval = /* @__PURE__ */ new Map();
3038
1435
  await Promise.all(
3039
- intervalWindows.map(async ({ interval: interval2 }) => {
1436
+ intervalWindows.map(async ({ interval }) => {
3040
1437
  edgesByInterval.set(
3041
- interval2,
3042
- await (0, import_timescale2.getDerivativesDataEdgesForSymbols)(symbols, interval2)
1438
+ interval,
1439
+ await (0, import_derivatives.getDerivativesDataEdgesForSymbols)(symbols, interval)
3043
1440
  );
3044
1441
  })
3045
1442
  );
@@ -3048,32 +1445,32 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3048
1445
  const liquidationCoverageRangesByInterval = /* @__PURE__ */ new Map();
3049
1446
  const coverageNowMs = Date.now();
3050
1447
  await Promise.all(
3051
- intervalWindows.map(async (window2) => {
1448
+ intervalWindows.map(async (window) => {
3052
1449
  const confirmedLiquidationWindow = (0, import_indicators2.resolveCoinalyzeConfirmedIntradayCoverage)({
3053
- interval: window2.interval,
3054
- fromMs: window2.fromMs,
3055
- toMs: window2.toMs,
1450
+ interval: window.interval,
1451
+ fromMs: window.fromMs,
1452
+ toMs: window.toMs,
3056
1453
  nowMs: coverageNowMs
3057
1454
  });
3058
1455
  const [coverageRows, liquidationCoverageRows] = await Promise.all([
3059
- (0, import_timescale2.getDerivativesBackfillCoverage)({
1456
+ (0, import_derivatives.getDerivativesBackfillCoverage)({
3060
1457
  source: "coinalyze",
3061
1458
  symbols,
3062
- interval: window2.interval,
3063
- fromMs: window2.fromMs,
3064
- toMs: window2.toMs
1459
+ interval: window.interval,
1460
+ fromMs: window.fromMs,
1461
+ toMs: window.toMs
3065
1462
  }),
3066
- confirmedLiquidationWindow ? (0, import_timescale2.getDerivativesMetricCoverage)({
1463
+ confirmedLiquidationWindow ? (0, import_derivatives.getDerivativesMetricCoverage)({
3067
1464
  source: "coinalyze",
3068
1465
  metric: "liquidation",
3069
1466
  symbols,
3070
- interval: window2.interval,
1467
+ interval: window.interval,
3071
1468
  fromMs: confirmedLiquidationWindow.fromMs,
3072
1469
  toMs: confirmedLiquidationWindow.toMs
3073
1470
  }) : Promise.resolve([])
3074
1471
  ]);
3075
1472
  coverageKeysByInterval.set(
3076
- window2.interval,
1473
+ window.interval,
3077
1474
  new Set(
3078
1475
  coverageRows.map(
3079
1476
  (row) => coverageKey({
@@ -3092,7 +1489,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3092
1489
  ranges.push({ fromMs: row.fromMs, toMs: row.toMs });
3093
1490
  rangesBySymbol.set(symbol, ranges);
3094
1491
  }
3095
- coverageRangesByInterval.set(window2.interval, rangesBySymbol);
1492
+ coverageRangesByInterval.set(window.interval, rangesBySymbol);
3096
1493
  const liquidationRangesBySymbol = /* @__PURE__ */ new Map();
3097
1494
  for (const row of liquidationCoverageRows) {
3098
1495
  const symbol = row.symbol.toUpperCase();
@@ -3101,33 +1498,33 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3101
1498
  liquidationRangesBySymbol.set(symbol, ranges);
3102
1499
  }
3103
1500
  liquidationCoverageRangesByInterval.set(
3104
- window2.interval,
1501
+ window.interval,
3105
1502
  liquidationRangesBySymbol
3106
1503
  );
3107
1504
  })
3108
1505
  );
3109
1506
  const cachedWindows = intervalWindows.reduce(
3110
- (sum, window2) => sum + countBackfillWindows({
3111
- fromMs: window2.fromMs,
3112
- toMs: window2.toMs,
1507
+ (sum, window) => sum + countBackfillWindows({
1508
+ fromMs: window.fromMs,
1509
+ toMs: window.toMs,
3113
1510
  batchMs,
3114
- intervalMs: window2.intervalMs
1511
+ intervalMs: window.intervalMs
3115
1512
  }),
3116
1513
  0
3117
1514
  );
3118
- const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window2) => {
3119
- const edgesBySymbol = edgesByInterval.get(window2.interval);
3120
- const coverageKeys = coverageKeysByInterval.get(window2.interval);
1515
+ const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window) => {
1516
+ const edgesBySymbol = edgesByInterval.get(window.interval);
1517
+ const coverageKeys = coverageKeysByInterval.get(window.interval);
3121
1518
  const backfillWindows = buildBackfillWindows({
3122
- fromMs: window2.fromMs,
3123
- toMs: window2.toMs,
1519
+ fromMs: window.fromMs,
1520
+ toMs: window.toMs,
3124
1521
  batchMs,
3125
- intervalMs: window2.intervalMs
1522
+ intervalMs: window.intervalMs
3126
1523
  });
3127
1524
  return symbols.every(
3128
1525
  (symbol) => backfillWindows.every((backfillWindow) => {
3129
1526
  const normalizedSymbol = symbol.toUpperCase();
3130
- const coverageRanges = coverageRangesByInterval.get(window2.interval)?.get(normalizedSymbol) ?? [];
1527
+ const coverageRanges = coverageRangesByInterval.get(window.interval)?.get(normalizedSymbol) ?? [];
3131
1528
  const dataCovered = hasDerivativesWindowCoverage({
3132
1529
  edges: edgesBySymbol?.get(normalizedSymbol),
3133
1530
  fromMs: backfillWindow.fromMs,
@@ -3136,26 +1533,26 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3136
1533
  ranges: coverageRanges,
3137
1534
  fromMs: backfillWindow.fromMs,
3138
1535
  toMs: backfillWindow.toMs,
3139
- intervalMs: window2.intervalMs
1536
+ intervalMs: window.intervalMs
3140
1537
  }) == null || coverageKeys?.has(
3141
1538
  coverageKey({
3142
1539
  symbol: normalizedSymbol,
3143
- interval: window2.interval,
1540
+ interval: window.interval,
3144
1541
  fromMs: backfillWindow.fromMs,
3145
1542
  toMs: backfillWindow.toMs
3146
1543
  })
3147
1544
  );
3148
1545
  const confirmedLiquidationWindow = (0, import_indicators2.resolveCoinalyzeConfirmedIntradayCoverage)({
3149
- interval: window2.interval,
1546
+ interval: window.interval,
3150
1547
  fromMs: backfillWindow.fromMs,
3151
1548
  toMs: backfillWindow.toMs,
3152
1549
  nowMs: coverageNowMs
3153
1550
  });
3154
1551
  const liquidationCovered = confirmedLiquidationWindow == null || resolveDerivativesContextMissingCoverageFetchFromMs({
3155
- ranges: liquidationCoverageRangesByInterval.get(window2.interval)?.get(normalizedSymbol) ?? [],
1552
+ ranges: liquidationCoverageRangesByInterval.get(window.interval)?.get(normalizedSymbol) ?? [],
3156
1553
  fromMs: confirmedLiquidationWindow.fromMs,
3157
1554
  toMs: confirmedLiquidationWindow.toMs,
3158
- intervalMs: window2.intervalMs
1555
+ intervalMs: window.intervalMs
3159
1556
  }) == null;
3160
1557
  return dataCovered && liquidationCovered;
3161
1558
  })
@@ -3205,11 +1602,11 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3205
1602
  );
3206
1603
  const symbolBatches = chunkArray(matches, symbolBatchSize);
3207
1604
  const windowsPerPair = intervalWindows.reduce(
3208
- (sum, window2) => sum + countBackfillWindows({
3209
- fromMs: window2.fromMs,
3210
- toMs: window2.toMs,
1605
+ (sum, window) => sum + countBackfillWindows({
1606
+ fromMs: window.fromMs,
1607
+ toMs: window.toMs,
3211
1608
  batchMs,
3212
- intervalMs: window2.intervalMs
1609
+ intervalMs: window.intervalMs
3213
1610
  }),
3214
1611
  0
3215
1612
  );
@@ -3232,30 +1629,30 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3232
1629
  `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()}`
3233
1630
  )
3234
1631
  );
3235
- for (const window2 of intervalWindows) {
3236
- const { interval: interval2, intervalMs: intervalMs2 } = window2;
3237
- const edgesBySymbol = edgesByInterval.get(interval2) ?? await (0, import_timescale2.getDerivativesDataEdgesForSymbols)(
1632
+ for (const window of intervalWindows) {
1633
+ const { interval, intervalMs } = window;
1634
+ const edgesBySymbol = edgesByInterval.get(interval) ?? await (0, import_derivatives.getDerivativesDataEdgesForSymbols)(
3238
1635
  matches.map((item) => item.symbol),
3239
- interval2
1636
+ interval
3240
1637
  );
3241
- const coverageKeys = coverageKeysByInterval.get(interval2) ?? /* @__PURE__ */ new Set();
3242
- coverageKeysByInterval.set(interval2, coverageKeys);
3243
- const coverageRangesBySymbol = coverageRangesByInterval.get(interval2) ?? /* @__PURE__ */ new Map();
3244
- coverageRangesByInterval.set(interval2, coverageRangesBySymbol);
3245
- const liquidationCoverageRangesBySymbol = liquidationCoverageRangesByInterval.get(interval2) ?? /* @__PURE__ */ new Map();
1638
+ const coverageKeys = coverageKeysByInterval.get(interval) ?? /* @__PURE__ */ new Set();
1639
+ coverageKeysByInterval.set(interval, coverageKeys);
1640
+ const coverageRangesBySymbol = coverageRangesByInterval.get(interval) ?? /* @__PURE__ */ new Map();
1641
+ coverageRangesByInterval.set(interval, coverageRangesBySymbol);
1642
+ const liquidationCoverageRangesBySymbol = liquidationCoverageRangesByInterval.get(interval) ?? /* @__PURE__ */ new Map();
3246
1643
  liquidationCoverageRangesByInterval.set(
3247
- interval2,
1644
+ interval,
3248
1645
  liquidationCoverageRangesBySymbol
3249
1646
  );
3250
1647
  for (let batchIdx = 0; batchIdx < symbolBatches.length; batchIdx += 1) {
3251
1648
  const batch = symbolBatches[batchIdx];
3252
- let cursor = window2.fromMs;
3253
- while (cursor < window2.toMs) {
3254
- const toMs = Math.min(window2.toMs, cursor + batchMs);
1649
+ let cursor = window.fromMs;
1650
+ while (cursor < window.toMs) {
1651
+ const toMs = Math.min(window.toMs, cursor + batchMs);
3255
1652
  const missingRanges = batch.map((item) => {
3256
1653
  const key = coverageKey({
3257
1654
  symbol: item.symbol,
3258
- interval: interval2,
1655
+ interval,
3259
1656
  fromMs: cursor,
3260
1657
  toMs
3261
1658
  });
@@ -3263,8 +1660,8 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3263
1660
  const requiredFromMs = resolveDerivativesContextRequiredFetchFromMs(
3264
1661
  {
3265
1662
  mode,
3266
- interval: interval2,
3267
- intervalMs: intervalMs2,
1663
+ interval,
1664
+ intervalMs,
3268
1665
  fromMs: cursor,
3269
1666
  toMs,
3270
1667
  nowMs: coverageNowMs,
@@ -3309,7 +1706,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3309
1706
  metric: "oi",
3310
1707
  marketSymbols,
3311
1708
  apiKey,
3312
- interval: interval2,
1709
+ interval,
3313
1710
  fromMs: group.fromMs,
3314
1711
  toMs
3315
1712
  });
@@ -3318,7 +1715,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3318
1715
  metric: "funding",
3319
1716
  marketSymbols,
3320
1717
  apiKey,
3321
- interval: interval2,
1718
+ interval,
3322
1719
  fromMs: group.fromMs,
3323
1720
  toMs
3324
1721
  });
@@ -3327,7 +1724,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3327
1724
  metric: "liq",
3328
1725
  marketSymbols,
3329
1726
  apiKey,
3330
- interval: interval2,
1727
+ interval,
3331
1728
  fromMs: group.fromMs,
3332
1729
  toMs
3333
1730
  });
@@ -3339,7 +1736,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3339
1736
  fundingRaw: fundingMap.get(marketSymbol) ?? [],
3340
1737
  liqRaw: liquidationRowsByMarket.get(marketSymbol) ?? []
3341
1738
  });
3342
- return (0, import_indicators2.coinalyzePointsToRows)(points, interval2, "coinalyze");
1739
+ return (0, import_indicators2.coinalyzePointsToRows)(points, interval, "coinalyze");
3343
1740
  });
3344
1741
  missingClosedSymbols = mode === "signals" ? getMissingClosedDerivativesSymbols({
3345
1742
  symbols: missingBatch.map((item) => item.symbol),
@@ -3353,15 +1750,15 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3353
1750
  }
3354
1751
  if (missingClosedSymbols.length) {
3355
1752
  throw new Error(
3356
- `Coinalyze closed ${interval2} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
1753
+ `Coinalyze closed ${interval} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
3357
1754
  );
3358
1755
  }
3359
1756
  if (rows.length) {
3360
- await (0, import_timescale2.upsertDerivatives)(rows);
1757
+ await (0, import_derivatives.upsertDerivatives)(rows);
3361
1758
  totalRows += rows.length;
3362
1759
  }
3363
1760
  const confirmedLiquidationWindow = (0, import_indicators2.resolveCoinalyzeConfirmedIntradayCoverage)({
3364
- interval: interval2,
1761
+ interval,
3365
1762
  fromMs: group.fromMs,
3366
1763
  toMs,
3367
1764
  nowMs: coverageNowMs
@@ -3379,13 +1776,13 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3379
1776
  source: "coinalyze",
3380
1777
  metric: "liquidation",
3381
1778
  symbol: item.symbol,
3382
- interval: interval2,
1779
+ interval,
3383
1780
  fromMs: confirmedLiquidationWindow.fromMs,
3384
1781
  toMs: confirmedLiquidationWindow.toMs,
3385
1782
  eventRowsCount
3386
1783
  };
3387
1784
  });
3388
- await (0, import_timescale2.applyDerivativesMetricCoverage)(metricCoverageRows);
1785
+ await (0, import_derivatives.applyDerivativesMetricCoverage)(metricCoverageRows);
3389
1786
  for (const coverageRow of metricCoverageRows) {
3390
1787
  const symbol = coverageRow.symbol.toUpperCase();
3391
1788
  const ranges = liquidationCoverageRangesBySymbol.get(symbol) ?? [];
@@ -3411,13 +1808,13 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3411
1808
  return {
3412
1809
  source: "coinalyze",
3413
1810
  symbol: item.symbol,
3414
- interval: interval2,
1811
+ interval,
3415
1812
  fromMs: cursor,
3416
1813
  toMs,
3417
1814
  rowsCount
3418
1815
  };
3419
1816
  });
3420
- await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
1817
+ await (0, import_derivatives.upsertDerivativesBackfillCoverage)(coverageRows);
3421
1818
  for (const coverageRow of coverageRows) {
3422
1819
  const symbol = coverageRow.symbol.toUpperCase();
3423
1820
  edgesBySymbol.set(
@@ -3427,7 +1824,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3427
1824
  coverageKeys.add(
3428
1825
  coverageKey({
3429
1826
  symbol,
3430
- interval: interval2,
1827
+ interval,
3431
1828
  fromMs: cursor,
3432
1829
  toMs
3433
1830
  })
@@ -3443,20 +1840,20 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3443
1840
  failedWindows += 1;
3444
1841
  console.error(
3445
1842
  import_chalk2.default.red(
3446
- `derivatives context backfill window failed batch=${batchIdx + 1}/${symbolBatches.length} interval=${interval2} ${new Date(cursor).toISOString()}..${new Date(toMs).toISOString()}: ${error}`
1843
+ `derivatives context backfill window failed batch=${batchIdx + 1}/${symbolBatches.length} interval=${interval} ${new Date(cursor).toISOString()}..${new Date(toMs).toISOString()}: ${error}`
3447
1844
  )
3448
1845
  );
3449
1846
  } finally {
3450
1847
  bar.tick(1, {
3451
1848
  batch: import_chalk2.default.gray(
3452
- `${batchIdx + 1}/${symbolBatches.length} ${interval2}`
1849
+ `${batchIdx + 1}/${symbolBatches.length} ${interval}`
3453
1850
  ),
3454
1851
  rows: totalRows,
3455
1852
  fail: failedWindows,
3456
1853
  skip: skippedWindows
3457
1854
  });
3458
1855
  }
3459
- cursor = toMs + intervalMs2;
1856
+ cursor = toMs + intervalMs;
3460
1857
  }
3461
1858
  }
3462
1859
  }
@@ -3494,7 +1891,8 @@ var backfillDerivativesContextForSignals = async (params) => backfillDerivatives
3494
1891
  // src/lib/coinMarketCapContextBackfill.ts
3495
1892
  var import_chalk3 = __toESM(require("chalk"));
3496
1893
  var import_async2 = require("@tradejs/core/async");
3497
- var import_timescale3 = require("@tradejs/infra/timescale");
1894
+ var import_marketContext2 = require("@tradejs/infra/timescale/marketContext");
1895
+ var import_client3 = require("@tradejs/infra/timescale/client");
3498
1896
  var import_userSettings2 = require("@tradejs/infra/userSettings");
3499
1897
  var DAY_MS3 = 864e5;
3500
1898
  var DEFAULT_CONTEXT_MAX_AGE_MS = 48 * 60 * 6e4;
@@ -3646,10 +2044,10 @@ var resolveCoinMarketCapBackfillWindow = (params) => {
3646
2044
  toMs: dayStartUtc(params.endMs)
3647
2045
  };
3648
2046
  };
3649
- var hasIntervalCoverage = (coverage, fromMs, toMs, intervalMs2) => {
2047
+ var hasIntervalCoverage = (coverage, fromMs, toMs, intervalMs) => {
3650
2048
  if (!coverage) return false;
3651
- const expectedRows = Math.max(1, Math.floor((toMs - fromMs) / intervalMs2));
3652
- return coverage.firstMs <= fromMs + intervalMs2 && coverage.lastMs >= toMs - intervalMs2 && coverage.rows >= Math.floor(expectedRows * 0.9);
2049
+ const expectedRows = Math.max(1, Math.floor((toMs - fromMs) / intervalMs));
2050
+ return coverage.firstMs <= fromMs + intervalMs && coverage.lastMs >= toMs - intervalMs && coverage.rows >= Math.floor(expectedRows * 0.9);
3653
2051
  };
3654
2052
  var hasDailyCoverage = (coverage, fromMs, toMs) => hasIntervalCoverage(coverage, fromMs, toMs, DAY_MS3);
3655
2053
  var coverageKey2 = (params) => [
@@ -3758,7 +2156,7 @@ var logBackfillSourceDone = (params) => {
3758
2156
  )
3759
2157
  );
3760
2158
  };
3761
- var markBackfillCoverage = (rows) => (0, import_timescale3.upsertMarketContextBackfillCoverage)(rows);
2159
+ var markBackfillCoverage = (rows) => (0, import_marketContext2.upsertMarketContextBackfillCoverage)(rows);
3762
2160
  var coinMarketCapFetch = async (params) => {
3763
2161
  const url = new URL(`${getBaseUrl()}${params.path}`);
3764
2162
  for (const [key, value] of Object.entries(params.searchParams)) {
@@ -3894,7 +2292,7 @@ var normalizeAssetDataItems = (payload) => {
3894
2292
  }
3895
2293
  return [];
3896
2294
  };
3897
- var coinMarketCapHistoricalQuotesPayloadToRows = (payload, interval2 = "1d") => {
2295
+ var coinMarketCapHistoricalQuotesPayloadToRows = (payload, interval = "1d") => {
3898
2296
  return normalizeAssetDataItems(payload).flatMap((asset) => {
3899
2297
  const cmcId = toIntOrNull(asset.id);
3900
2298
  const symbolRaw = String(asset.symbol ?? "").trim().toUpperCase();
@@ -3913,7 +2311,7 @@ var coinMarketCapHistoricalQuotesPayloadToRows = (payload, interval2 = "1d") =>
3913
2311
  source: SOURCE_REFERENCE,
3914
2312
  symbol: target.symbol,
3915
2313
  cmcId,
3916
- interval: interval2,
2314
+ interval,
3917
2315
  ts,
3918
2316
  openUsd: null,
3919
2317
  highUsd: null,
@@ -3925,7 +2323,7 @@ var coinMarketCapHistoricalQuotesPayloadToRows = (payload, interval2 = "1d") =>
3925
2323
  }).filter((row) => row != null);
3926
2324
  });
3927
2325
  };
3928
- var coinMarketCapExchangeQuotesPayloadToLiquidityRows = (payload, interval2 = "1d") => {
2326
+ var coinMarketCapExchangeQuotesPayloadToLiquidityRows = (payload, interval = "1d") => {
3929
2327
  const data = getRecord(payload).data;
3930
2328
  const exchangeItems = Array.isArray(data) ? data : Object.values(getRecord(data));
3931
2329
  const rowsByTs = /* @__PURE__ */ new Map();
@@ -3966,7 +2364,7 @@ var coinMarketCapExchangeQuotesPayloadToLiquidityRows = (payload, interval2 = "1
3966
2364
  );
3967
2365
  return {
3968
2366
  source: SOURCE_EXCHANGE_LIQUIDITY,
3969
- interval: interval2,
2367
+ interval,
3970
2368
  ts: new Date(ts),
3971
2369
  exchangesCount: exchanges.length,
3972
2370
  totalVolumeUsd,
@@ -4009,7 +2407,7 @@ var toCmcIndexWeightPct = (value) => {
4009
2407
  }
4010
2408
  return toFiniteNumberOrNull(value);
4011
2409
  };
4012
- var coinMarketCapIndexPayloadToRows = (payload, indexSlug, interval2 = "1d") => {
2410
+ var coinMarketCapIndexPayloadToRows = (payload, indexSlug, interval = "1d") => {
4013
2411
  const data = getRecord(payload).data;
4014
2412
  const items = Array.isArray(data) ? data : [];
4015
2413
  return items.map((item) => {
@@ -4038,7 +2436,7 @@ var coinMarketCapIndexPayloadToRows = (payload, indexSlug, interval2 = "1d") =>
4038
2436
  return {
4039
2437
  source: SOURCE_INDEX,
4040
2438
  indexSlug,
4041
- interval: interval2,
2439
+ interval,
4042
2440
  ts,
4043
2441
  value,
4044
2442
  constituentsCount: constituents.length,
@@ -4087,7 +2485,7 @@ var backfillCoinMarketCapContext = async (params) => {
4087
2485
  if (toMs <= fromMs) return skippedResult();
4088
2486
  const exchangeLiquidityEnabled = isExchangeLiquidityBackfillEnabled();
4089
2487
  const fearGreedEnabled = isFearGreedBackfillEnabled();
4090
- await (0, import_timescale3.waitForDbReady)();
2488
+ await (0, import_client3.waitForDbReady)();
4091
2489
  const [
4092
2490
  globalDailyCoverage,
4093
2491
  referenceDailyCoverage,
@@ -4100,66 +2498,66 @@ var backfillCoinMarketCapContext = async (params) => {
4100
2498
  fearGreedBackfillCoverage,
4101
2499
  indexBackfillCoverage
4102
2500
  ] = await Promise.all([
4103
- (0, import_timescale3.getMarketGlobalContextCoverage)({
2501
+ (0, import_marketContext2.getMarketGlobalContextCoverage)({
4104
2502
  source: SOURCE_GLOBAL_DAILY,
4105
2503
  startMs: fromMs,
4106
2504
  endMs: toMs
4107
2505
  }),
4108
- (0, import_timescale3.getMarketReferenceAssetContextCoverage)({
2506
+ (0, import_marketContext2.getMarketReferenceAssetContextCoverage)({
4109
2507
  source: SOURCE_REFERENCE,
4110
2508
  symbols: REFERENCE_ASSETS.map((item) => item.symbol),
4111
2509
  interval: "1d",
4112
2510
  startMs: fromMs,
4113
2511
  endMs: toMs
4114
2512
  }),
4115
- exchangeLiquidityEnabled ? (0, import_timescale3.getMarketCmcExchangeLiquidityContextCoverage)({
2513
+ exchangeLiquidityEnabled ? (0, import_marketContext2.getMarketCmcExchangeLiquidityContextCoverage)({
4116
2514
  source: SOURCE_EXCHANGE_LIQUIDITY,
4117
2515
  interval: "1d",
4118
2516
  startMs: fromMs,
4119
2517
  endMs: toMs
4120
2518
  }) : Promise.resolve(null),
4121
- fearGreedEnabled ? (0, import_timescale3.getMarketCmcFearGreedContextCoverage)({
2519
+ fearGreedEnabled ? (0, import_marketContext2.getMarketCmcFearGreedContextCoverage)({
4122
2520
  source: SOURCE_FEAR_GREED,
4123
2521
  interval: "1d",
4124
2522
  startMs: fromMs,
4125
2523
  endMs: toMs
4126
2524
  }) : Promise.resolve(null),
4127
- (0, import_timescale3.getMarketCmcIndexContextCoverage)({
2525
+ (0, import_marketContext2.getMarketCmcIndexContextCoverage)({
4128
2526
  source: SOURCE_INDEX,
4129
2527
  indexSlugs: CMC_INDEXES.map((index) => index.slug),
4130
2528
  interval: "1d",
4131
2529
  startMs: fromMs,
4132
2530
  endMs: toMs
4133
2531
  }),
4134
- (0, import_timescale3.getMarketContextBackfillCoverage)({
2532
+ (0, import_marketContext2.getMarketContextBackfillCoverage)({
4135
2533
  source: SOURCE_GLOBAL_DAILY,
4136
2534
  scopes: [COVERAGE_SCOPE_ALL],
4137
2535
  interval: "1d",
4138
2536
  fromMs,
4139
2537
  toMs
4140
2538
  }),
4141
- (0, import_timescale3.getMarketContextBackfillCoverage)({
2539
+ (0, import_marketContext2.getMarketContextBackfillCoverage)({
4142
2540
  source: SOURCE_REFERENCE,
4143
2541
  scopes: REFERENCE_ASSETS.map((item) => item.symbol),
4144
2542
  interval: "1d",
4145
2543
  fromMs,
4146
2544
  toMs
4147
2545
  }),
4148
- exchangeLiquidityEnabled ? (0, import_timescale3.getMarketContextBackfillCoverage)({
2546
+ exchangeLiquidityEnabled ? (0, import_marketContext2.getMarketContextBackfillCoverage)({
4149
2547
  source: SOURCE_EXCHANGE_LIQUIDITY,
4150
2548
  scopes: [COVERAGE_SCOPE_ALL],
4151
2549
  interval: "1d",
4152
2550
  fromMs,
4153
2551
  toMs
4154
2552
  }) : Promise.resolve([]),
4155
- fearGreedEnabled ? (0, import_timescale3.getMarketContextBackfillCoverage)({
2553
+ fearGreedEnabled ? (0, import_marketContext2.getMarketContextBackfillCoverage)({
4156
2554
  source: SOURCE_FEAR_GREED,
4157
2555
  scopes: [COVERAGE_SCOPE_ALL],
4158
2556
  interval: "1d",
4159
2557
  fromMs,
4160
2558
  toMs
4161
2559
  }) : Promise.resolve([]),
4162
- (0, import_timescale3.getMarketContextBackfillCoverage)({
2560
+ (0, import_marketContext2.getMarketContextBackfillCoverage)({
4163
2561
  source: SOURCE_INDEX,
4164
2562
  scopes: CMC_INDEXES.map((index) => index.slug),
4165
2563
  interval: "1d",
@@ -4350,7 +2748,7 @@ var backfillCoinMarketCapContext = async (params) => {
4350
2748
  }
4351
2749
  });
4352
2750
  const rows = coinMarketCapGlobalPayloadToRows(payload, SOURCE_GLOBAL_DAILY);
4353
- await (0, import_timescale3.upsertMarketGlobalContextRows)(rows);
2751
+ await (0, import_marketContext2.upsertMarketGlobalContextRows)(rows);
4354
2752
  await markBackfillCoverage([
4355
2753
  {
4356
2754
  source: SOURCE_GLOBAL_DAILY,
@@ -4384,7 +2782,7 @@ var backfillCoinMarketCapContext = async (params) => {
4384
2782
  }
4385
2783
  });
4386
2784
  const rows = coinMarketCapHistoricalQuotesPayloadToRows(payload, "1d");
4387
- await (0, import_timescale3.upsertMarketReferenceAssetContextRows)(rows);
2785
+ await (0, import_marketContext2.upsertMarketReferenceAssetContextRows)(rows);
4388
2786
  await markBackfillCoverage(
4389
2787
  REFERENCE_ASSETS.map((asset) => ({
4390
2788
  source: SOURCE_REFERENCE,
@@ -4423,7 +2821,7 @@ var backfillCoinMarketCapContext = async (params) => {
4423
2821
  payload,
4424
2822
  "1d"
4425
2823
  );
4426
- await (0, import_timescale3.upsertMarketCmcExchangeLiquidityContextRows)(rows);
2824
+ await (0, import_marketContext2.upsertMarketCmcExchangeLiquidityContextRows)(rows);
4427
2825
  await markBackfillCoverage([
4428
2826
  {
4429
2827
  source: SOURCE_EXCHANGE_LIQUIDITY,
@@ -4468,7 +2866,7 @@ var backfillCoinMarketCapContext = async (params) => {
4468
2866
  const oldestPageTs = Math.min(...pageRows.map((row) => row.ts.getTime()));
4469
2867
  if (oldestPageTs < fromMs || pageRows.length < pageSize) break;
4470
2868
  }
4471
- await (0, import_timescale3.upsertMarketCmcFearGreedContextRows)(rows);
2869
+ await (0, import_marketContext2.upsertMarketCmcFearGreedContextRows)(rows);
4472
2870
  await markBackfillCoverage([
4473
2871
  {
4474
2872
  source: SOURCE_FEAR_GREED,
@@ -4502,7 +2900,7 @@ var backfillCoinMarketCapContext = async (params) => {
4502
2900
  }))
4503
2901
  );
4504
2902
  const rows = rowsByIndex.flatMap((item) => item.result.rows);
4505
- await (0, import_timescale3.upsertMarketCmcIndexContextRows)(rows);
2903
+ await (0, import_marketContext2.upsertMarketCmcIndexContextRows)(rows);
4506
2904
  await markBackfillCoverage(
4507
2905
  rowsByIndex.map(({ index, result }) => ({
4508
2906
  source: SOURCE_INDEX,
@@ -4554,7 +2952,7 @@ var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapCo
4554
2952
 
4555
2953
  // src/lib/hyperliquidWhaleBackfill.ts
4556
2954
  var import_progress3 = __toESM(require("progress"));
4557
- var import_timescale4 = require("@tradejs/infra/timescale");
2955
+ var import_hyperliquidWhales = require("@tradejs/infra/timescale/hyperliquidWhales");
4558
2956
  var import_strategies2 = require("@tradejs/node/strategies");
4559
2957
 
4560
2958
  // src/lib/hyperliquidWhaleData.ts
@@ -4809,7 +3207,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4809
3207
  };
4810
3208
  const fromMs = Math.floor(params.startMs / HYPERLIQUID_WHALE_BUCKET_MS) * HYPERLIQUID_WHALE_BUCKET_MS;
4811
3209
  const toMs = minuteCeil(params.endMs);
4812
- const cached = await (0, import_timescale4.hasHyperliquidWhaleBackfillCoverage)({
3210
+ const cached = await (0, import_hyperliquidWhales.hasHyperliquidWhaleBackfillCoverage)({
4813
3211
  fromMs,
4814
3212
  toMs,
4815
3213
  ...identity
@@ -4858,7 +3256,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4858
3256
  items: whales.addresses,
4859
3257
  concurrency,
4860
3258
  worker: async (address) => {
4861
- const previous = await (0, import_timescale4.getHyperliquidWhaleWalletCoverage)({
3259
+ const previous = await (0, import_hyperliquidWhales.getHyperliquidWhaleWalletCoverage)({
4862
3260
  address,
4863
3261
  fromMs,
4864
3262
  toMs,
@@ -4885,8 +3283,8 @@ var backfillHyperliquidWhaleContext = async (params) => {
4885
3283
  identity
4886
3284
  })
4887
3285
  ).filter((row) => row != null);
4888
- await (0, import_timescale4.upsertHyperliquidWhaleTradeEvents)(addressEvents);
4889
- await (0, import_timescale4.upsertHyperliquidWhaleWalletCoverage)({
3286
+ await (0, import_hyperliquidWhales.upsertHyperliquidWhaleTradeEvents)(addressEvents);
3287
+ await (0, import_hyperliquidWhales.upsertHyperliquidWhaleWalletCoverage)({
4890
3288
  address,
4891
3289
  fromMs,
4892
3290
  toMs,
@@ -4904,7 +3302,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4904
3302
  const normalizedError = error instanceof Error ? error : new Error(String(error));
4905
3303
  failures.push(normalizedError);
4906
3304
  failedWallets += 1;
4907
- await (0, import_timescale4.upsertHyperliquidWhaleWalletCoverage)({
3305
+ await (0, import_hyperliquidWhales.upsertHyperliquidWhaleWalletCoverage)({
4908
3306
  address,
4909
3307
  fromMs,
4910
3308
  toMs,
@@ -4923,7 +3321,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4923
3321
  );
4924
3322
  }
4925
3323
  });
4926
- const buckets = await (0, import_timescale4.rebuildHyperliquidWhaleFlowRows)({
3324
+ const buckets = await (0, import_hyperliquidWhales.rebuildHyperliquidWhaleFlowRows)({
4927
3325
  fromMs,
4928
3326
  toMs,
4929
3327
  ...identity
@@ -4939,7 +3337,7 @@ var backfillHyperliquidWhaleContext = async (params) => {
4939
3337
  }
4940
3338
  );
4941
3339
  let displayedCoverageBuckets = 0;
4942
- const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
3340
+ const coverageBuckets = await (0, import_hyperliquidWhales.rebuildHyperliquidWhaleCoverageRows)({
4943
3341
  fromMs,
4944
3342
  toMs,
4945
3343
  expectedWhales: whales.addresses.length,
@@ -5139,17 +3537,17 @@ var prepareMarketContextForRun = async (params) => {
5139
3537
  const log = params.log ?? ((message) => {
5140
3538
  console.log(import_chalk4.default.gray(message));
5141
3539
  });
5142
- const timeOperation3 = (label, operation) => timeOperation(label, operation, log);
3540
+ const timeOperation2 = (label, operation) => timeOperation(label, operation, log);
5143
3541
  const requirements = await resolveMarketContextRunRequirements(params);
5144
3542
  const readableSources = Object.entries(requirements).filter(([, requirement]) => requirement.read).map(([source]) => source);
5145
3543
  if (readableSources.length) {
5146
- await timeOperation3(
3544
+ await timeOperation2(
5147
3545
  "market context schema ensure",
5148
- () => (0, import_timescale5.ensureMarketContextSchemas)(readableSources)
3546
+ () => (0, import_marketContext3.ensureMarketContextSchemas)(readableSources)
5149
3547
  );
5150
3548
  }
5151
3549
  if (requirements.derivatives.backfill) {
5152
- await timeOperation3(
3550
+ await timeOperation2(
5153
3551
  "derivatives context backfill",
5154
3552
  () => (params.mode === "signals" ? backfillDerivativesContextForSignals : backfillDerivativesContextForBacktest)(
5155
3553
  buildDerivativesBackfillParams(params)
@@ -5157,7 +3555,7 @@ var prepareMarketContextForRun = async (params) => {
5157
3555
  );
5158
3556
  }
5159
3557
  if (requirements.hyperliquidWhales.backfill) {
5160
- await timeOperation3(
3558
+ await timeOperation2(
5161
3559
  "hyperliquid whale context backfill",
5162
3560
  () => backfillHyperliquidWhaleContext({
5163
3561
  startMs: params.preloadStartMs ?? params.startMs,
@@ -5169,13 +3567,13 @@ var prepareMarketContextForRun = async (params) => {
5169
3567
  );
5170
3568
  }
5171
3569
  if (requirements.binance.backfill) {
5172
- await timeOperation3("binance market context backfill", () => {
3570
+ await timeOperation2("binance market context backfill", () => {
5173
3571
  const backfill = params.mode === "backtest" ? backfillBinanceMarketContextForBacktest : params.mode === "signals" ? backfillBinanceMarketContextForSignals : backfillBinanceMarketContextForReplay;
5174
3572
  return backfill(buildBinanceMarketBackfillParams(params));
5175
3573
  });
5176
3574
  }
5177
3575
  if (requirements.coinmarketcap.backfill) {
5178
- await timeOperation3(
3576
+ await timeOperation2(
5179
3577
  "coinmarketcap historical context backfill",
5180
3578
  () => resolveCoinMarketCapBackfillForMode(params.mode)(
5181
3579
  buildCoinMarketCapBackfillParams(params)
@@ -5197,7 +3595,7 @@ var loadBtcReferenceConnectors = async ({
5197
3595
  connectorName,
5198
3596
  marketConnector,
5199
3597
  userName,
5200
- projectRoot: projectRoot2,
3598
+ projectRoot,
5201
3599
  shouldUseDedicatedReferences,
5202
3600
  requireDedicatedReferences = false,
5203
3601
  warn
@@ -5209,8 +3607,8 @@ var loadBtcReferenceConnectors = async ({
5209
3607
  };
5210
3608
  }
5211
3609
  const [binanceFactory, coinbaseFactory] = await Promise.all([
5212
- (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance, projectRoot2),
5213
- (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase, projectRoot2)
3610
+ (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance, projectRoot),
3611
+ (0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase, projectRoot)
5214
3612
  ]);
5215
3613
  const binance = binanceFactory ? await binanceFactory({ userName }) : marketConnector;
5216
3614
  if (!binanceFactory) {
@@ -5232,7 +3630,7 @@ var updateMarketHistoryWithBtcReferences = async ({
5232
3630
  marketConnector,
5233
3631
  connectorName,
5234
3632
  btcReferences,
5235
- interval: interval2,
3633
+ interval,
5236
3634
  symbols,
5237
3635
  preloadDays,
5238
3636
  preloadStart,
@@ -5243,7 +3641,7 @@ var updateMarketHistoryWithBtcReferences = async ({
5243
3641
  await updatePrimaryMarketHistory({
5244
3642
  marketConnector,
5245
3643
  connectorName,
5246
- interval: interval2,
3644
+ interval,
5247
3645
  symbols,
5248
3646
  preloadDays,
5249
3647
  preloadStart,
@@ -5254,7 +3652,7 @@ var updateMarketHistoryWithBtcReferences = async ({
5254
3652
  await updateBtcReferenceHistory({
5255
3653
  marketConnector,
5256
3654
  btcReferences,
5257
- interval: interval2,
3655
+ interval,
5258
3656
  preloadDays,
5259
3657
  preloadStart,
5260
3658
  preloadEnd,
@@ -5265,7 +3663,7 @@ var updateMarketHistoryWithBtcReferences = async ({
5265
3663
  var updatePrimaryMarketHistory = async ({
5266
3664
  marketConnector,
5267
3665
  connectorName,
5268
- interval: interval2,
3666
+ interval,
5269
3667
  symbols,
5270
3668
  preloadDays,
5271
3669
  preloadStart,
@@ -5274,7 +3672,7 @@ var updatePrimaryMarketHistory = async ({
5274
3672
  universe = marketConnector.universe ?? "crypto"
5275
3673
  }) => {
5276
3674
  if (!symbols.length) return;
5277
- const timeOperation3 = (label, operation) => timeOperation(
3675
+ const timeOperation2 = (label, operation) => timeOperation(
5278
3676
  label,
5279
3677
  operation,
5280
3678
  log ?? ((message) => console.log(import_chalk5.default.gray(message)))
@@ -5284,11 +3682,11 @@ var updatePrimaryMarketHistory = async ({
5284
3682
  ...preloadStart != null ? { preloadStart } : {},
5285
3683
  ...preloadEnd != null ? { preloadEnd } : {}
5286
3684
  } : { connectorLabel: connectorName };
5287
- await timeOperation3(
3685
+ await timeOperation2(
5288
3686
  `update ${connectorName}`,
5289
3687
  () => (0, import_cli.update)(
5290
3688
  marketConnector,
5291
- interval2,
3689
+ interval,
5292
3690
  universe === "crypto" ? withPrimaryMarketReferenceSymbols(symbols) : symbols,
5293
3691
  preloadDays,
5294
3692
  updateOptions
@@ -5298,7 +3696,7 @@ var updatePrimaryMarketHistory = async ({
5298
3696
  var updateBtcReferenceHistory = async ({
5299
3697
  marketConnector,
5300
3698
  btcReferences,
5301
- interval: interval2,
3699
+ interval,
5302
3700
  preloadDays,
5303
3701
  preloadStart,
5304
3702
  preloadEnd,
@@ -5306,7 +3704,7 @@ var updateBtcReferenceHistory = async ({
5306
3704
  universe = marketConnector.universe ?? "crypto"
5307
3705
  }) => {
5308
3706
  if (universe !== "crypto") return;
5309
- const timeOperation3 = (label, operation) => timeOperation(
3707
+ const timeOperation2 = (label, operation) => timeOperation(
5310
3708
  label,
5311
3709
  operation,
5312
3710
  log ?? ((message) => console.log(import_chalk5.default.gray(message)))
@@ -5323,9 +3721,9 @@ var updateBtcReferenceHistory = async ({
5323
3721
  ...preloadStart != null ? { preloadStart } : {},
5324
3722
  ...preloadEnd != null ? { preloadEnd } : {}
5325
3723
  } : { connectorLabel };
5326
- await timeOperation3(
3724
+ await timeOperation2(
5327
3725
  `update ${connectorLabel}`,
5328
- () => (0, import_cli.update)(connector, interval2, ["BTCUSDT"], preloadDays, referenceOptions)
3726
+ () => (0, import_cli.update)(connector, interval, ["BTCUSDT"], preloadDays, referenceOptions)
5329
3727
  );
5330
3728
  };
5331
3729
  await updateReference({
@@ -5341,79 +3739,33 @@ var updateBtcReferenceHistory = async ({
5341
3739
  // src/lib/signals/runtimeStrategies.ts
5342
3740
  var import_logger = require("@tradejs/infra/logger");
5343
3741
  var import_redis2 = require("@tradejs/infra/redis");
5344
- var import_tradingAccounts = require("@tradejs/infra/tradingAccounts");
5345
- var import_strategies3 = require("@tradejs/node/strategies");
5346
-
5347
- // src/lib/runtimeRedis.ts
5348
- var import_redis = require("@tradejs/infra/redis");
5349
- var import_time = require("@tradejs/core/time");
5350
- var RESERVED_STRATEGY_NAMES = /* @__PURE__ */ new Set(["charts"]);
5351
- var RESERVED_CONFIG_IDS = /* @__PURE__ */ new Set(["results"]);
5352
- var resolveStrategyConfigIdentityByKey = (userName, key) => {
5353
- const parts = key.split(":");
5354
- if (parts.length !== 5) return null;
5355
- const [users, keyUserName, strategiesKey, strategyName, configId] = parts;
5356
- 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)) {
5357
- return null;
5358
- }
5359
- return { strategyName, configId };
5360
- };
5361
- var isRuntimeStrategyEnabled = (strategyConfig) => {
5362
- const enabled = strategyConfig.ENABLE;
5363
- return enabled !== false;
5364
- };
5365
- var resolveStrategyNameByConfigKey = (userName, key) => {
5366
- return resolveStrategyConfigIdentityByKey(userName, key)?.strategyName ?? null;
5367
- };
5368
- var getRuntimeStrategyConfigKeys = async (userName) => {
5369
- const keys = await (0, import_redis.getKeys)(`${import_redis.redisKeys.strategies(userName)}:`);
5370
- return keys.filter((key) => resolveStrategyConfigIdentityByKey(userName, key)).sort((left, right) => left.localeCompare(right));
5371
- };
5372
- var loadRuntimeStrategyConfigs = async (userName, {
5373
- onInvalidConfig
5374
- } = {}) => {
5375
- const configKeys = await getRuntimeStrategyConfigKeys(userName);
5376
- const strategyConfigs = await Promise.all(
5377
- configKeys.map(async (key) => {
5378
- const strategyName = resolveStrategyNameByConfigKey(userName, key);
5379
- const identity = resolveStrategyConfigIdentityByKey(userName, key);
5380
- if (!strategyName || !identity) {
5381
- return null;
5382
- }
5383
- const strategyConfig = await (0, import_redis.getData)(
5384
- key,
5385
- null
5386
- );
5387
- if (!strategyConfig || typeof strategyConfig !== "object" || Array.isArray(strategyConfig)) {
5388
- onInvalidConfig?.(key);
5389
- return null;
5390
- }
5391
- return {
5392
- key,
5393
- strategyName,
5394
- configId: identity.configId,
5395
- strategyConfig
5396
- };
5397
- })
5398
- );
5399
- return strategyConfigs.filter(Boolean);
3742
+ var import_tradingAccounts = require("@tradejs/infra/tradingAccounts");
3743
+ var import_strategies3 = require("@tradejs/node/strategies");
3744
+
3745
+ // src/lib/runtimeRedis.ts
3746
+ var import_redis = require("@tradejs/infra/redis");
3747
+ var import_time = require("@tradejs/core/time");
3748
+ var import_runtimeStrategyConfigs = require("@tradejs/infra/runtimeStrategyConfigs");
3749
+ var isRuntimeStrategyEnabled = (strategyConfig) => {
3750
+ const enabled = strategyConfig.ENABLE;
3751
+ return enabled !== false;
5400
3752
  };
5401
3753
 
5402
3754
  // src/lib/signals/runtimeStrategies.ts
5403
3755
  var loadRuntimeStrategies = async ({
5404
3756
  userName,
5405
- projectRoot: projectRoot2,
3757
+ projectRoot,
5406
3758
  deployment,
5407
3759
  connectorName = "bybit",
5408
3760
  universe,
5409
3761
  accountId,
5410
- interval: interval2
3762
+ interval
5411
3763
  }) => {
5412
3764
  const deploymentStrategies = new Map(
5413
3765
  (deployment?.strategies ?? []).filter(({ enabled }) => enabled !== false).map((strategy) => [strategy.strategyName, strategy])
5414
3766
  );
5415
3767
  const strategyConfigs = await Promise.all(
5416
- (await loadRuntimeStrategyConfigs(userName)).map(
3768
+ (await (0, import_runtimeStrategyConfigs.loadRuntimeStrategyConfigs)(userName)).map(
5417
3769
  async ({
5418
3770
  key,
5419
3771
  strategyName,
@@ -5442,7 +3794,7 @@ var loadRuntimeStrategies = async ({
5442
3794
  });
5443
3795
  const effectiveAccountId = resolvedAccount?.id ?? requestedAccountId;
5444
3796
  const [strategyCreator, strategyResults] = await Promise.all([
5445
- (0, import_strategies3.getStrategyCreator)(strategyName, projectRoot2),
3797
+ (0, import_strategies3.getStrategyCreator)(strategyName, projectRoot),
5446
3798
  (0, import_redis2.getData)(import_redis2.redisKeys.strategyResults(userName, strategyName), {})
5447
3799
  ]);
5448
3800
  if (!strategyCreator) {
@@ -5483,7 +3835,7 @@ var loadRuntimeStrategies = async ({
5483
3835
  byStrategyAndAccount.set(conflictKey, candidate);
5484
3836
  }
5485
3837
  return active.filter(
5486
- (candidate) => (!universe || candidate.universe === universe) && (!interval2 || String(candidate.interval) === String(interval2)) && (!accountId || candidate.accountId === accountId)
3838
+ (candidate) => (!universe || candidate.universe === universe) && (!interval || String(candidate.interval) === String(interval)) && (!accountId || candidate.accountId === accountId)
5487
3839
  );
5488
3840
  };
5489
3841
 
@@ -5699,11 +4051,11 @@ var normalizeForStableJson = (value) => {
5699
4051
  }
5700
4052
  return value;
5701
4053
  };
5702
- var resolveRuntimeMaxLossValue = (config) => {
5703
- if (!config || typeof config !== "object" || Array.isArray(config)) {
4054
+ var resolveRuntimeMaxLossValue = (config2) => {
4055
+ if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) {
5704
4056
  return null;
5705
4057
  }
5706
- const strategyConfig = config.strategyConfig;
4058
+ const strategyConfig = config2.strategyConfig;
5707
4059
  if (!strategyConfig || typeof strategyConfig !== "object" || Array.isArray(strategyConfig)) {
5708
4060
  return null;
5709
4061
  }
@@ -5717,8 +4069,8 @@ var gitLineageCache = /* @__PURE__ */ new Map();
5717
4069
  var gateFingerprintCache = /* @__PURE__ */ new Map();
5718
4070
  var binanceBreadthFingerprintCache = /* @__PURE__ */ new Map();
5719
4071
  var snapshotFingerprintCache = /* @__PURE__ */ new Map();
5720
- var resolveGitLineage = (projectRoot2) => {
5721
- const cached = gitLineageCache.get(projectRoot2);
4072
+ var resolveGitLineage = (projectRoot) => {
4073
+ const cached = gitLineageCache.get(projectRoot);
5722
4074
  if (cached) {
5723
4075
  return cached;
5724
4076
  }
@@ -5728,12 +4080,12 @@ var resolveGitLineage = (projectRoot2) => {
5728
4080
  gitSha: envSha,
5729
4081
  gitDirty: false
5730
4082
  };
5731
- gitLineageCache.set(projectRoot2, result);
4083
+ gitLineageCache.set(projectRoot, result);
5732
4084
  return result;
5733
4085
  }
5734
4086
  try {
5735
4087
  const gitSha = (0, import_node_child_process.execFileSync)("git", ["rev-parse", "HEAD"], {
5736
- cwd: projectRoot2,
4088
+ cwd: projectRoot,
5737
4089
  encoding: "utf8",
5738
4090
  stdio: ["ignore", "pipe", "ignore"]
5739
4091
  }).trim();
@@ -5741,7 +4093,7 @@ var resolveGitLineage = (projectRoot2) => {
5741
4093
  "git",
5742
4094
  ["status", "--porcelain", "--untracked-files=normal"],
5743
4095
  {
5744
- cwd: projectRoot2,
4096
+ cwd: projectRoot,
5745
4097
  encoding: "utf8",
5746
4098
  stdio: ["ignore", "pipe", "ignore"]
5747
4099
  }
@@ -5750,14 +4102,14 @@ var resolveGitLineage = (projectRoot2) => {
5750
4102
  gitSha: gitSha || null,
5751
4103
  gitDirty: status.length > 0
5752
4104
  };
5753
- gitLineageCache.set(projectRoot2, result);
4105
+ gitLineageCache.set(projectRoot, result);
5754
4106
  return result;
5755
4107
  } catch {
5756
4108
  const result = {
5757
4109
  gitSha: null,
5758
4110
  gitDirty: null
5759
4111
  };
5760
- gitLineageCache.set(projectRoot2, result);
4112
+ gitLineageCache.set(projectRoot, result);
5761
4113
  return result;
5762
4114
  }
5763
4115
  };
@@ -5768,13 +4120,13 @@ var readOptionalFile = async (filePath) => {
5768
4120
  return null;
5769
4121
  }
5770
4122
  };
5771
- var resolveBinanceBreadthFingerprint = async (projectRoot2) => {
5772
- if (binanceBreadthFingerprintCache.has(projectRoot2)) {
5773
- return binanceBreadthFingerprintCache.get(projectRoot2) ?? null;
4123
+ var resolveBinanceBreadthFingerprint = async (projectRoot) => {
4124
+ if (binanceBreadthFingerprintCache.has(projectRoot)) {
4125
+ return binanceBreadthFingerprintCache.get(projectRoot) ?? null;
5774
4126
  }
5775
4127
  const content = await readOptionalFile(
5776
4128
  import_node_path.default.join(
5777
- projectRoot2,
4129
+ projectRoot,
5778
4130
  "packages/node/src/config/binanceBreadthUniverses.json"
5779
4131
  )
5780
4132
  );
@@ -5787,15 +4139,15 @@ var resolveBinanceBreadthFingerprint = async (projectRoot2) => {
5787
4139
  result = null;
5788
4140
  }
5789
4141
  }
5790
- binanceBreadthFingerprintCache.set(projectRoot2, result);
4142
+ binanceBreadthFingerprintCache.set(projectRoot, result);
5791
4143
  return result;
5792
4144
  };
5793
- var resolveSnapshotFingerprint = async (projectRoot2, relativePath) => {
5794
- const cacheKey = `${projectRoot2}:${relativePath}`;
4145
+ var resolveSnapshotFingerprint = async (projectRoot, relativePath) => {
4146
+ const cacheKey = `${projectRoot}:${relativePath}`;
5795
4147
  if (snapshotFingerprintCache.has(cacheKey)) {
5796
4148
  return snapshotFingerprintCache.get(cacheKey) ?? null;
5797
4149
  }
5798
- const content = await readOptionalFile(import_node_path.default.join(projectRoot2, relativePath));
4150
+ const content = await readOptionalFile(import_node_path.default.join(projectRoot, relativePath));
5799
4151
  let result = null;
5800
4152
  if (content) {
5801
4153
  try {
@@ -5809,11 +4161,11 @@ var resolveSnapshotFingerprint = async (projectRoot2, relativePath) => {
5809
4161
  return result;
5810
4162
  };
5811
4163
  var resolveGateFingerprint = async ({
5812
- projectRoot: projectRoot2,
4164
+ projectRoot,
5813
4165
  strategyName,
5814
4166
  gitSha
5815
4167
  }) => {
5816
- const cacheKey = `${projectRoot2}:${strategyName}:${gitSha ?? "unknown"}`;
4168
+ const cacheKey = `${projectRoot}:${strategyName}:${gitSha ?? "unknown"}`;
5817
4169
  const cached = gateFingerprintCache.get(cacheKey);
5818
4170
  if (cached) {
5819
4171
  return cached;
@@ -5829,7 +4181,7 @@ var resolveGateFingerprint = async ({
5829
4181
  const optionalEntries = await Promise.all(
5830
4182
  relativeCandidates.map(async (relativePath) => {
5831
4183
  const content = await readOptionalFile(
5832
- import_node_path.default.join(projectRoot2, relativePath)
4184
+ import_node_path.default.join(projectRoot, relativePath)
5833
4185
  );
5834
4186
  return content == null ? null : { relativePath, content };
5835
4187
  })
@@ -5855,19 +4207,19 @@ var resolveGateFingerprint = async ({
5855
4207
  return fingerprint;
5856
4208
  };
5857
4209
  var buildRuntimeLineage = async ({
5858
- projectRoot: projectRoot2,
4210
+ projectRoot,
5859
4211
  strategyName,
5860
- config,
4212
+ config: config2,
5861
4213
  runContext,
5862
4214
  env = process.env
5863
4215
  }) => {
5864
- const git = resolveGitLineage(projectRoot2);
4216
+ const git = resolveGitLineage(projectRoot);
5865
4217
  const hyperliquidPerpUniverseFingerprint = typeof import_strategies4.getHyperliquidPerpUniverseSnapshot === "function" ? (0, import_strategies4.getHyperliquidPerpUniverseSnapshot)().fingerprint : await resolveSnapshotFingerprint(
5866
- projectRoot2,
4218
+ projectRoot,
5867
4219
  "packages/node/src/config/hyperliquidPerpUniverse.json"
5868
4220
  );
5869
4221
  const hyperliquidWhaleRegistryFingerprint = typeof import_strategies4.getHyperliquidWhaleRegistrySnapshot === "function" ? (0, import_strategies4.getHyperliquidWhaleRegistrySnapshot)().fingerprint : await resolveSnapshotFingerprint(
5870
- projectRoot2,
4222
+ projectRoot,
5871
4223
  "packages/node/src/config/hyperliquidWhales.json"
5872
4224
  );
5873
4225
  const context = {
@@ -5875,7 +4227,7 @@ var buildRuntimeLineage = async ({
5875
4227
  RUNTIME_CONTEXT_ENV_KEYS.map((key) => [key, env[key] ?? null])
5876
4228
  ),
5877
4229
  ...RUNTIME_CONTEXT_DATA_MODEL,
5878
- binanceBreadthUniverseFingerprint: await resolveBinanceBreadthFingerprint(projectRoot2),
4230
+ binanceBreadthUniverseFingerprint: await resolveBinanceBreadthFingerprint(projectRoot),
5879
4231
  hyperliquidPerpUniverseFingerprint,
5880
4232
  hyperliquidWhaleRegistryFingerprint,
5881
4233
  ...runContext
@@ -5884,13 +4236,13 @@ var buildRuntimeLineage = async ({
5884
4236
  schemaVersion: 1,
5885
4237
  ...git,
5886
4238
  gateFingerprint: await resolveGateFingerprint({
5887
- projectRoot: projectRoot2,
4239
+ projectRoot,
5888
4240
  strategyName,
5889
4241
  gitSha: git.gitSha
5890
4242
  }),
5891
- configFingerprint: fingerprintRuntimeValue(config),
4243
+ configFingerprint: fingerprintRuntimeValue(config2),
5892
4244
  contextFingerprint: fingerprintRuntimeValue(context),
5893
- maxLossValue: resolveRuntimeMaxLossValue(config)
4245
+ maxLossValue: resolveRuntimeMaxLossValue(config2)
5894
4246
  };
5895
4247
  };
5896
4248
  var runtimeLineageKey = (lineage) => [
@@ -6080,23 +4432,6 @@ var getTelegramDeliverableSignals = (signals2) => signals2.filter(
6080
4432
  (signal) => signal.orderStatus !== "skipped" && signal.orderStatus !== "canceled"
6081
4433
  );
6082
4434
 
6083
- // src/lib/runtimeModeConfig.ts
6084
- var buildRuntimeModeStrategyConfig = ({
6085
- strategyConfig,
6086
- env,
6087
- interval: interval2,
6088
- makeOrders,
6089
- recordRuntimeTrades,
6090
- aiReplayAnalyses
6091
- }) => ({
6092
- ...strategyConfig,
6093
- ENV: env,
6094
- MAKE_ORDERS: makeOrders,
6095
- INTERVAL: interval2,
6096
- ...typeof recordRuntimeTrades === "boolean" ? { RECORD_RUNTIME_TRADES: recordRuntimeTrades } : {},
6097
- ...aiReplayAnalyses?.length ? { AI_REPLAY_ANALYSES: aiReplayAnalyses } : {}
6098
- });
6099
-
6100
4435
  // src/lib/signals/runtimeLifecycle.ts
6101
4436
  var stableStringify = (value) => {
6102
4437
  if (value == null || typeof value !== "object") {
@@ -6114,13 +4449,13 @@ var buildSignalsStrategyLifecycleKey = ({
6114
4449
  accountId,
6115
4450
  deploymentId,
6116
4451
  symbol,
6117
- interval: interval2,
4452
+ interval,
6118
4453
  strategyName,
6119
4454
  configId
6120
4455
  }) => {
6121
4456
  const namedConfigId = configId && configId !== "config" ? configId : void 0;
6122
4457
  if (!universe && !accountId && !deploymentId) {
6123
- return [connectorName, symbol, interval2, strategyName, namedConfigId].filter(Boolean).join(":");
4458
+ return [connectorName, symbol, interval, strategyName, namedConfigId].filter(Boolean).join(":");
6124
4459
  }
6125
4460
  return [
6126
4461
  connectorName,
@@ -6128,17 +4463,17 @@ var buildSignalsStrategyLifecycleKey = ({
6128
4463
  accountId ?? "default",
6129
4464
  deploymentId ?? "default",
6130
4465
  symbol,
6131
- interval2,
4466
+ interval,
6132
4467
  strategyName,
6133
4468
  namedConfigId
6134
4469
  ].filter(Boolean).join(":");
6135
4470
  };
6136
4471
  var createSignalsStrategyLifecycle = ({
6137
- intervalMs: intervalMs2,
4472
+ intervalMs,
6138
4473
  maxLiveBars,
6139
4474
  releaseState = () => void 0
6140
4475
  }) => {
6141
- if (!Number.isFinite(intervalMs2) || intervalMs2 <= 0) {
4476
+ if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
6142
4477
  throw new Error("Signals strategy lifecycle requires a positive interval");
6143
4478
  }
6144
4479
  if (!Number.isFinite(maxLiveBars) || maxLiveBars <= 0) {
@@ -6149,7 +4484,7 @@ var createSignalsStrategyLifecycle = ({
6149
4484
  const evaluate = async ({
6150
4485
  key,
6151
4486
  timestamp,
6152
- config,
4487
+ config: config2,
6153
4488
  btcBinanceData,
6154
4489
  btcCoinbaseData,
6155
4490
  onRuntimeClose,
@@ -6159,7 +4494,7 @@ var createSignalsStrategyLifecycle = ({
6159
4494
  if (!Number.isFinite(timestamp)) {
6160
4495
  throw new Error(`Signals strategy lifecycle received ${timestamp}`);
6161
4496
  }
6162
- const configFingerprint = stableStringify(config);
4497
+ const configFingerprint = stableStringify(config2);
6163
4498
  const current = entries.get(key);
6164
4499
  if (current) {
6165
4500
  if (timestamp === current.lastTimestamp) {
@@ -6172,7 +4507,7 @@ var createSignalsStrategyLifecycle = ({
6172
4507
  let action = "created";
6173
4508
  if (current && current.configFingerprint !== configFingerprint) {
6174
4509
  action = "rebuilt_config";
6175
- } else if (current && timestamp !== current.lastTimestamp + intervalMs2) {
4510
+ } else if (current && timestamp !== current.lastTimestamp + intervalMs) {
6176
4511
  action = "rebuilt_gap";
6177
4512
  } else if (current && current.processedBars >= normalizedMaxLiveBars) {
6178
4513
  action = "rebuilt_limit";
@@ -6228,18 +4563,18 @@ var createSignalsStrategyLifecycle = ({
6228
4563
  // src/lib/signals/daemon.ts
6229
4564
  var getNextSignalsCycleDelay = ({
6230
4565
  now,
6231
- intervalMs: intervalMs2,
4566
+ intervalMs,
6232
4567
  settleDelayMs
6233
4568
  }) => {
6234
- const nextBoundary = (Math.floor(now / intervalMs2) + 1) * intervalMs2;
4569
+ const nextBoundary = (Math.floor(now / intervalMs) + 1) * intervalMs;
6235
4570
  return Math.max(0, nextBoundary + settleDelayMs - now);
6236
4571
  };
6237
4572
  var getCurrentSignalsCycleDelay = ({
6238
4573
  now,
6239
- intervalMs: intervalMs2,
4574
+ intervalMs,
6240
4575
  settleDelayMs
6241
4576
  }) => {
6242
- const currentBoundary = Math.floor(now / intervalMs2) * intervalMs2;
4577
+ const currentBoundary = Math.floor(now / intervalMs) * intervalMs;
6243
4578
  return Math.max(0, currentBoundary + settleDelayMs - now);
6244
4579
  };
6245
4580
  var getSignalsHeartbeatStatus = ({
@@ -6266,7 +4601,7 @@ var waitForNextCycle = (delayMs, signal) => new Promise((resolve) => {
6266
4601
  });
6267
4602
  var runSignalsDaemon = async ({
6268
4603
  runCycle,
6269
- intervalMs: intervalMs2,
4604
+ intervalMs,
6270
4605
  settleDelayMs,
6271
4606
  signal,
6272
4607
  onCycleError,
@@ -6275,7 +4610,7 @@ var runSignalsDaemon = async ({
6275
4610
  }) => {
6276
4611
  const initialDelay = getCurrentSignalsCycleDelay({
6277
4612
  now: now(),
6278
- intervalMs: intervalMs2,
4613
+ intervalMs,
6279
4614
  settleDelayMs
6280
4615
  });
6281
4616
  if (initialDelay > 0) {
@@ -6285,7 +4620,7 @@ var runSignalsDaemon = async ({
6285
4620
  const cycleStartedAt = now();
6286
4621
  const nextCycleAt = cycleStartedAt + getNextSignalsCycleDelay({
6287
4622
  now: cycleStartedAt,
6288
- intervalMs: intervalMs2,
4623
+ intervalMs,
6289
4624
  settleDelayMs
6290
4625
  });
6291
4626
  try {
@@ -6303,7 +4638,7 @@ var runSignalsDaemon = async ({
6303
4638
  // src/lib/signals/klineFeed.ts
6304
4639
  var import_connectors5 = require("@tradejs/connectors");
6305
4640
  var import_logger3 = require("@tradejs/infra/logger");
6306
- var import_timescale6 = require("@tradejs/infra/timescale");
4641
+ var import_candles = require("@tradejs/infra/timescale/candles");
6307
4642
 
6308
4643
  // src/lib/marketData/klineEvents.ts
6309
4644
  var import_ioredis = __toESM(require("ioredis"));
@@ -6317,15 +4652,15 @@ var normalizeSymbols2 = (symbols) => [...new Set(symbols.map((symbol) => symbol.
6317
4652
  Boolean
6318
4653
  );
6319
4654
  var createSignalsKlineFeed = async ({
6320
- config,
6321
- interval: interval2,
4655
+ config: config2,
4656
+ interval,
6322
4657
  universe,
6323
4658
  publish = publishMarketKlineEvent,
6324
4659
  persist = async (rows) => {
6325
- const intervalMinutes = Number(interval2);
6326
- await (0, import_timescale6.upsertCandles)(
4660
+ const intervalMinutes = Number(interval);
4661
+ await (0, import_candles.upsertCandles)(
6327
4662
  rows.flatMap(
6328
- ({ symbol, candle }) => (0, import_timescale6.toRows)("bybit", symbol, intervalMinutes, [candle])
4663
+ ({ symbol, candle }) => (0, import_candles.toRows)("bybit", symbol, intervalMinutes, [candle])
6329
4664
  )
6330
4665
  );
6331
4666
  },
@@ -6368,14 +4703,14 @@ var createSignalsKlineFeed = async ({
6368
4703
  }, FLUSH_DELAY_MS);
6369
4704
  };
6370
4705
  const stream = await streamFactory({
6371
- config,
4706
+ config: config2,
6372
4707
  onEvent: (event) => {
6373
- if (event.interval !== interval2) return;
4708
+ if (event.interval !== interval) return;
6374
4709
  void publish({
6375
4710
  provider: "bybit",
6376
4711
  universe,
6377
4712
  symbol: event.symbol,
6378
- interval: interval2,
4713
+ interval,
6379
4714
  candle: event.candle,
6380
4715
  confirm: event.confirm,
6381
4716
  receivedAt: event.receivedAt
@@ -6394,7 +4729,7 @@ var createSignalsKlineFeed = async ({
6394
4729
  });
6395
4730
  return {
6396
4731
  setSubscriptions: (symbols) => {
6397
- stream.setSubscriptions(normalizeSymbols2(symbols), interval2);
4732
+ stream.setSubscriptions(normalizeSymbols2(symbols), interval);
6398
4733
  },
6399
4734
  waitForClosed: async ({ symbols, timestamp, timeoutMs, signal }) => {
6400
4735
  const expected = normalizeSymbols2(symbols);
@@ -6432,197 +4767,82 @@ var createSignalsKlineFeed = async ({
6432
4767
  };
6433
4768
  };
6434
4769
 
6435
- // src/scripts/signals.ts
6436
- import_args.default.option(["t", "tickers"], "Selected tickers");
6437
- import_args.default.option(["e", "exclude"], "Exclude tickers from tests");
6438
- import_args.default.option(["l", "tickersLimit"], "Tickers limit");
6439
- import_args.default.option(["f", "timeframe"], "Timeframe", 15);
6440
- import_args.default.option(["m", "makeOrders"], "Make orders");
6441
- import_args.default.option(["N", "notify"], "Send message in Telegram", false);
6442
- import_args.default.option(["S", "skipScreenshots"], "Skip screenshot generation", false);
6443
- import_args.default.option(["u", "updateOnly"], "Only update tickers history", false);
6444
- import_args.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
6445
- import_args.default.option(["L", "showTickersList"], "Just show only ticker list", false);
6446
- import_args.default.option(
6447
- ["p", "parallel"],
6448
- "Signal evaluation worker count",
6449
- Number(process.env.SIGNALS_PARALLEL || 4)
6450
- );
6451
- import_args.default.option(
6452
- ["R", "showSkipStats"],
6453
- "Show aggregated skip stats by strategy",
6454
- false
6455
- );
6456
- import_args.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
6457
- import_args.default.option(["U", "user"], "Use user confg", "root");
6458
- import_args.default.option(["w", "watch"], "Keep signals running on candle boundaries", false);
6459
- import_args.default.option(
6460
- ["d", "settleDelayMs"],
6461
- "Delay after candle close before a daemon cycle",
6462
- Number(process.env.SIGNALS_DAEMON_SETTLE_DELAY_MS || 5e3)
6463
- );
6464
- import_args.default.option(
6465
- ["o", "connector"],
6466
- "Connector provider or name for signals (e.g. bybit, binance, coinbase, custom)",
6467
- "bybit"
6468
- );
6469
- import_args.default.option(["V", "universe"], "Market universe (crypto or tradfi)", "crypto");
6470
- import_args.default.option(["A", "account"], "Trading account id");
6471
- import_args.default.option(["D", "deployment"], "Runtime deployment id");
6472
- var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
6473
- var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
6474
- var flags = import_args.default.parse(process.argv);
6475
- var interval = flags.timeframe.toString();
6476
- var intervalMs = Number(interval) * 6e4;
6477
- var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
6478
- var resolvePositiveInteger = (value, fallback) => {
6479
- const parsed = Number(value);
6480
- if (!Number.isFinite(parsed)) {
6481
- return fallback;
6482
- }
6483
- const normalized = Math.floor(parsed);
6484
- return normalized > 0 ? normalized : fallback;
6485
- };
6486
- var resolveNonNegativeInteger = (value, fallback) => {
6487
- const parsed = Number(value);
6488
- if (!Number.isFinite(parsed)) {
6489
- return fallback;
6490
- }
6491
- return Math.max(0, Math.floor(parsed));
6492
- };
6493
- var resolveSignalsDaemonMaxLiveBars = (runtimeInterval = interval) => {
6494
- const intervalMinutes = Number(runtimeInterval);
6495
- const preloadBars = Math.ceil(
6496
- import_constants3.SIGNALS_CLI_PRELOAD_DAYS * 24 * 60 / intervalMinutes
6497
- );
6498
- return resolvePositiveInteger(
6499
- process.env.SIGNALS_DAEMON_MAX_LIVE_BARS,
6500
- preloadBars
6501
- );
6502
- };
6503
- var isSignalsKlineWsEnabled = () => !["0", "false", "off", "no"].includes(
6504
- String(process.env.SIGNALS_KLINE_WS_ENABLED ?? "true").trim().toLowerCase()
6505
- );
6506
- var resolveSignalsKlineWsWaitMs = () => resolveNonNegativeInteger(process.env.SIGNALS_KLINE_WS_WAIT_MS, 1e4);
6507
- var createDefaultSignalsLifecycle = (runtimeInterval = interval) => createSignalsStrategyLifecycle({
6508
- intervalMs: Number(runtimeInterval) * 6e4,
6509
- maxLiveBars: resolveSignalsDaemonMaxLiveBars(runtimeInterval),
6510
- releaseState: import_strategies5.releaseStrategyReplayCache
4770
+ // src/lib/signals/tickerEvaluator.ts
4771
+ var import_strategies5 = require("@tradejs/node/strategies");
4772
+ var import_logger4 = require("@tradejs/infra/logger");
4773
+
4774
+ // src/lib/runtimeModeConfig.ts
4775
+ var buildRuntimeModeStrategyConfig = ({
4776
+ strategyConfig,
4777
+ env,
4778
+ interval,
4779
+ makeOrders,
4780
+ recordRuntimeTrades,
4781
+ aiReplayAnalyses
4782
+ }) => ({
4783
+ ...strategyConfig,
4784
+ ENV: env,
4785
+ MAKE_ORDERS: makeOrders,
4786
+ INTERVAL: interval,
4787
+ ...typeof recordRuntimeTrades === "boolean" ? { RECORD_RUNTIME_TRADES: recordRuntimeTrades } : {},
4788
+ ...aiReplayAnalyses?.length ? { AI_REPLAY_ANALYSES: aiReplayAnalyses } : {}
6511
4789
  });
6512
- var timeOperation2 = (label, operation) => timeOperation(
6513
- label,
6514
- operation,
6515
- (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
6516
- );
6517
- var formatSlowSignalsWarning = (params) => [
6518
- "<b>Slow yarn signals run</b>",
6519
- `Duration: <b>${formatDuration2(params.durationMs)}</b>`,
6520
- `Threshold: <b>${formatDuration2(SLOW_SIGNALS_WARNING_MS)}</b>`,
6521
- `Status: <b>${params.status}</b>`,
6522
- `Found signals: <b>${params.found}</b>`
6523
- ].join("\n");
6524
- var resolveSignalsConnectorName = async (value) => {
6525
- const connectorName = await (0, import_connectors6.resolveConnectorName)(value, projectRoot);
6526
- if (connectorName) {
6527
- return connectorName;
6528
- }
6529
- import_logger4.logger.warn(
6530
- 'Unknown connector "%s". Fallback to %s.',
6531
- String(value || "").trim() || String(value),
6532
- import_connectors6.DEFAULT_CONNECTOR_NAME
6533
- );
6534
- return import_connectors6.DEFAULT_CONNECTOR_NAME;
6535
- };
6536
- var createSignalsSession = async (lifecycle, scope = {}) => {
6537
- const deployment = flags.deployment ? await (0, import_tradingAccounts2.getRuntimeDeployment)(flags.user, String(flags.deployment)) : null;
6538
- if (flags.deployment && !deployment) {
6539
- throw new Error(`Runtime deployment not found: ${flags.deployment}`);
6540
- }
6541
- if (deployment && !deployment.enabled) {
6542
- throw new Error(`Runtime deployment is disabled: ${deployment.id}`);
6543
- }
6544
- const requestedRuntimeInterval = scope.interval ?? interval;
6545
- const runtimeInterval = deployment?.interval ?? requestedRuntimeInterval;
6546
- const runtimeIntervalMs = Number(runtimeInterval) * 6e4;
6547
- if (!Number.isFinite(runtimeIntervalMs) || runtimeIntervalMs <= 0) {
6548
- throw new Error(`Invalid runtime timeframe: ${runtimeInterval}`);
6549
- }
6550
- if (deployment && String(deployment.interval) !== String(requestedRuntimeInterval)) {
6551
- throw new Error(
6552
- `Deployment ${deployment.id} requires timeframe ${deployment.interval}; received ${requestedRuntimeInterval}`
6553
- );
6554
- }
6555
- const connectorName = await resolveSignalsConnectorName(
6556
- deployment?.connectorName ?? scope.connectorName ?? flags.connector
6557
- );
6558
- const universe = deployment?.universe ?? scope.universe ?? flags.universe;
6559
- const requestedAccountId = deployment?.accountId ?? scope.accountId ?? flags.account;
6560
- const connectorFactory = await (0, import_connectors6.getConnectorCreatorByName)(
6561
- connectorName,
6562
- projectRoot
6563
- );
6564
- if (!connectorFactory) {
6565
- throw new Error(`Connector "${connectorName}" is not registered`);
6566
- }
6567
- const marketConnector = await connectorFactory({
6568
- userName: flags.user,
6569
- universe,
6570
- accountId: requestedAccountId,
6571
- deploymentId: deployment?.id
6572
- });
6573
- const btcReferences = await loadBtcReferenceConnectors({
6574
- connectorName,
6575
- marketConnector,
6576
- userName: flags.user,
6577
- projectRoot,
6578
- shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors6.DEFAULT_CONNECTOR_NAME.toLowerCase(),
6579
- warn: (message) => import_logger4.logger.warn(message)
6580
- });
6581
- return {
4790
+
4791
+ // src/lib/signals/tickerEvaluator.ts
4792
+ var createSignalsTickerEvaluator = ({
4793
+ userName,
4794
+ makeOrders,
4795
+ projectRoot,
4796
+ context
4797
+ }) => async (symbol, instrument) => {
4798
+ const {
6582
4799
  connectorName,
4800
+ connector,
4801
+ btcBinanceData,
4802
+ btcCoinbaseData,
4803
+ primaryBtcClosedData,
4804
+ primaryEthClosedData,
4805
+ primaryEthByTimestamp,
4806
+ runtimeStrategies,
4807
+ strategyStats,
4808
+ runtimeCloseNotifications,
4809
+ lifecycle,
4810
+ preloadStart,
4811
+ currentTimestamp,
4812
+ persistStrategyState,
6583
4813
  universe,
6584
- accountId: marketConnector.accountId ?? requestedAccountId,
6585
- interval: runtimeInterval,
6586
- intervalMs: runtimeIntervalMs,
6587
- deployment,
6588
- startedAt: Date.now(),
6589
- marketConnector,
6590
- btcReferences,
6591
- lifecycle
6592
- };
6593
- };
6594
- 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) => {
6595
- const strategySignals = [];
6596
- const loadCached = (cachedSymbol) => connector.kline({
6597
- symbol: cachedSymbol,
4814
+ interval,
4815
+ intervalMs,
4816
+ accountId,
4817
+ deploymentId,
4818
+ runtimeScopeUniverse,
4819
+ saveRuntimeSignalEvaluation,
4820
+ saveRuntimeSignal
4821
+ } = context;
4822
+ const cachedData = universe === "crypto" && symbol === "BTCUSDT" ? primaryBtcClosedData : universe === "crypto" && symbol === "ETHUSDT" ? primaryEthClosedData : await connector.kline({
4823
+ symbol,
6598
4824
  start: preloadStart,
6599
4825
  end: currentTimestamp,
6600
4826
  cacheOnly: true,
6601
- interval: interval2
4827
+ interval
6602
4828
  });
6603
- const cachedData = universe === "crypto" && symbol === "BTCUSDT" ? primaryBtcClosedData : universe === "crypto" && symbol === "ETHUSDT" ? primaryEthClosedData : await loadCached(symbol);
6604
4829
  const closedData = getClosedCandlesForInterval(
6605
4830
  cachedData,
6606
4831
  currentTimestamp,
6607
- intervalMs2
6608
- );
6609
- const closedBtcData = primaryBtcClosedData;
6610
- const closedEthData = primaryEthClosedData;
6611
- const { alignedCoinCandles, alignedBtcCandles } = universe === "crypto" ? alignSymbolWithBtcReference(closedData, closedBtcData) : { alignedCoinCandles: closedData, alignedBtcCandles: closedData };
6612
- const alignedEthCandles = alignedCoinCandles.map((candle) => primaryEthByTimestamp.get(candle.timestamp)).filter(
6613
- (candle) => Boolean(candle)
4832
+ intervalMs
6614
4833
  );
4834
+ const { alignedCoinCandles, alignedBtcCandles } = universe === "crypto" ? alignSymbolWithBtcReference(closedData, primaryBtcClosedData) : { alignedCoinCandles: closedData, alignedBtcCandles: closedData };
4835
+ const alignedEthCandles = alignedCoinCandles.map((candle) => primaryEthByTimestamp.get(candle.timestamp)).filter((candle) => Boolean(candle));
6615
4836
  const lastCandle = alignedCoinCandles.at(-1);
6616
4837
  const btcLastCandle = alignedBtcCandles.at(-1);
6617
- const ethLastCandle = lastCandle == null ? void 0 : primaryEthByTimestamp.get(lastCandle.timestamp);
6618
- if (!lastCandle || !btcLastCandle) {
6619
- return strategySignals;
6620
- }
4838
+ const ethLastCandle = lastCandle ? primaryEthByTimestamp.get(lastCandle.timestamp) : void 0;
4839
+ if (!lastCandle || !btcLastCandle) return [];
6621
4840
  const previousData = alignedCoinCandles.slice(0, -1);
6622
4841
  const previousBtcData = alignedBtcCandles.slice(0, -1);
6623
4842
  const previousEthData = alignedEthCandles.filter(
6624
4843
  (candle) => candle.timestamp < lastCandle.timestamp
6625
4844
  );
4845
+ const strategySignals = [];
6626
4846
  for (const runtimeStrategy of runtimeStrategies) {
6627
4847
  const {
6628
4848
  strategyName,
@@ -6632,23 +4852,20 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6632
4852
  strategyConfig,
6633
4853
  strategyResults
6634
4854
  } = runtimeStrategy;
4855
+ const symbolResultConfig = strategyResults?.[symbol]?.config ?? null;
6635
4856
  const runtimeConfig = buildRuntimeModeStrategyConfig({
6636
4857
  strategyConfig,
6637
4858
  env: "CRON",
6638
- interval: interval2,
6639
- makeOrders: flags.makeOrders
4859
+ interval,
4860
+ makeOrders
6640
4861
  });
6641
4862
  const runtimeLineage = await buildRuntimeLineage({
6642
4863
  projectRoot,
6643
4864
  strategyName,
6644
- config: {
6645
- configId,
6646
- strategyConfig,
6647
- symbolResultConfig: strategyResults?.[symbol]?.config ?? null
6648
- },
4865
+ config: { configId, strategyConfig, symbolResultConfig },
6649
4866
  runContext: {
6650
4867
  connectorName: connectorName.toLowerCase(),
6651
- interval: String(interval2),
4868
+ interval: String(interval),
6652
4869
  universe
6653
4870
  }
6654
4871
  });
@@ -6658,40 +4875,36 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6658
4875
  accountId,
6659
4876
  deploymentId,
6660
4877
  symbol,
6661
- interval: interval2,
4878
+ interval,
6662
4879
  strategyName,
6663
4880
  configId
6664
4881
  });
6665
4882
  const stats = strategyStats.get(strategyName);
6666
- const initialDataLength = previousData.length;
6667
- const initialBtcDataLength = previousBtcData.length;
6668
- const initialEthDataLength = previousEthData.length;
4883
+ const initialLengths = [
4884
+ previousData.length,
4885
+ previousBtcData.length,
4886
+ previousEthData.length
4887
+ ];
6669
4888
  let evaluation;
6670
4889
  try {
6671
4890
  evaluation = await lifecycle.evaluate({
6672
4891
  key: lifecycleKey,
6673
4892
  timestamp: lastCandle.timestamp,
6674
- config: {
6675
- runtimeConfig,
6676
- sourceStrategyConfig,
6677
- symbolResultConfig: strategyResults?.[symbol]?.config ?? null
6678
- },
4893
+ config: { runtimeConfig, sourceStrategyConfig, symbolResultConfig },
6679
4894
  btcBinanceData,
6680
4895
  btcCoinbaseData,
6681
- onRuntimeClose: (event) => {
6682
- runtimeCloseNotifications.push(event);
6683
- },
6684
- create: async ({
4896
+ onRuntimeClose: (event) => runtimeCloseNotifications.push(event),
4897
+ create: ({
6685
4898
  btcBinanceData: lifecycleBtcBinanceData,
6686
4899
  btcCoinbaseData: lifecycleBtcCoinbaseData,
6687
4900
  onRuntimeClose
6688
4901
  }) => strategyCreator({
6689
- userName: flags.user,
4902
+ userName,
6690
4903
  connectorName,
6691
4904
  runtimeConfigId: configId,
6692
4905
  runtimeConfigSnapshot: {
6693
4906
  userConfig: sourceStrategyConfig,
6694
- symbolResultConfig: strategyResults?.[symbol]?.config ?? null
4907
+ symbolResultConfig
6695
4908
  },
6696
4909
  connector,
6697
4910
  symbol,
@@ -6714,9 +4927,9 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6714
4927
  run: (strategy) => strategy(lastCandle, btcLastCandle, ethLastCandle)
6715
4928
  });
6716
4929
  } finally {
6717
- previousData.length = initialDataLength;
6718
- previousBtcData.length = initialBtcDataLength;
6719
- previousEthData.length = initialEthDataLength;
4930
+ previousData.length = initialLengths[0];
4931
+ previousBtcData.length = initialLengths[1];
4932
+ previousEthData.length = initialLengths[2];
6720
4933
  }
6721
4934
  if (evaluation.action === "duplicate" || evaluation.action === "stale") {
6722
4935
  continue;
@@ -6729,9 +4942,7 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6729
4942
  symbol
6730
4943
  );
6731
4944
  }
6732
- if (stats) {
6733
- stats.evaluated += 1;
6734
- }
4945
+ if (stats) stats.evaluated += 1;
6735
4946
  const signal = evaluation.result;
6736
4947
  if (!signal || typeof signal === "string") {
6737
4948
  const reason = typeof signal === "string" && signal.trim() ? signal : "NO_SIGNAL";
@@ -6745,12 +4956,12 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6745
4956
  timestamp: lastCandle.timestamp,
6746
4957
  runtimeConfigId: configId
6747
4958
  }),
6748
- userName: flags.user,
4959
+ userName,
6749
4960
  strategy: strategyName,
6750
4961
  runtimeConfigId: configId,
6751
4962
  runtimeLineage,
6752
4963
  symbol,
6753
- interval: interval2,
4964
+ interval,
6754
4965
  universe,
6755
4966
  assetClass: instrument?.assetClass,
6756
4967
  accountId,
@@ -6763,18 +4974,13 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6763
4974
  });
6764
4975
  continue;
6765
4976
  }
6766
- if (stats) {
6767
- stats.signals += 1;
6768
- }
4977
+ if (stats) stats.signals += 1;
6769
4978
  signal.runtimeConfigId = configId;
6770
4979
  signal.runtimeLineage = runtimeLineage;
6771
4980
  if (configId && configId !== "config" && !signal.signalId.endsWith(`:${configId}`)) {
6772
4981
  signal.signalId = `${signal.signalId}:${configId}`;
6773
4982
  }
6774
- await (0, import_strategies6.enrichSignalWithBinanceMarketContext)({
6775
- signal,
6776
- env: "CRON"
6777
- });
4983
+ await (0, import_strategies5.enrichSignalWithBinanceMarketContext)({ signal, env: "CRON" });
6778
4984
  if (signal.orderStatus === "skipped" && typeof signal.orderSkipReason === "string" && signal.orderSkipReason.trim()) {
6779
4985
  recordStrategyReason(
6780
4986
  strategyStats,
@@ -6784,7 +4990,7 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6784
4990
  );
6785
4991
  }
6786
4992
  strategySignals.push(signal);
6787
- saveRuntimeSignal?.(flags.user, signal);
4993
+ saveRuntimeSignal?.(userName, signal);
6788
4994
  await saveRuntimeSignalEvaluation?.({
6789
4995
  evaluationId: buildRuntimeSignalEvaluationId({
6790
4996
  strategyName,
@@ -6792,12 +4998,12 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6792
4998
  timestamp: lastCandle.timestamp,
6793
4999
  runtimeConfigId: configId
6794
5000
  }),
6795
- userName: flags.user,
5001
+ userName,
6796
5002
  strategy: strategyName,
6797
5003
  runtimeConfigId: configId,
6798
5004
  runtimeLineage,
6799
5005
  symbol,
6800
- interval: interval2,
5006
+ interval,
6801
5007
  universe,
6802
5008
  assetClass: instrument?.assetClass,
6803
5009
  accountId,
@@ -6818,259 +5024,383 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
6818
5024
  }
6819
5025
  return strategySignals;
6820
5026
  };
6821
- var signals = async (options = {}) => {
6822
- const startedAt = Date.now();
6823
- const signals2 = new Array();
6824
- const runtimeCloseNotifications = new Array();
6825
- let status = "completed";
6826
- let failureMessage;
6827
- let activeSession;
6828
- let projectHooks;
6829
- let afterSignalsHookContext = null;
6830
- const runtimeSignalEvaluations = createRuntimeSignalEvaluationBuffer();
6831
- try {
6832
- const session = options.session ?? await createSignalsSession(createDefaultSignalsLifecycle());
6833
- activeSession = session;
6834
- const persistStrategyState = options.session != null;
6835
- const {
5027
+
5028
+ // src/lib/signals/runner.ts
5029
+ var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
5030
+ var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
5031
+ var resolvePositiveInteger = (value, fallback) => {
5032
+ const parsed = Number(value);
5033
+ if (!Number.isFinite(parsed)) {
5034
+ return fallback;
5035
+ }
5036
+ const normalized = Math.floor(parsed);
5037
+ return normalized > 0 ? normalized : fallback;
5038
+ };
5039
+ var resolveNonNegativeInteger = (value, fallback) => {
5040
+ const parsed = Number(value);
5041
+ if (!Number.isFinite(parsed)) {
5042
+ return fallback;
5043
+ }
5044
+ return Math.max(0, Math.floor(parsed));
5045
+ };
5046
+ var createSignalsRunner = (config2) => {
5047
+ const interval = config2.interval;
5048
+ const projectRoot = config2.projectRoot?.trim() || String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
5049
+ const resolveSignalsDaemonMaxLiveBars = (runtimeInterval = interval) => {
5050
+ const intervalMinutes = Number(runtimeInterval);
5051
+ const preloadBars = Math.ceil(
5052
+ import_constants3.SIGNALS_CLI_PRELOAD_DAYS * 24 * 60 / intervalMinutes
5053
+ );
5054
+ return resolvePositiveInteger(
5055
+ process.env.SIGNALS_DAEMON_MAX_LIVE_BARS,
5056
+ preloadBars
5057
+ );
5058
+ };
5059
+ const isSignalsKlineWsEnabled = () => !["0", "false", "off", "no"].includes(
5060
+ String(process.env.SIGNALS_KLINE_WS_ENABLED ?? "true").trim().toLowerCase()
5061
+ );
5062
+ const resolveSignalsKlineWsWaitMs = () => resolveNonNegativeInteger(process.env.SIGNALS_KLINE_WS_WAIT_MS, 1e4);
5063
+ const createDefaultSignalsLifecycle = (runtimeInterval = interval) => createSignalsStrategyLifecycle({
5064
+ intervalMs: Number(runtimeInterval) * 6e4,
5065
+ maxLiveBars: resolveSignalsDaemonMaxLiveBars(runtimeInterval),
5066
+ releaseState: import_strategies6.releaseStrategyReplayCache
5067
+ });
5068
+ const timeOperation2 = (label, operation) => timeOperation(
5069
+ label,
5070
+ operation,
5071
+ (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5072
+ );
5073
+ const formatSlowSignalsWarning = (params) => [
5074
+ "<b>Slow yarn signals run</b>",
5075
+ `Duration: <b>${formatDuration2(params.durationMs)}</b>`,
5076
+ `Threshold: <b>${formatDuration2(SLOW_SIGNALS_WARNING_MS)}</b>`,
5077
+ `Status: <b>${params.status}</b>`,
5078
+ `Found signals: <b>${params.found}</b>`
5079
+ ].join("\n");
5080
+ const resolveSignalsConnectorName = async (value) => {
5081
+ const connectorName = await (0, import_connectors6.resolveConnectorName)(value, projectRoot);
5082
+ if (connectorName) {
5083
+ return connectorName;
5084
+ }
5085
+ import_logger5.logger.warn(
5086
+ 'Unknown connector "%s". Fallback to %s.',
5087
+ String(value || "").trim() || String(value),
5088
+ import_connectors6.DEFAULT_CONNECTOR_NAME
5089
+ );
5090
+ return import_connectors6.DEFAULT_CONNECTOR_NAME;
5091
+ };
5092
+ const createSignalsSession2 = async (lifecycle, scope = {}) => {
5093
+ const deployment = config2.deploymentId ? await (0, import_runtimeDeployments.getRuntimeDeployment)(config2.userName, config2.deploymentId) : null;
5094
+ if (config2.deploymentId && !deployment) {
5095
+ throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
5096
+ }
5097
+ if (deployment && !deployment.enabled) {
5098
+ throw new Error(`Runtime deployment is disabled: ${deployment.id}`);
5099
+ }
5100
+ const requestedRuntimeInterval = scope.interval ?? interval;
5101
+ const runtimeInterval = deployment?.interval ?? requestedRuntimeInterval;
5102
+ const runtimeIntervalMs = Number(runtimeInterval) * 6e4;
5103
+ if (!Number.isFinite(runtimeIntervalMs) || runtimeIntervalMs <= 0) {
5104
+ throw new Error(`Invalid runtime timeframe: ${runtimeInterval}`);
5105
+ }
5106
+ if (deployment && String(deployment.interval) !== String(requestedRuntimeInterval)) {
5107
+ throw new Error(
5108
+ `Deployment ${deployment.id} requires timeframe ${deployment.interval}; received ${requestedRuntimeInterval}`
5109
+ );
5110
+ }
5111
+ const connectorName = await resolveSignalsConnectorName(
5112
+ deployment?.connectorName ?? scope.connectorName ?? config2.connectorName
5113
+ );
5114
+ const universe = deployment?.universe ?? scope.universe ?? config2.universe;
5115
+ const requestedAccountId = deployment?.accountId ?? scope.accountId ?? config2.accountId;
5116
+ const connectorFactory = await (0, import_connectors6.getConnectorCreatorByName)(
6836
5117
  connectorName,
6837
- universe: sessionUniverse,
6838
- accountId,
5118
+ projectRoot
5119
+ );
5120
+ if (!connectorFactory) {
5121
+ throw new Error(`Connector "${connectorName}" is not registered`);
5122
+ }
5123
+ const marketConnector = await connectorFactory({
5124
+ userName: config2.userName,
5125
+ universe,
5126
+ accountId: requestedAccountId,
5127
+ deploymentId: deployment?.id
5128
+ });
5129
+ const btcReferences = await loadBtcReferenceConnectors({
5130
+ connectorName,
5131
+ marketConnector,
5132
+ userName: config2.userName,
5133
+ projectRoot,
5134
+ shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors6.DEFAULT_CONNECTOR_NAME.toLowerCase(),
5135
+ warn: (message) => import_logger5.logger.warn(message)
5136
+ });
5137
+ return {
5138
+ connectorName,
5139
+ universe,
5140
+ accountId: marketConnector.accountId ?? requestedAccountId,
5141
+ interval: runtimeInterval,
5142
+ intervalMs: runtimeIntervalMs,
6839
5143
  deployment,
5144
+ startedAt: Date.now(),
6840
5145
  marketConnector,
6841
5146
  btcReferences,
6842
- lifecycle,
6843
- interval: interval2,
6844
- intervalMs: intervalMs2
6845
- } = session;
6846
- const universe = sessionUniverse ?? marketConnector.universe ?? "crypto";
6847
- const tickers = await timeOperation2("tickers load", () => {
6848
- const baseArgs = [
5147
+ lifecycle
5148
+ };
5149
+ };
5150
+ const signals2 = async (options = {}) => {
5151
+ const startedAt = Date.now();
5152
+ const signals3 = new Array();
5153
+ const runtimeCloseNotifications = new Array();
5154
+ let status = "completed";
5155
+ let failureMessage;
5156
+ let activeSession;
5157
+ let projectHooks;
5158
+ let afterSignalsHookContext = null;
5159
+ const runtimeSignalEvaluations = createRuntimeSignalEvaluationBuffer();
5160
+ try {
5161
+ const session = options.session ?? await createSignalsSession2(createDefaultSignalsLifecycle());
5162
+ activeSession = session;
5163
+ const persistStrategyState = options.session != null;
5164
+ const {
5165
+ connectorName,
5166
+ universe: sessionUniverse,
5167
+ accountId,
5168
+ deployment,
6849
5169
  marketConnector,
6850
- flags.tickers || deployment?.tickers?.join(","),
6851
- flags.exclude,
6852
- flags.tickersLimit,
6853
- flags.chunk
6854
- ];
6855
- return sessionUniverse || accountId || deployment ? (0, import_cli2.getTickers)(...baseArgs, {
5170
+ btcReferences,
5171
+ lifecycle,
5172
+ interval: interval2,
5173
+ intervalMs
5174
+ } = session;
5175
+ const universe = sessionUniverse ?? marketConnector.universe ?? "crypto";
5176
+ const tickers = await timeOperation2("tickers load", () => {
5177
+ const baseArgs = [
5178
+ marketConnector,
5179
+ config2.tickers || deployment?.tickers?.join(","),
5180
+ config2.exclude,
5181
+ config2.tickersLimit,
5182
+ config2.chunk
5183
+ ];
5184
+ return sessionUniverse || accountId || deployment ? (0, import_cli2.getTickers)(...baseArgs, {
5185
+ universe,
5186
+ assetClasses: deployment?.assetClasses
5187
+ }) : (0, import_cli2.getTickers)(...baseArgs);
5188
+ });
5189
+ if (universe === "tradfi" && typeof marketConnector.listInstruments !== "function") {
5190
+ throw new Error("TradFi connector must implement listInstruments");
5191
+ }
5192
+ const instruments = typeof marketConnector.listInstruments === "function" ? await marketConnector.listInstruments({
6856
5193
  universe,
6857
- assetClasses: deployment?.assetClasses
6858
- }) : (0, import_cli2.getTickers)(...baseArgs);
6859
- });
6860
- if (universe === "tradfi" && typeof marketConnector.listInstruments !== "function") {
6861
- throw new Error("TradFi connector must implement listInstruments");
6862
- }
6863
- const instruments = typeof marketConnector.listInstruments === "function" ? await marketConnector.listInstruments({
6864
- universe,
6865
- assetClasses: deployment?.assetClasses,
6866
- symbols: tickers
6867
- }) : [];
6868
- const instrumentsBySymbol = new Map(
6869
- instruments.map((instrument) => [instrument.symbol, instrument])
6870
- );
6871
- if (flags.showTickersList) {
6872
- console.log(import_chalk7.default.gray(JSON.stringify(tickers.sort(), null, 2)));
6873
- return;
6874
- }
6875
- const projectConfig = await (0, import_cli2.loadTradejsConfig)(projectRoot);
6876
- projectHooks = projectConfig.hooks;
6877
- const currentTimestamp = (0, import_time3.getTimestamp)();
6878
- const preloadStart = (0, import_time3.getTimestamp)(import_constants3.SIGNALS_CLI_PRELOAD_DAYS);
6879
- if (!flags.cacheOnly && session.klineFeed) {
6880
- const expectedSymbols = universe === "crypto" ? [.../* @__PURE__ */ new Set([...tickers, "BTCUSDT", "ETHUSDT"])] : tickers;
6881
- session.klineFeed.setSubscriptions(expectedSymbols);
6882
- const targetTimestamp = Math.floor(currentTimestamp / intervalMs2) * intervalMs2 - intervalMs2;
6883
- const missingSymbols = await timeOperation2(
6884
- "websocket candle readiness",
6885
- () => session.klineFeed.waitForClosed({
6886
- symbols: expectedSymbols,
6887
- timestamp: targetTimestamp,
6888
- timeoutMs: resolveSignalsKlineWsWaitMs()
6889
- })
5194
+ assetClasses: deployment?.assetClasses,
5195
+ symbols: tickers
5196
+ }) : [];
5197
+ const instrumentsBySymbol = new Map(
5198
+ instruments.map((instrument) => [instrument.symbol, instrument])
5199
+ );
5200
+ if (config2.showTickersList) {
5201
+ console.log(import_chalk7.default.gray(JSON.stringify(tickers.sort(), null, 2)));
5202
+ return;
5203
+ }
5204
+ const projectConfig = await (0, import_cli2.loadTradejsConfig)(projectRoot);
5205
+ projectHooks = projectConfig.hooks;
5206
+ const currentTimestamp = (0, import_time3.getTimestamp)();
5207
+ const preloadStart = (0, import_time3.getTimestamp)(import_constants3.SIGNALS_CLI_PRELOAD_DAYS);
5208
+ if (!config2.cacheOnly && session.klineFeed) {
5209
+ const expectedSymbols = universe === "crypto" ? [.../* @__PURE__ */ new Set([...tickers, "BTCUSDT", "ETHUSDT"])] : tickers;
5210
+ session.klineFeed.setSubscriptions(expectedSymbols);
5211
+ const targetTimestamp = Math.floor(currentTimestamp / intervalMs) * intervalMs - intervalMs;
5212
+ const missingSymbols = await timeOperation2(
5213
+ "websocket candle readiness",
5214
+ () => session.klineFeed.waitForClosed({
5215
+ symbols: expectedSymbols,
5216
+ timestamp: targetTimestamp,
5217
+ timeoutMs: resolveSignalsKlineWsWaitMs()
5218
+ })
5219
+ );
5220
+ await session.klineFeed.flush();
5221
+ import_logger5.logger.info(
5222
+ import_chalk7.default.gray(
5223
+ `websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
5224
+ )
5225
+ );
5226
+ await updatePrimaryMarketHistory({
5227
+ marketConnector,
5228
+ connectorName,
5229
+ interval: interval2,
5230
+ symbols: missingSymbols,
5231
+ preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
5232
+ universe,
5233
+ log: (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5234
+ });
5235
+ await updateBtcReferenceHistory({
5236
+ marketConnector,
5237
+ btcReferences,
5238
+ interval: interval2,
5239
+ preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
5240
+ universe,
5241
+ log: (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5242
+ });
5243
+ } else if (!config2.cacheOnly) {
5244
+ await updateMarketHistoryWithBtcReferences({
5245
+ marketConnector,
5246
+ connectorName,
5247
+ btcReferences,
5248
+ interval: interval2,
5249
+ symbols: tickers,
5250
+ preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
5251
+ universe,
5252
+ log: (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5253
+ });
5254
+ }
5255
+ await prepareMarketContextForRun({
5256
+ mode: "signals",
5257
+ userName: config2.userName,
5258
+ projectRoot,
5259
+ symbols: tickers,
5260
+ universe,
5261
+ interval: interval2,
5262
+ startMs: currentTimestamp,
5263
+ endMs: currentTimestamp,
5264
+ preloadStartMs: preloadStart,
5265
+ cacheOnly: config2.cacheOnly,
5266
+ log: (message) => import_logger5.logger.info(import_chalk7.default.gray(message))
5267
+ });
5268
+ if (config2.updateOnly) {
5269
+ return;
5270
+ }
5271
+ const [
5272
+ btcBinanceData,
5273
+ btcCoinbaseData,
5274
+ primaryBtcCachedData,
5275
+ primaryEthCachedData
5276
+ ] = universe === "crypto" ? await timeOperation2(
5277
+ "reference candles load",
5278
+ () => Promise.all([
5279
+ btcReferences.binance.kline({
5280
+ symbol: "BTCUSDT",
5281
+ start: preloadStart,
5282
+ end: currentTimestamp,
5283
+ cacheOnly: true,
5284
+ interval: interval2
5285
+ }),
5286
+ btcReferences.coinbase.kline({
5287
+ symbol: "BTCUSDT",
5288
+ start: preloadStart,
5289
+ end: currentTimestamp,
5290
+ cacheOnly: true,
5291
+ interval: interval2
5292
+ }),
5293
+ marketConnector.kline({
5294
+ symbol: "BTCUSDT",
5295
+ start: preloadStart,
5296
+ end: currentTimestamp,
5297
+ cacheOnly: true,
5298
+ interval: interval2
5299
+ }),
5300
+ marketConnector.kline({
5301
+ symbol: "ETHUSDT",
5302
+ start: preloadStart,
5303
+ end: currentTimestamp,
5304
+ cacheOnly: true,
5305
+ interval: interval2
5306
+ })
5307
+ ])
5308
+ ) : [[], [], [], []];
5309
+ const primaryBtcClosedData = getClosedCandlesForInterval(
5310
+ primaryBtcCachedData,
5311
+ currentTimestamp,
5312
+ intervalMs
6890
5313
  );
6891
- await session.klineFeed.flush();
6892
- import_logger4.logger.info(
6893
- import_chalk7.default.gray(
6894
- `websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
6895
- )
5314
+ const primaryEthClosedData = getClosedCandlesForInterval(
5315
+ primaryEthCachedData,
5316
+ currentTimestamp,
5317
+ intervalMs
6896
5318
  );
6897
- await updatePrimaryMarketHistory({
6898
- marketConnector,
5319
+ const primaryEthByTimestamp = new Map(
5320
+ primaryEthClosedData.map((candle) => [candle.timestamp, candle])
5321
+ );
5322
+ const runtimeStrategies = await loadRuntimeStrategies({
5323
+ userName: config2.userName,
5324
+ projectRoot,
5325
+ deployment,
6899
5326
  connectorName,
6900
- interval: interval2,
6901
- symbols: missingSymbols,
6902
- preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
6903
- universe,
6904
- log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
6905
- });
6906
- await updateBtcReferenceHistory({
6907
- marketConnector,
6908
- btcReferences,
6909
- interval: interval2,
6910
- preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
6911
5327
  universe,
6912
- log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
5328
+ accountId,
5329
+ interval: interval2
6913
5330
  });
6914
- } else if (!flags.cacheOnly) {
6915
- await updateMarketHistoryWithBtcReferences({
6916
- marketConnector,
5331
+ if (!runtimeStrategies.length) {
5332
+ lifecycle.clear();
5333
+ import_logger5.logger.warn(
5334
+ "No strategy configs found by users:%s:strategies:*:config",
5335
+ config2.userName
5336
+ );
5337
+ return;
5338
+ }
5339
+ lifecycle.retain(
5340
+ new Set(
5341
+ tickers.flatMap(
5342
+ (symbol) => runtimeStrategies.map(
5343
+ ({ strategyName, configId }) => buildSignalsStrategyLifecycleKey({
5344
+ connectorName,
5345
+ universe: sessionUniverse,
5346
+ accountId,
5347
+ deploymentId: deployment?.id,
5348
+ symbol,
5349
+ interval: interval2,
5350
+ strategyName,
5351
+ configId
5352
+ })
5353
+ )
5354
+ )
5355
+ )
5356
+ );
5357
+ import_logger5.logger.info(
5358
+ import_chalk7.default.yellow(
5359
+ `loaded strategies (user=${config2.userName}): ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
5360
+ )
5361
+ );
5362
+ afterSignalsHookContext = {
5363
+ connector: marketConnector,
6917
5364
  connectorName,
6918
- btcReferences,
5365
+ userName: config2.userName,
6919
5366
  interval: interval2,
6920
- symbols: tickers,
6921
- preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
6922
- universe,
6923
- log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
6924
- });
6925
- }
6926
- await prepareMarketContextForRun({
6927
- mode: "signals",
6928
- userName: flags.user,
6929
- projectRoot,
6930
- symbols: tickers,
6931
- universe,
6932
- interval: interval2,
6933
- startMs: currentTimestamp,
6934
- endMs: currentTimestamp,
6935
- preloadStartMs: preloadStart,
6936
- cacheOnly: Boolean(flags.cacheOnly),
6937
- log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
6938
- });
6939
- if (flags.updateOnly) {
6940
- return;
6941
- }
6942
- const [
6943
- btcBinanceData,
6944
- btcCoinbaseData,
6945
- primaryBtcCachedData,
6946
- primaryEthCachedData
6947
- ] = universe === "crypto" ? await timeOperation2(
6948
- "reference candles load",
6949
- () => Promise.all([
6950
- btcReferences.binance.kline({
6951
- symbol: "BTCUSDT",
6952
- start: preloadStart,
6953
- end: currentTimestamp,
6954
- cacheOnly: true,
6955
- interval: interval2
6956
- }),
6957
- btcReferences.coinbase.kline({
6958
- symbol: "BTCUSDT",
6959
- start: preloadStart,
6960
- end: currentTimestamp,
6961
- cacheOnly: true,
6962
- interval: interval2
6963
- }),
6964
- marketConnector.kline({
6965
- symbol: "BTCUSDT",
6966
- start: preloadStart,
6967
- end: currentTimestamp,
6968
- cacheOnly: true,
6969
- interval: interval2
6970
- }),
6971
- marketConnector.kline({
6972
- symbol: "ETHUSDT",
6973
- start: preloadStart,
6974
- end: currentTimestamp,
6975
- cacheOnly: true,
6976
- interval: interval2
6977
- })
6978
- ])
6979
- ) : [[], [], [], []];
6980
- const primaryBtcClosedData = getClosedCandlesForInterval(
6981
- primaryBtcCachedData,
6982
- currentTimestamp,
6983
- intervalMs2
6984
- );
6985
- const primaryEthClosedData = getClosedCandlesForInterval(
6986
- primaryEthCachedData,
6987
- currentTimestamp,
6988
- intervalMs2
6989
- );
6990
- const primaryEthByTimestamp = new Map(
6991
- primaryEthClosedData.map((candle) => [candle.timestamp, candle])
6992
- );
6993
- const runtimeStrategies = await loadRuntimeStrategies({
6994
- userName: flags.user,
6995
- projectRoot,
6996
- deployment,
6997
- connectorName,
6998
- universe,
6999
- accountId,
7000
- interval: interval2
7001
- });
7002
- if (!runtimeStrategies.length) {
7003
- lifecycle.clear();
7004
- import_logger4.logger.warn(
7005
- "No strategy configs found by users:%s:strategies:*:config",
7006
- flags.user
7007
- );
7008
- return;
7009
- }
7010
- lifecycle.retain(
7011
- new Set(
7012
- tickers.flatMap(
7013
- (symbol) => runtimeStrategies.map(
7014
- ({ strategyName, configId }) => buildSignalsStrategyLifecycleKey({
7015
- connectorName,
7016
- universe: sessionUniverse,
7017
- accountId,
7018
- deploymentId: deployment?.id,
7019
- symbol,
7020
- interval: interval2,
7021
- strategyName,
7022
- configId
7023
- })
7024
- )
5367
+ tickers: [...tickers],
5368
+ runtimeStrategies: runtimeStrategies.map(
5369
+ ({ strategyName, strategyConfig }) => ({
5370
+ strategyName,
5371
+ strategyConfig
5372
+ })
7025
5373
  )
7026
- )
7027
- );
7028
- import_logger4.logger.info(
7029
- import_chalk7.default.yellow(
7030
- `loaded strategies (user=${flags.user}): ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
7031
- )
7032
- );
7033
- afterSignalsHookContext = {
7034
- connector: marketConnector,
7035
- connectorName,
7036
- userName: flags.user,
7037
- interval: interval2,
7038
- tickers: [...tickers],
7039
- runtimeStrategies: runtimeStrategies.map(
7040
- ({ strategyName, strategyConfig }) => ({
7041
- strategyName,
7042
- strategyConfig
7043
- })
7044
- )
7045
- };
7046
- const beforeSignalsResult = await invokeBeforeSignalsHooks(
7047
- projectHooks,
7048
- afterSignalsHookContext
7049
- );
7050
- if (beforeSignalsResult?.abort === true) {
7051
- import_logger4.logger.info(
7052
- "signals aborted before ticker evaluation: %s",
7053
- beforeSignalsResult.reason ?? "PROJECT_BEFORE_SIGNALS_ABORTED"
5374
+ };
5375
+ const beforeSignalsResult = await invokeBeforeSignalsHooks(
5376
+ projectHooks,
5377
+ afterSignalsHookContext
7054
5378
  );
7055
- return;
7056
- }
7057
- const strategyStats = createStrategySkipStats(runtimeStrategies);
7058
- const bar = new import_progress4.default(
7059
- ":current/:total [:bar][:percent] :found :eta(s) :symbol",
7060
- {
7061
- total: tickers.length,
7062
- width: 30
5379
+ if (beforeSignalsResult?.abort === true) {
5380
+ import_logger5.logger.info(
5381
+ "signals aborted before ticker evaluation: %s",
5382
+ beforeSignalsResult.reason ?? "PROJECT_BEFORE_SIGNALS_ABORTED"
5383
+ );
5384
+ return;
7063
5385
  }
7064
- );
7065
- import_logger4.logger.info(import_chalk7.default.yellow(`tickers: ${tickers.length}`));
7066
- const signalsParallel = resolvePositiveInteger(flags.parallel, 4);
7067
- import_logger4.logger.info(import_chalk7.default.yellow(`signal workers: ${signalsParallel}`));
7068
- await timeOperation2("strategy evaluation", async () => {
7069
- await (0, import_async3.runWithConcurrency)(tickers, signalsParallel, async (symbol) => {
7070
- const strategySignals = await findSignals(
7071
- symbol,
5386
+ const strategyStats = createStrategySkipStats(runtimeStrategies);
5387
+ const bar = new import_progress4.default(
5388
+ ":current/:total [:bar][:percent] :found :eta(s) :symbol",
5389
+ {
5390
+ total: tickers.length,
5391
+ width: 30
5392
+ }
5393
+ );
5394
+ import_logger5.logger.info(import_chalk7.default.yellow(`tickers: ${tickers.length}`));
5395
+ const signalsParallel = resolvePositiveInteger(config2.parallel, 4);
5396
+ import_logger5.logger.info(import_chalk7.default.yellow(`signal workers: ${signalsParallel}`));
5397
+ const evaluateTicker = createSignalsTickerEvaluator({
5398
+ userName: config2.userName,
5399
+ makeOrders: config2.makeOrders,
5400
+ projectRoot,
5401
+ context: {
7072
5402
  connectorName,
7073
- marketConnector,
5403
+ connector: marketConnector,
7074
5404
  btcBinanceData,
7075
5405
  btcCoinbaseData,
7076
5406
  primaryBtcClosedData,
@@ -7084,146 +5414,336 @@ var signals = async (options = {}) => {
7084
5414
  currentTimestamp,
7085
5415
  persistStrategyState,
7086
5416
  universe,
7087
- interval2,
7088
- intervalMs2,
5417
+ interval: interval2,
5418
+ intervalMs,
7089
5419
  accountId,
7090
- deployment?.id,
7091
- instrumentsBySymbol.get(symbol),
7092
- sessionUniverse,
7093
- runtimeSignalEvaluations.save,
7094
- runtimeSignalEvaluations.saveSignal
7095
- );
7096
- if (strategySignals.length > 0) {
7097
- signals2.push(...strategySignals);
5420
+ deploymentId: deployment?.id,
5421
+ runtimeScopeUniverse: sessionUniverse,
5422
+ saveRuntimeSignalEvaluation: runtimeSignalEvaluations.save,
5423
+ saveRuntimeSignal: runtimeSignalEvaluations.saveSignal
7098
5424
  }
7099
- bar.tick(1, {
7100
- found: import_chalk7.default.cyan(signals2.length),
7101
- symbol: import_chalk7.default.gray(symbol)
5425
+ });
5426
+ await timeOperation2("strategy evaluation", async () => {
5427
+ await (0, import_async3.runWithConcurrency)(tickers, signalsParallel, async (symbol) => {
5428
+ const strategySignals = await evaluateTicker(
5429
+ symbol,
5430
+ instrumentsBySymbol.get(symbol)
5431
+ );
5432
+ if (strategySignals.length > 0) {
5433
+ signals3.push(...strategySignals);
5434
+ }
5435
+ bar.tick(1, {
5436
+ found: import_chalk7.default.cyan(signals3.length),
5437
+ symbol: import_chalk7.default.gray(symbol)
5438
+ });
7102
5439
  });
7103
5440
  });
7104
- });
7105
- if (flags.notify) {
7106
- const telegramSignals = getTelegramDeliverableSignals(signals2);
7107
- if (!flags.skipScreenshots && telegramSignals.length > 0) {
7108
- await (0, import_cli2.makeScreenshots)(telegramSignals, interval2, flags.user);
5441
+ if (config2.notify) {
5442
+ const telegramSignals = getTelegramDeliverableSignals(signals3);
5443
+ if (!config2.skipScreenshots && telegramSignals.length > 0) {
5444
+ await (0, import_cli2.makeScreenshots)(telegramSignals, interval2, config2.userName);
5445
+ }
5446
+ await (0, import_cli2.sendToTG)(telegramSignals, interval2, config2.userName);
5447
+ await (0, import_cli2.sendRuntimeCloseNotificationsToTG)(
5448
+ runtimeCloseNotifications,
5449
+ config2.userName
5450
+ );
7109
5451
  }
7110
- await (0, import_cli2.sendToTG)(telegramSignals, interval2, flags.user);
7111
- await (0, import_cli2.sendRuntimeCloseNotificationsToTG)(
7112
- runtimeCloseNotifications,
7113
- flags.user
5452
+ import_logger5.logger.info(
5453
+ JSON.stringify(
5454
+ signals3.map((s) => s.symbol),
5455
+ null,
5456
+ 2
5457
+ )
7114
5458
  );
7115
- }
7116
- import_logger4.logger.info(
7117
- JSON.stringify(
7118
- signals2.map((s) => s.symbol),
7119
- null,
7120
- 2
7121
- )
7122
- );
7123
- if (flags.showSkipStats) {
7124
- logStrategySkipStats(runtimeStrategies, strategyStats);
7125
- }
7126
- } catch (error) {
7127
- status = "failed";
7128
- failureMessage = error?.message || String(error);
7129
- import_logger4.logger.error(
7130
- "signals failed: %s",
7131
- error?.message || String(error)
7132
- );
7133
- throw error;
7134
- } finally {
7135
- try {
7136
- await runtimeSignalEvaluations.flush();
5459
+ if (config2.showSkipStats) {
5460
+ logStrategySkipStats(runtimeStrategies, strategyStats);
5461
+ }
7137
5462
  } catch (error) {
7138
- import_logger4.logger.error(
7139
- "runtime signal evaluation flush failed: %s",
5463
+ status = "failed";
5464
+ failureMessage = error?.message || String(error);
5465
+ import_logger5.logger.error(
5466
+ "signals failed: %s",
7140
5467
  error?.message || String(error)
7141
5468
  );
7142
- }
7143
- const durationMs = Date.now() - startedAt;
7144
- if (activeSession?.deployment) {
7145
- await (0, import_tradingAccounts2.saveRuntimeDeploymentHeartbeat)(flags.user, {
7146
- deploymentId: activeSession.deployment.id,
7147
- status: getSignalsHeartbeatStatus({
7148
- cycleStatus: status,
7149
- continuous: options.session != null || Boolean(flags.watch)
7150
- }),
7151
- pid: process.pid,
7152
- startedAt: activeSession.startedAt,
7153
- lastCycleAt: Date.now(),
7154
- ...failureMessage ? { lastError: failureMessage } : {}
7155
- });
7156
- }
7157
- if (projectHooks && afterSignalsHookContext) {
5469
+ throw error;
5470
+ } finally {
7158
5471
  try {
7159
- await invokeAfterSignalsHooks(projectHooks, {
7160
- ...afterSignalsHookContext,
7161
- signals: [...signals2],
7162
- status,
7163
- durationMs
7164
- });
5472
+ await runtimeSignalEvaluations.flush();
7165
5473
  } catch (error) {
7166
- import_logger4.logger.error(
7167
- "afterSignals hook failed: %s",
5474
+ import_logger5.logger.error(
5475
+ "runtime signal evaluation flush failed: %s",
7168
5476
  error?.message || String(error)
7169
5477
  );
7170
5478
  }
5479
+ const durationMs = Date.now() - startedAt;
5480
+ if (activeSession?.deployment) {
5481
+ await (0, import_runtimeDeployments.saveRuntimeDeploymentHeartbeat)(config2.userName, {
5482
+ deploymentId: activeSession.deployment.id,
5483
+ status: getSignalsHeartbeatStatus({
5484
+ cycleStatus: status,
5485
+ continuous: options.session != null || Boolean(config2.watch)
5486
+ }),
5487
+ pid: process.pid,
5488
+ startedAt: activeSession.startedAt,
5489
+ lastCycleAt: Date.now(),
5490
+ ...failureMessage ? { lastError: failureMessage } : {}
5491
+ });
5492
+ }
5493
+ if (projectHooks && afterSignalsHookContext) {
5494
+ try {
5495
+ await invokeAfterSignalsHooks(projectHooks, {
5496
+ ...afterSignalsHookContext,
5497
+ signals: [...signals3],
5498
+ status,
5499
+ durationMs
5500
+ });
5501
+ } catch (error) {
5502
+ import_logger5.logger.error(
5503
+ "afterSignals hook failed: %s",
5504
+ error?.message || String(error)
5505
+ );
5506
+ }
5507
+ }
5508
+ if (config2.notify && durationMs > SLOW_SIGNALS_WARNING_MS) {
5509
+ try {
5510
+ await (0, import_cli2.sendTextToTG)(
5511
+ formatSlowSignalsWarning({
5512
+ durationMs,
5513
+ status,
5514
+ found: signals3.length
5515
+ }),
5516
+ { userName: config2.userName }
5517
+ );
5518
+ } catch (error) {
5519
+ import_logger5.logger.error(
5520
+ "slow signals warning failed: %s",
5521
+ error?.message || String(error)
5522
+ );
5523
+ }
5524
+ }
5525
+ import_logger5.logger.info(
5526
+ import_chalk7.default.yellow(
5527
+ `signals ${status} in ${formatDuration2(durationMs)} (found=${signals3.length})`
5528
+ )
5529
+ );
5530
+ import_logger5.logger.info("");
5531
+ import_logger5.logger.info("");
5532
+ import_logger5.logger.info("");
5533
+ }
5534
+ };
5535
+ const loadConfiguredSignalsScopes = async (deployment) => {
5536
+ const configuredStrategies = await loadRuntimeStrategies({
5537
+ userName: config2.userName,
5538
+ projectRoot,
5539
+ deployment,
5540
+ connectorName: config2.connectorName
5541
+ });
5542
+ const connectorName = await resolveSignalsConnectorName(
5543
+ deployment?.connectorName ?? config2.connectorName
5544
+ );
5545
+ const scopes = /* @__PURE__ */ new Map();
5546
+ for (const strategy of configuredStrategies) {
5547
+ const key = [
5548
+ connectorName,
5549
+ strategy.universe,
5550
+ strategy.accountId ?? "default",
5551
+ strategy.interval
5552
+ ].join(":");
5553
+ scopes.set(key, {
5554
+ connectorName,
5555
+ universe: strategy.universe,
5556
+ accountId: strategy.accountId,
5557
+ interval: strategy.interval
5558
+ });
5559
+ }
5560
+ return scopes;
5561
+ };
5562
+ const hasExplicitSignalsScope = () => Boolean(config2.hasExplicitScope);
5563
+ const signalsConfiguredScopesOnce2 = async () => {
5564
+ if (config2.updateOnly || config2.showTickersList || config2.deploymentId || hasExplicitSignalsScope()) {
5565
+ return signals2();
7171
5566
  }
7172
- if (flags.notify && durationMs > SLOW_SIGNALS_WARNING_MS) {
5567
+ const scopes = await loadConfiguredSignalsScopes();
5568
+ if (!scopes.size) return signals2();
5569
+ for (const scope of scopes.values()) {
5570
+ const session = await createSignalsSession2(
5571
+ createDefaultSignalsLifecycle(scope.interval),
5572
+ scope
5573
+ );
7173
5574
  try {
7174
- await (0, import_cli2.sendTextToTG)(
7175
- formatSlowSignalsWarning({
7176
- durationMs,
7177
- status,
7178
- found: signals2.length
7179
- }),
7180
- { userName: flags.user }
7181
- );
7182
- } catch (error) {
7183
- import_logger4.logger.error(
7184
- "slow signals warning failed: %s",
7185
- error?.message || String(error)
7186
- );
5575
+ await signals2({ session });
5576
+ } finally {
5577
+ await session.klineFeed?.close();
5578
+ session.lifecycle.clear();
7187
5579
  }
7188
5580
  }
7189
- import_logger4.logger.info(
7190
- import_chalk7.default.yellow(
7191
- `signals ${status} in ${formatDuration2(durationMs)} (found=${signals2.length})`
7192
- )
5581
+ };
5582
+ const signalsDaemon2 = async () => {
5583
+ if (config2.updateOnly || config2.showTickersList) {
5584
+ throw new Error(
5585
+ "Signals daemon does not support updateOnly or showTickersList mode"
5586
+ );
5587
+ }
5588
+ const abortController = new AbortController();
5589
+ const daemonDeployment = config2.deploymentId ? await (0, import_runtimeDeployments.getRuntimeDeployment)(config2.userName, config2.deploymentId) : null;
5590
+ if (config2.deploymentId && !daemonDeployment) {
5591
+ throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
5592
+ }
5593
+ const sessions = /* @__PURE__ */ new Map();
5594
+ const lastBoundaryByScope = /* @__PURE__ */ new Map();
5595
+ const stop = (signalName) => {
5596
+ import_logger5.logger.info("signals daemon stopping by %s", signalName);
5597
+ abortController.abort();
5598
+ };
5599
+ const stopOnSigint = () => stop("SIGINT");
5600
+ const stopOnSigterm = () => stop("SIGTERM");
5601
+ process.once("SIGINT", stopOnSigint);
5602
+ process.once("SIGTERM", stopOnSigterm);
5603
+ import_logger5.logger.info(
5604
+ "signals daemon started (config-driven scopes, fallback interval=%s)",
5605
+ interval
7193
5606
  );
7194
- import_logger4.logger.info("");
7195
- import_logger4.logger.info("");
7196
- import_logger4.logger.info("");
7197
- }
7198
- };
7199
- var loadConfiguredSignalsScopes = async (deployment) => {
7200
- const configuredStrategies = await loadRuntimeStrategies({
7201
- userName: flags.user,
7202
- projectRoot,
7203
- deployment,
7204
- connectorName: String(flags.connector)
7205
- });
7206
- const connectorName = await resolveSignalsConnectorName(
7207
- deployment?.connectorName ?? flags.connector
7208
- );
7209
- const scopes = /* @__PURE__ */ new Map();
7210
- for (const strategy of configuredStrategies) {
7211
- const key = [
7212
- connectorName,
7213
- strategy.universe,
7214
- strategy.accountId ?? "default",
7215
- strategy.interval
7216
- ].join(":");
7217
- scopes.set(key, {
7218
- connectorName,
7219
- universe: strategy.universe,
7220
- accountId: strategy.accountId,
7221
- interval: strategy.interval
7222
- });
7223
- }
7224
- return scopes;
5607
+ try {
5608
+ await runSignalsDaemon({
5609
+ intervalMs: 6e4,
5610
+ settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
5611
+ signal: abortController.signal,
5612
+ runCycle: async () => {
5613
+ const scopes = await loadConfiguredSignalsScopes(daemonDeployment);
5614
+ for (const [key, staleSession] of sessions) {
5615
+ if (scopes.has(key)) continue;
5616
+ await staleSession.klineFeed?.close();
5617
+ staleSession.lifecycle.clear();
5618
+ sessions.delete(key);
5619
+ lastBoundaryByScope.delete(key);
5620
+ }
5621
+ for (const [key, scope] of scopes) {
5622
+ const scopeIntervalMs = Number(scope.interval) * 6e4;
5623
+ const boundary = Math.floor(Date.now() / scopeIntervalMs) * scopeIntervalMs;
5624
+ if (lastBoundaryByScope.get(key) === boundary) continue;
5625
+ let session = sessions.get(key);
5626
+ if (!session) {
5627
+ session = await createSignalsSession2(
5628
+ createDefaultSignalsLifecycle(scope.interval),
5629
+ scope
5630
+ );
5631
+ sessions.set(key, session);
5632
+ }
5633
+ if (!session.klineFeed && isSignalsKlineWsEnabled() && session.connectorName.toLowerCase() === "bybit") {
5634
+ session.klineFeed = await createSignalsKlineFeed({
5635
+ config: {
5636
+ userName: config2.userName,
5637
+ universe: session.universe,
5638
+ accountId: session.accountId,
5639
+ deploymentId: session.deployment?.id
5640
+ },
5641
+ interval: session.interval,
5642
+ universe: session.universe
5643
+ });
5644
+ import_logger5.logger.info(
5645
+ "Bybit websocket candle feed enabled (account=%s, universe=%s, interval=%s)",
5646
+ session.accountId ?? "default",
5647
+ session.universe,
5648
+ session.interval
5649
+ );
5650
+ }
5651
+ try {
5652
+ await signals2({ session });
5653
+ lastBoundaryByScope.set(key, boundary);
5654
+ } catch (error) {
5655
+ await session.klineFeed?.close();
5656
+ session.lifecycle.clear();
5657
+ sessions.delete(key);
5658
+ throw error;
5659
+ }
5660
+ }
5661
+ const memory = process.memoryUsage();
5662
+ const stateKeys = [...sessions.values()].reduce(
5663
+ (sum, session) => sum + session.lifecycle.size(),
5664
+ 0
5665
+ );
5666
+ import_logger5.logger.info(
5667
+ "signals daemon resources: rss=%sMB heapUsed=%sMB heapTotal=%sMB stateKeys=%s scopes=%s",
5668
+ (memory.rss / 1024 / 1024).toFixed(1),
5669
+ (memory.heapUsed / 1024 / 1024).toFixed(1),
5670
+ (memory.heapTotal / 1024 / 1024).toFixed(1),
5671
+ stateKeys,
5672
+ sessions.size
5673
+ );
5674
+ },
5675
+ onCycleError: (error) => {
5676
+ import_logger5.logger.error(
5677
+ "signals daemon cycle failed: %s",
5678
+ error?.message || String(error)
5679
+ );
5680
+ }
5681
+ });
5682
+ } finally {
5683
+ process.removeListener("SIGINT", stopOnSigint);
5684
+ process.removeListener("SIGTERM", stopOnSigterm);
5685
+ for (const session of sessions.values()) {
5686
+ await session.klineFeed?.close();
5687
+ session.lifecycle.clear();
5688
+ if (session.deployment) {
5689
+ await (0, import_runtimeDeployments.saveRuntimeDeploymentHeartbeat)(config2.userName, {
5690
+ deploymentId: session.deployment.id,
5691
+ status: "stopped",
5692
+ pid: process.pid,
5693
+ startedAt: session.startedAt,
5694
+ lastCycleAt: Date.now()
5695
+ });
5696
+ }
5697
+ }
5698
+ }
5699
+ };
5700
+ return {
5701
+ createSession: createSignalsSession2,
5702
+ runCycle: signals2,
5703
+ runConfiguredScopesOnce: signalsConfiguredScopesOnce2,
5704
+ runDaemon: signalsDaemon2
5705
+ };
7225
5706
  };
7226
- var hasExplicitSignalsScope = () => process.argv.some(
5707
+
5708
+ // src/scripts/signals.ts
5709
+ import_args.default.option(["t", "tickers"], "Selected tickers");
5710
+ import_args.default.option(["e", "exclude"], "Exclude tickers from tests");
5711
+ import_args.default.option(["l", "tickersLimit"], "Tickers limit");
5712
+ import_args.default.option(["f", "timeframe"], "Timeframe", 15);
5713
+ import_args.default.option(["m", "makeOrders"], "Make orders");
5714
+ import_args.default.option(["N", "notify"], "Send message in Telegram", false);
5715
+ import_args.default.option(["S", "skipScreenshots"], "Skip screenshot generation", false);
5716
+ import_args.default.option(["u", "updateOnly"], "Only update tickers history", false);
5717
+ import_args.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
5718
+ import_args.default.option(["L", "showTickersList"], "Just show only ticker list", false);
5719
+ import_args.default.option(
5720
+ ["p", "parallel"],
5721
+ "Signal evaluation worker count",
5722
+ Number(process.env.SIGNALS_PARALLEL || 4)
5723
+ );
5724
+ import_args.default.option(
5725
+ ["R", "showSkipStats"],
5726
+ "Show aggregated skip stats by strategy",
5727
+ false
5728
+ );
5729
+ import_args.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
5730
+ import_args.default.option(["U", "user"], "Use user confg", "root");
5731
+ import_args.default.option(["w", "watch"], "Keep signals running on candle boundaries", false);
5732
+ import_args.default.option(
5733
+ ["d", "settleDelayMs"],
5734
+ "Delay after candle close before a daemon cycle",
5735
+ Number(process.env.SIGNALS_DAEMON_SETTLE_DELAY_MS || 5e3)
5736
+ );
5737
+ import_args.default.option(
5738
+ ["o", "connector"],
5739
+ "Connector provider or name for signals (e.g. bybit, binance, coinbase, custom)",
5740
+ "bybit"
5741
+ );
5742
+ import_args.default.option(["V", "universe"], "Market universe (crypto or tradfi)", "crypto");
5743
+ import_args.default.option(["A", "account"], "Trading account id");
5744
+ import_args.default.option(["D", "deployment"], "Runtime deployment id");
5745
+ var flags = import_args.default.parse(process.argv);
5746
+ var hasExplicitScope = process.argv.some(
7227
5747
  (argument) => [
7228
5748
  "-f",
7229
5749
  "--timeframe",
@@ -7233,148 +5753,38 @@ var hasExplicitSignalsScope = () => process.argv.some(
7233
5753
  "--account",
7234
5754
  "-D",
7235
5755
  "--deployment"
7236
- ].some(
7237
- (option) => argument === option || argument.startsWith(`${option}=`)
7238
- )
5756
+ ].some((option) => argument === option || argument.startsWith(`${option}=`))
7239
5757
  );
7240
- var signalsConfiguredScopesOnce = async () => {
7241
- if (flags.updateOnly || flags.showTickersList || flags.deployment || hasExplicitSignalsScope()) {
7242
- return signals();
7243
- }
7244
- const scopes = await loadConfiguredSignalsScopes();
7245
- if (!scopes.size) return signals();
7246
- for (const scope of scopes.values()) {
7247
- const session = await createSignalsSession(
7248
- createDefaultSignalsLifecycle(scope.interval),
7249
- scope
7250
- );
7251
- try {
7252
- await signals({ session });
7253
- } finally {
7254
- await session.klineFeed?.close();
7255
- session.lifecycle.clear();
7256
- }
7257
- }
7258
- };
7259
- var signalsDaemon = async () => {
7260
- if (flags.updateOnly || flags.showTickersList) {
7261
- throw new Error(
7262
- "Signals daemon does not support updateOnly or showTickersList mode"
7263
- );
7264
- }
7265
- const abortController = new AbortController();
7266
- const daemonDeployment = flags.deployment ? await (0, import_tradingAccounts2.getRuntimeDeployment)(flags.user, String(flags.deployment)) : null;
7267
- if (flags.deployment && !daemonDeployment) {
7268
- throw new Error(`Runtime deployment not found: ${flags.deployment}`);
7269
- }
7270
- const sessions = /* @__PURE__ */ new Map();
7271
- const lastBoundaryByScope = /* @__PURE__ */ new Map();
7272
- const stop = (signalName) => {
7273
- import_logger4.logger.info("signals daemon stopping by %s", signalName);
7274
- abortController.abort();
7275
- };
7276
- const stopOnSigint = () => stop("SIGINT");
7277
- const stopOnSigterm = () => stop("SIGTERM");
7278
- process.once("SIGINT", stopOnSigint);
7279
- process.once("SIGTERM", stopOnSigterm);
7280
- import_logger4.logger.info(
7281
- "signals daemon started (config-driven scopes, fallback interval=%s)",
7282
- interval
7283
- );
7284
- try {
7285
- await runSignalsDaemon({
7286
- intervalMs: 6e4,
7287
- settleDelayMs: resolveNonNegativeInteger(flags.settleDelayMs, 5e3),
7288
- signal: abortController.signal,
7289
- runCycle: async () => {
7290
- const scopes = await loadConfiguredSignalsScopes(daemonDeployment);
7291
- for (const [key, staleSession] of sessions) {
7292
- if (scopes.has(key)) continue;
7293
- await staleSession.klineFeed?.close();
7294
- staleSession.lifecycle.clear();
7295
- sessions.delete(key);
7296
- lastBoundaryByScope.delete(key);
7297
- }
7298
- for (const [key, scope] of scopes) {
7299
- const scopeIntervalMs = Number(scope.interval) * 6e4;
7300
- const boundary = Math.floor(Date.now() / scopeIntervalMs) * scopeIntervalMs;
7301
- if (lastBoundaryByScope.get(key) === boundary) continue;
7302
- let session = sessions.get(key);
7303
- if (!session) {
7304
- session = await createSignalsSession(
7305
- createDefaultSignalsLifecycle(scope.interval),
7306
- scope
7307
- );
7308
- sessions.set(key, session);
7309
- }
7310
- if (!session.klineFeed && isSignalsKlineWsEnabled() && session.connectorName.toLowerCase() === "bybit") {
7311
- session.klineFeed = await createSignalsKlineFeed({
7312
- config: {
7313
- userName: flags.user,
7314
- universe: session.universe,
7315
- accountId: session.accountId,
7316
- deploymentId: session.deployment?.id
7317
- },
7318
- interval: session.interval,
7319
- universe: session.universe
7320
- });
7321
- import_logger4.logger.info(
7322
- "Bybit websocket candle feed enabled (account=%s, universe=%s, interval=%s)",
7323
- session.accountId ?? "default",
7324
- session.universe,
7325
- session.interval
7326
- );
7327
- }
7328
- try {
7329
- await signals({ session });
7330
- lastBoundaryByScope.set(key, boundary);
7331
- } catch (error) {
7332
- await session.klineFeed?.close();
7333
- session.lifecycle.clear();
7334
- sessions.delete(key);
7335
- throw error;
7336
- }
7337
- }
7338
- const memory = process.memoryUsage();
7339
- const stateKeys = [...sessions.values()].reduce(
7340
- (sum, session) => sum + session.lifecycle.size(),
7341
- 0
7342
- );
7343
- import_logger4.logger.info(
7344
- "signals daemon resources: rss=%sMB heapUsed=%sMB heapTotal=%sMB stateKeys=%s scopes=%s",
7345
- (memory.rss / 1024 / 1024).toFixed(1),
7346
- (memory.heapUsed / 1024 / 1024).toFixed(1),
7347
- (memory.heapTotal / 1024 / 1024).toFixed(1),
7348
- stateKeys,
7349
- sessions.size
7350
- );
7351
- },
7352
- onCycleError: (error) => {
7353
- import_logger4.logger.error(
7354
- "signals daemon cycle failed: %s",
7355
- error?.message || String(error)
7356
- );
7357
- }
7358
- });
7359
- } finally {
7360
- process.removeListener("SIGINT", stopOnSigint);
7361
- process.removeListener("SIGTERM", stopOnSigterm);
7362
- for (const session of sessions.values()) {
7363
- await session.klineFeed?.close();
7364
- session.lifecycle.clear();
7365
- if (session.deployment) {
7366
- await (0, import_tradingAccounts2.saveRuntimeDeploymentHeartbeat)(flags.user, {
7367
- deploymentId: session.deployment.id,
7368
- status: "stopped",
7369
- pid: process.pid,
7370
- startedAt: session.startedAt,
7371
- lastCycleAt: Date.now()
7372
- });
7373
- }
7374
- }
7375
- }
7376
- };
7377
- var main = () => flags.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
5758
+ var config = {
5759
+ projectRoot: String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd(),
5760
+ userName: String(flags.user || "root"),
5761
+ interval: String(flags.timeframe ?? 15),
5762
+ connectorName: String(flags.connector || "bybit"),
5763
+ universe: flags.universe,
5764
+ accountId: flags.account ? String(flags.account) : void 0,
5765
+ deploymentId: flags.deployment ? String(flags.deployment) : void 0,
5766
+ tickers: flags.tickers,
5767
+ exclude: flags.exclude,
5768
+ tickersLimit: flags.tickersLimit,
5769
+ chunk: flags.chunk,
5770
+ makeOrders: Boolean(flags.makeOrders),
5771
+ notify: Boolean(flags.notify),
5772
+ skipScreenshots: Boolean(flags.skipScreenshots),
5773
+ updateOnly: Boolean(flags.updateOnly),
5774
+ cacheOnly: Boolean(flags.cacheOnly),
5775
+ showTickersList: Boolean(flags.showTickersList),
5776
+ showSkipStats: Boolean(flags.showSkipStats),
5777
+ parallel: flags.parallel,
5778
+ watch: Boolean(flags.watch),
5779
+ settleDelayMs: flags.settleDelayMs,
5780
+ hasExplicitScope
5781
+ };
5782
+ var runner = createSignalsRunner(config);
5783
+ var createSignalsSession = runner.createSession;
5784
+ var signals = runner.runCycle;
5785
+ var signalsConfiguredScopesOnce = runner.runConfiguredScopesOnce;
5786
+ var signalsDaemon = runner.runDaemon;
5787
+ var main = () => config.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
7378
5788
  // Annotate the CommonJS export names for ESM import in node:
7379
5789
  0 && (module.exports = {
7380
5790
  createSignalsSession,