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