@tradejs/cli 2.0.5 → 2.0.7
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 +3145 -1827
- package/dist/lib/aiExport.js +1822 -0
- package/dist/lib/binanceMarketContextBackfill.js +97 -88
- package/dist/lib/binanceMarketData.js +6 -3
- package/dist/lib/marketContextPrepare.js +149 -125
- package/dist/lib/runEnvironment.js +100 -55
- package/dist/lib/runFormatting.js +52 -37
- package/dist/lib/runtimeLineage.js +255 -0
- package/dist/lib/runtimeParityDetails.js +24 -1
- package/dist/lib/runtimeSignalsLoader.js +19 -0
- package/dist/lib/runtimeSignalsStorage.js +3 -0
- package/dist/lib/runtimeTradeSync.js +40 -11
- package/dist/lib/timeWindow.js +44 -16
- package/dist/scripts/aiExport.js +252 -125
- package/dist/scripts/aiPocketSearch.js +52 -37
- package/dist/scripts/aiTrain.js +52 -37
- package/dist/scripts/backtest.js +222 -144
- package/dist/scripts/binanceBreadthUniversesUpdate.js +120 -0
- package/dist/scripts/binanceMarketIngest.js +32 -33
- package/dist/scripts/candlesMigrateProvider.js +648 -419
- package/dist/scripts/doctor.js +648 -419
- package/dist/scripts/mlExport.js +57 -39
- package/dist/scripts/replay.js +1040 -255
- package/dist/scripts/replayRunner.js +1040 -255
- package/dist/scripts/replayRuntimeEvidence.js +3 -1
- package/dist/scripts/resolveExportStrategy.js +7 -2
- package/dist/scripts/results.js +52 -37
- package/dist/scripts/runtimeParity.js +193 -141
- package/dist/scripts/signals.js +433 -144
- package/dist/scripts/signalsDaemon.js +433 -144
- package/dist/scripts/signalsSummary.js +40 -11
- package/package.json +15 -14
|
@@ -34,9 +34,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
34
34
|
));
|
|
35
35
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
36
|
|
|
37
|
-
// ../../node_modules/
|
|
37
|
+
// ../../node_modules/ms/index.js
|
|
38
38
|
var require_ms = __commonJS({
|
|
39
|
-
"../../node_modules/
|
|
39
|
+
"../../node_modules/ms/index.js"(exports2, module2) {
|
|
40
40
|
"use strict";
|
|
41
41
|
var s = 1e3;
|
|
42
42
|
var m = s * 60;
|
|
@@ -151,9 +151,9 @@ var require_ms = __commonJS({
|
|
|
151
151
|
}
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
-
// ../../node_modules/debug/src/common.js
|
|
154
|
+
// ../../node_modules/list-it/node_modules/debug/src/common.js
|
|
155
155
|
var require_common = __commonJS({
|
|
156
|
-
"../../node_modules/debug/src/common.js"(exports2, module2) {
|
|
156
|
+
"../../node_modules/list-it/node_modules/debug/src/common.js"(exports2, module2) {
|
|
157
157
|
"use strict";
|
|
158
158
|
function setup(env) {
|
|
159
159
|
createDebug.debug = createDebug;
|
|
@@ -255,50 +255,64 @@ var require_common = __commonJS({
|
|
|
255
255
|
createDebug.namespaces = namespaces;
|
|
256
256
|
createDebug.names = [];
|
|
257
257
|
createDebug.skips = [];
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
264
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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;
|
|
268
286
|
} else {
|
|
269
|
-
|
|
287
|
+
return false;
|
|
270
288
|
}
|
|
271
289
|
}
|
|
290
|
+
while (templateIndex < template.length && template[templateIndex] === "*") {
|
|
291
|
+
templateIndex++;
|
|
292
|
+
}
|
|
293
|
+
return templateIndex === template.length;
|
|
272
294
|
}
|
|
273
295
|
function disable() {
|
|
274
296
|
const namespaces = [
|
|
275
|
-
...createDebug.names
|
|
276
|
-
...createDebug.skips.map(
|
|
297
|
+
...createDebug.names,
|
|
298
|
+
...createDebug.skips.map((namespace) => "-" + namespace)
|
|
277
299
|
].join(",");
|
|
278
300
|
createDebug.enable("");
|
|
279
301
|
return namespaces;
|
|
280
302
|
}
|
|
281
303
|
function enabled(name) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}
|
|
285
|
-
let i;
|
|
286
|
-
let len;
|
|
287
|
-
for (i = 0, len = createDebug.skips.length; i < len; i++) {
|
|
288
|
-
if (createDebug.skips[i].test(name)) {
|
|
304
|
+
for (const skip of createDebug.skips) {
|
|
305
|
+
if (matchesTemplate(name, skip)) {
|
|
289
306
|
return false;
|
|
290
307
|
}
|
|
291
308
|
}
|
|
292
|
-
for (
|
|
293
|
-
if (
|
|
309
|
+
for (const ns of createDebug.names) {
|
|
310
|
+
if (matchesTemplate(name, ns)) {
|
|
294
311
|
return true;
|
|
295
312
|
}
|
|
296
313
|
}
|
|
297
314
|
return false;
|
|
298
315
|
}
|
|
299
|
-
function toNamespace(regexp) {
|
|
300
|
-
return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\.\*\?$/, "*");
|
|
301
|
-
}
|
|
302
316
|
function coerce(val) {
|
|
303
317
|
if (val instanceof Error) {
|
|
304
318
|
return val.stack || val.message;
|
|
@@ -315,9 +329,9 @@ var require_common = __commonJS({
|
|
|
315
329
|
}
|
|
316
330
|
});
|
|
317
331
|
|
|
318
|
-
// ../../node_modules/debug/src/browser.js
|
|
332
|
+
// ../../node_modules/list-it/node_modules/debug/src/browser.js
|
|
319
333
|
var require_browser = __commonJS({
|
|
320
|
-
"../../node_modules/debug/src/browser.js"(exports2, module2) {
|
|
334
|
+
"../../node_modules/list-it/node_modules/debug/src/browser.js"(exports2, module2) {
|
|
321
335
|
"use strict";
|
|
322
336
|
exports2.formatArgs = formatArgs;
|
|
323
337
|
exports2.save = save;
|
|
@@ -418,10 +432,11 @@ var require_browser = __commonJS({
|
|
|
418
432
|
if (typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
|
|
419
433
|
return false;
|
|
420
434
|
}
|
|
435
|
+
let m;
|
|
421
436
|
return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773
|
|
422
437
|
typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?
|
|
423
438
|
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
|
424
|
-
typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(
|
|
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
|
|
425
440
|
typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
|
|
426
441
|
}
|
|
427
442
|
function formatArgs(args2) {
|
|
@@ -459,7 +474,7 @@ var require_browser = __commonJS({
|
|
|
459
474
|
function load() {
|
|
460
475
|
let r;
|
|
461
476
|
try {
|
|
462
|
-
r = exports2.storage.getItem("debug");
|
|
477
|
+
r = exports2.storage.getItem("debug") || exports2.storage.getItem("DEBUG");
|
|
463
478
|
} catch (error) {
|
|
464
479
|
}
|
|
465
480
|
if (!r && typeof process !== "undefined" && "env" in process) {
|
|
@@ -600,9 +615,9 @@ var require_supports_color = __commonJS({
|
|
|
600
615
|
}
|
|
601
616
|
});
|
|
602
617
|
|
|
603
|
-
// ../../node_modules/debug/src/node.js
|
|
618
|
+
// ../../node_modules/list-it/node_modules/debug/src/node.js
|
|
604
619
|
var require_node = __commonJS({
|
|
605
|
-
"../../node_modules/debug/src/node.js"(exports2, module2) {
|
|
620
|
+
"../../node_modules/list-it/node_modules/debug/src/node.js"(exports2, module2) {
|
|
606
621
|
"use strict";
|
|
607
622
|
var tty = require("tty");
|
|
608
623
|
var util = require("util");
|
|
@@ -743,7 +758,7 @@ var require_node = __commonJS({
|
|
|
743
758
|
return (/* @__PURE__ */ new Date()).toISOString() + " ";
|
|
744
759
|
}
|
|
745
760
|
function log(...args2) {
|
|
746
|
-
return process.stderr.write(util.
|
|
761
|
+
return process.stderr.write(util.formatWithOptions(exports2.inspectOpts, ...args2) + "\n");
|
|
747
762
|
}
|
|
748
763
|
function save(namespaces) {
|
|
749
764
|
if (namespaces) {
|
|
@@ -775,9 +790,9 @@ var require_node = __commonJS({
|
|
|
775
790
|
}
|
|
776
791
|
});
|
|
777
792
|
|
|
778
|
-
// ../../node_modules/debug/src/index.js
|
|
793
|
+
// ../../node_modules/list-it/node_modules/debug/src/index.js
|
|
779
794
|
var require_src = __commonJS({
|
|
780
|
-
"../../node_modules/debug/src/index.js"(exports2, module2) {
|
|
795
|
+
"../../node_modules/list-it/node_modules/debug/src/index.js"(exports2, module2) {
|
|
781
796
|
"use strict";
|
|
782
797
|
if (typeof process === "undefined" || process.type === "renderer" || process.browser === true || process.__nwjs) {
|
|
783
798
|
module2.exports = require_browser();
|
|
@@ -2241,11 +2256,30 @@ var resolveTimeWindow = ({
|
|
|
2241
2256
|
endTime,
|
|
2242
2257
|
nowMs = Date.now(),
|
|
2243
2258
|
defaultStartMs,
|
|
2244
|
-
defaultEndMs
|
|
2259
|
+
defaultEndMs,
|
|
2260
|
+
closedIntervalMs
|
|
2245
2261
|
}) => {
|
|
2246
2262
|
const explicitStart = toEpochMs(startTime);
|
|
2247
2263
|
const explicitEnd = toEpochMs(endTime);
|
|
2248
2264
|
const resolvedDays = toPositiveNumber(days);
|
|
2265
|
+
const alignToLastClosedInterval = (window2, preserveDuration) => {
|
|
2266
|
+
if (typeof closedIntervalMs !== "number" || !Number.isFinite(closedIntervalMs) || closedIntervalMs <= 0) {
|
|
2267
|
+
return window2;
|
|
2268
|
+
}
|
|
2269
|
+
const alignedEnd = Math.floor(window2.end / closedIntervalMs) * closedIntervalMs - 1;
|
|
2270
|
+
const delta = window2.end - alignedEnd;
|
|
2271
|
+
const alignedStart = preserveDuration ? window2.start - delta : window2.start;
|
|
2272
|
+
if (alignedStart >= alignedEnd) {
|
|
2273
|
+
throw new Error(
|
|
2274
|
+
`Invalid closed-candle window: start (${alignedStart}) must be less than end (${alignedEnd})`
|
|
2275
|
+
);
|
|
2276
|
+
}
|
|
2277
|
+
return {
|
|
2278
|
+
...window2,
|
|
2279
|
+
start: Math.trunc(alignedStart),
|
|
2280
|
+
end: Math.trunc(alignedEnd)
|
|
2281
|
+
};
|
|
2282
|
+
};
|
|
2249
2283
|
if (explicitStart != null || explicitEnd != null) {
|
|
2250
2284
|
const resolvedStart = explicitStart ?? (resolvedDays != null && explicitEnd != null ? explicitEnd - resolvedDays * ONE_DAY_MS : defaultStartMs);
|
|
2251
2285
|
const resolvedEnd2 = explicitEnd ?? (resolvedDays != null && explicitStart != null ? explicitStart + resolvedDays * ONE_DAY_MS : defaultEndMs ?? nowMs);
|
|
@@ -2254,11 +2288,14 @@ var resolveTimeWindow = ({
|
|
|
2254
2288
|
`Invalid time window: startTime (${resolvedStart}) must be less than endTime (${resolvedEnd2})`
|
|
2255
2289
|
);
|
|
2256
2290
|
}
|
|
2257
|
-
return
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2291
|
+
return alignToLastClosedInterval(
|
|
2292
|
+
{
|
|
2293
|
+
start: resolvedStart,
|
|
2294
|
+
end: resolvedEnd2,
|
|
2295
|
+
source: "explicit"
|
|
2296
|
+
},
|
|
2297
|
+
explicitStart == null && resolvedDays != null
|
|
2298
|
+
);
|
|
2262
2299
|
}
|
|
2263
2300
|
if (resolvedDays != null) {
|
|
2264
2301
|
const resolvedEnd2 = defaultEndMs ?? nowMs;
|
|
@@ -2268,11 +2305,14 @@ var resolveTimeWindow = ({
|
|
|
2268
2305
|
`Invalid time window: computed start (${resolvedStart}) must be less than end (${resolvedEnd2})`
|
|
2269
2306
|
);
|
|
2270
2307
|
}
|
|
2271
|
-
return
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2308
|
+
return alignToLastClosedInterval(
|
|
2309
|
+
{
|
|
2310
|
+
start: Math.trunc(resolvedStart),
|
|
2311
|
+
end: Math.trunc(resolvedEnd2),
|
|
2312
|
+
source: "days"
|
|
2313
|
+
},
|
|
2314
|
+
true
|
|
2315
|
+
);
|
|
2276
2316
|
}
|
|
2277
2317
|
const resolvedEnd = defaultEndMs ?? nowMs;
|
|
2278
2318
|
if (defaultStartMs >= resolvedEnd) {
|
|
@@ -2280,11 +2320,14 @@ var resolveTimeWindow = ({
|
|
|
2280
2320
|
`Invalid default time window: start (${defaultStartMs}) must be less than end (${resolvedEnd})`
|
|
2281
2321
|
);
|
|
2282
2322
|
}
|
|
2283
|
-
return
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2323
|
+
return alignToLastClosedInterval(
|
|
2324
|
+
{
|
|
2325
|
+
start: Math.trunc(defaultStartMs),
|
|
2326
|
+
end: Math.trunc(resolvedEnd),
|
|
2327
|
+
source: "default"
|
|
2328
|
+
},
|
|
2329
|
+
true
|
|
2330
|
+
);
|
|
2288
2331
|
};
|
|
2289
2332
|
|
|
2290
2333
|
// src/lib/runFormatting.ts
|
|
@@ -2314,6 +2357,7 @@ var import_progress = __toESM(require("progress"));
|
|
|
2314
2357
|
var import_chalk = __toESM(require("chalk"));
|
|
2315
2358
|
var import_connectors = require("@tradejs/connectors");
|
|
2316
2359
|
var import_connectors2 = require("@tradejs/node/connectors");
|
|
2360
|
+
var import_strategies = require("@tradejs/node/strategies");
|
|
2317
2361
|
var import_timescale = require("@tradejs/infra/timescale");
|
|
2318
2362
|
|
|
2319
2363
|
// src/lib/binanceMarketData.ts
|
|
@@ -2323,14 +2367,6 @@ var MARKET_FEATURE_INTERVAL_MS = {
|
|
|
2323
2367
|
"15m": 9e5,
|
|
2324
2368
|
"1h": 36e5
|
|
2325
2369
|
};
|
|
2326
|
-
var STABLE_QUOTE_SYMBOLS = /* @__PURE__ */ new Set([
|
|
2327
|
-
"USDCUSDT",
|
|
2328
|
-
"FDUSDUSDT",
|
|
2329
|
-
"TUSDUSDT",
|
|
2330
|
-
"BUSDUSDT",
|
|
2331
|
-
"USDPUSDT",
|
|
2332
|
-
"DAIUSDT"
|
|
2333
|
-
]);
|
|
2334
2370
|
var safeDivide = (num, den) => Number.isFinite(num) && Number.isFinite(den) && den !== 0 ? num / den : null;
|
|
2335
2371
|
var mean = (values) => values.length ? values.reduce((sum, value) => sum + value, 0) / values.length : null;
|
|
2336
2372
|
var standardDeviation = (values) => {
|
|
@@ -2374,9 +2410,6 @@ var classifyBtcAltRegime = ({
|
|
|
2374
2410
|
if (btcVsAltReturn24h < -5e-3) return "alt_lead";
|
|
2375
2411
|
return "neutral";
|
|
2376
2412
|
};
|
|
2377
|
-
var selectBreadthUniverseFromTickers = (tickers, limit) => tickers.filter(
|
|
2378
|
-
(ticker) => ticker.symbol.endsWith("USDT") && ticker.symbol !== "BTCUSDT" && !STABLE_QUOTE_SYMBOLS.has(ticker.symbol) && Number.isFinite(ticker.turnover24h) && ticker.turnover24h > 0
|
|
2379
|
-
).sort((a, b) => b.turnover24h - a.turnover24h).slice(0, Math.max(0, limit)).map((ticker) => ticker.symbol);
|
|
2380
2413
|
var aggregateAggTradesToRows = ({
|
|
2381
2414
|
symbol,
|
|
2382
2415
|
interval: interval2,
|
|
@@ -2858,10 +2891,6 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
2858
2891
|
process.env.BINANCE_MARKET_CONTEXT_TRADE_FLOW_SYMBOL_LIMIT,
|
|
2859
2892
|
2
|
|
2860
2893
|
);
|
|
2861
|
-
const breadthLimit = asInt(
|
|
2862
|
-
process.env.BINANCE_MARKET_CONTEXT_BREADTH_LIMIT,
|
|
2863
|
-
30
|
|
2864
|
-
);
|
|
2865
2894
|
const breadthChunkDays = asFloat(
|
|
2866
2895
|
process.env.BINANCE_MARKET_CONTEXT_BREADTH_CHUNK_DAYS,
|
|
2867
2896
|
30
|
|
@@ -2984,88 +3013,113 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
2984
3013
|
}
|
|
2985
3014
|
}
|
|
2986
3015
|
if (includeBreadth) {
|
|
2987
|
-
const
|
|
2988
|
-
const breadthSymbols =
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
);
|
|
2992
|
-
const universe = `binance_top${breadthSymbols.length}_usdt`;
|
|
2993
|
-
const coverage = await (0, import_timescale.getMarketBreadthCoverage)({
|
|
2994
|
-
universe,
|
|
2995
|
-
interval: interval2,
|
|
2996
|
-
startMs: breadthStartMs,
|
|
2997
|
-
endMs
|
|
2998
|
-
});
|
|
2999
|
-
const hasBtcAltMetrics = (coverage?.btcAltMetricsRows ?? 0) >= Math.floor(Math.max(1, coverage?.rows ?? 0) * 0.9);
|
|
3000
|
-
if (!hasCoverage({
|
|
3001
|
-
coverage,
|
|
3016
|
+
const breadthUniverses = (0, import_strategies.getBinanceBreadthUniverses)();
|
|
3017
|
+
const breadthSymbols = breadthUniverses.at(-1)?.symbols ?? [];
|
|
3018
|
+
const connectorInterval = marketIntervalToConnectorInterval(interval2);
|
|
3019
|
+
const chunks = buildBreadthBackfillChunks({
|
|
3002
3020
|
startMs: breadthStartMs,
|
|
3003
3021
|
endMs,
|
|
3004
|
-
intervalMs
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
chunks,
|
|
3015
|
-
coverage,
|
|
3016
|
-
intervalMs
|
|
3017
|
-
});
|
|
3018
|
-
const bar = new import_progress.default(
|
|
3019
|
-
"breadth :current/:total [:bar][:percent] :etas(s) candles=:candles skip=:skip chunk=:chunk :symbol",
|
|
3020
|
-
{
|
|
3021
|
-
total: Math.max(1, missingChunks.length * breadthSymbols.length),
|
|
3022
|
-
width: 24
|
|
3023
|
-
}
|
|
3024
|
-
);
|
|
3025
|
-
let candlesRead = 0;
|
|
3026
|
-
let skippedBreadthChunks = chunks.length - missingChunks.length;
|
|
3027
|
-
if (!missingChunks.length) {
|
|
3028
|
-
bar.tick(1, {
|
|
3029
|
-
candles: 0,
|
|
3030
|
-
skip: skippedBreadthChunks,
|
|
3031
|
-
chunk: "cached",
|
|
3032
|
-
symbol: universe
|
|
3022
|
+
intervalMs,
|
|
3023
|
+
chunkDays: breadthChunkDays
|
|
3024
|
+
});
|
|
3025
|
+
const plans = await Promise.all(
|
|
3026
|
+
breadthUniverses.map(async (definition) => {
|
|
3027
|
+
const coverage = await (0, import_timescale.getMarketBreadthCoverage)({
|
|
3028
|
+
universe: definition.universe,
|
|
3029
|
+
interval: interval2,
|
|
3030
|
+
startMs: breadthStartMs,
|
|
3031
|
+
endMs
|
|
3033
3032
|
});
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
candlesBySymbol[symbol] = candles;
|
|
3050
|
-
candlesRead += candles.length;
|
|
3051
|
-
bar.tick(1, {
|
|
3052
|
-
candles: candlesRead,
|
|
3053
|
-
skip: skippedBreadthChunks,
|
|
3054
|
-
chunk: `${originalChunkIndex + 1}/${chunks.length}`,
|
|
3055
|
-
symbol
|
|
3056
|
-
});
|
|
3033
|
+
const hasBtcAltMetrics = (coverage?.btcAltMetricsRows ?? 0) >= Math.floor(Math.max(1, coverage?.rows ?? 0) * 0.9);
|
|
3034
|
+
const missingChunks2 = !hasCoverage({
|
|
3035
|
+
coverage,
|
|
3036
|
+
startMs: breadthStartMs,
|
|
3037
|
+
endMs,
|
|
3038
|
+
intervalMs
|
|
3039
|
+
}) || !hasBtcAltMetrics ? !hasBtcAltMetrics ? chunks : filterMissingBreadthBackfillChunks({
|
|
3040
|
+
chunks,
|
|
3041
|
+
coverage,
|
|
3042
|
+
intervalMs
|
|
3043
|
+
}) : [];
|
|
3044
|
+
if (!missingChunks2.length) {
|
|
3045
|
+
console.log(
|
|
3046
|
+
import_chalk.default.gray(`breadth cached: universe=${definition.universe}`)
|
|
3047
|
+
);
|
|
3057
3048
|
}
|
|
3058
|
-
|
|
3059
|
-
|
|
3049
|
+
return {
|
|
3050
|
+
definition,
|
|
3051
|
+
missingChunkKeys: new Set(
|
|
3052
|
+
missingChunks2.map((chunk) => `${chunk.startMs}:${chunk.endMs}`)
|
|
3053
|
+
)
|
|
3054
|
+
};
|
|
3055
|
+
})
|
|
3056
|
+
);
|
|
3057
|
+
const missingChunks = chunks.filter((chunk) => {
|
|
3058
|
+
const key = `${chunk.startMs}:${chunk.endMs}`;
|
|
3059
|
+
return plans.some((plan) => plan.missingChunkKeys.has(key));
|
|
3060
|
+
});
|
|
3061
|
+
const bar = new import_progress.default(
|
|
3062
|
+
"breadth :current/:total [:bar][:percent] :etas(s) candles=:candles skip=:skip chunk=:chunk :symbol",
|
|
3063
|
+
{
|
|
3064
|
+
total: Math.max(1, missingChunks.length * breadthSymbols.length),
|
|
3065
|
+
width: 24
|
|
3066
|
+
}
|
|
3067
|
+
);
|
|
3068
|
+
let candlesRead = 0;
|
|
3069
|
+
const skippedBreadthChunks = chunks.length - missingChunks.length;
|
|
3070
|
+
if (!missingChunks.length) {
|
|
3071
|
+
bar.tick(1, {
|
|
3072
|
+
candles: 0,
|
|
3073
|
+
skip: skippedBreadthChunks,
|
|
3074
|
+
chunk: "cached",
|
|
3075
|
+
symbol: "top5/top10/top30/top50/top100"
|
|
3076
|
+
});
|
|
3077
|
+
}
|
|
3078
|
+
for (let chunkIndex = 0; chunkIndex < missingChunks.length; chunkIndex += 1) {
|
|
3079
|
+
const chunk = missingChunks[chunkIndex];
|
|
3080
|
+
const originalChunkIndex = chunks.findIndex(
|
|
3081
|
+
(item) => item.startMs === chunk.startMs && item.endMs === chunk.endMs
|
|
3082
|
+
);
|
|
3083
|
+
const candlesBySymbol = {};
|
|
3084
|
+
for (const symbol of breadthSymbols) {
|
|
3085
|
+
const candles = await connector.kline({
|
|
3086
|
+
symbol,
|
|
3060
3087
|
interval: connectorInterval,
|
|
3061
3088
|
start: chunk.fetchStartMs,
|
|
3062
3089
|
end: chunk.endMs,
|
|
3063
3090
|
silent: true
|
|
3064
3091
|
});
|
|
3092
|
+
candlesBySymbol[symbol] = candles;
|
|
3093
|
+
candlesRead += candles.length;
|
|
3094
|
+
bar.tick(1, {
|
|
3095
|
+
candles: candlesRead,
|
|
3096
|
+
skip: skippedBreadthChunks,
|
|
3097
|
+
chunk: `${originalChunkIndex + 1}/${chunks.length}`,
|
|
3098
|
+
symbol
|
|
3099
|
+
});
|
|
3100
|
+
}
|
|
3101
|
+
const btcCandles = await connector.kline({
|
|
3102
|
+
symbol: "BTCUSDT",
|
|
3103
|
+
interval: connectorInterval,
|
|
3104
|
+
start: chunk.fetchStartMs,
|
|
3105
|
+
end: chunk.endMs,
|
|
3106
|
+
silent: true
|
|
3107
|
+
});
|
|
3108
|
+
const chunkKey = `${chunk.startMs}:${chunk.endMs}`;
|
|
3109
|
+
for (const plan of plans) {
|
|
3110
|
+
if (!plan.missingChunkKeys.has(chunkKey)) {
|
|
3111
|
+
continue;
|
|
3112
|
+
}
|
|
3113
|
+
const symbolSet = new Set(plan.definition.symbols);
|
|
3114
|
+
const universeCandles = Object.fromEntries(
|
|
3115
|
+
Object.entries(candlesBySymbol).filter(
|
|
3116
|
+
([symbol]) => symbolSet.has(symbol)
|
|
3117
|
+
)
|
|
3118
|
+
);
|
|
3065
3119
|
const rows = buildMarketBreadthRows({
|
|
3066
|
-
universe,
|
|
3120
|
+
universe: plan.definition.universe,
|
|
3067
3121
|
interval: interval2,
|
|
3068
|
-
candlesBySymbol,
|
|
3122
|
+
candlesBySymbol: universeCandles,
|
|
3069
3123
|
btcCandles
|
|
3070
3124
|
}).filter((row) => {
|
|
3071
3125
|
const ts = row.ts.getTime();
|
|
@@ -3074,8 +3128,6 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
3074
3128
|
await (0, import_timescale.upsertMarketBreadthRows)(rows);
|
|
3075
3129
|
breadthRows += rows.length;
|
|
3076
3130
|
}
|
|
3077
|
-
} else {
|
|
3078
|
-
console.log(import_chalk.default.gray(`breadth cached: universe=${universe}`));
|
|
3079
3131
|
}
|
|
3080
3132
|
}
|
|
3081
3133
|
console.log(
|