@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
|
@@ -46,6 +46,7 @@ var import_progress = __toESM(require("progress"));
|
|
|
46
46
|
var import_chalk = __toESM(require("chalk"));
|
|
47
47
|
var import_connectors = require("@tradejs/connectors");
|
|
48
48
|
var import_connectors2 = require("@tradejs/node/connectors");
|
|
49
|
+
var import_strategies = require("@tradejs/node/strategies");
|
|
49
50
|
var import_timescale = require("@tradejs/infra/timescale");
|
|
50
51
|
|
|
51
52
|
// src/lib/binanceMarketData.ts
|
|
@@ -55,14 +56,6 @@ var MARKET_FEATURE_INTERVAL_MS = {
|
|
|
55
56
|
"15m": 9e5,
|
|
56
57
|
"1h": 36e5
|
|
57
58
|
};
|
|
58
|
-
var STABLE_QUOTE_SYMBOLS = /* @__PURE__ */ new Set([
|
|
59
|
-
"USDCUSDT",
|
|
60
|
-
"FDUSDUSDT",
|
|
61
|
-
"TUSDUSDT",
|
|
62
|
-
"BUSDUSDT",
|
|
63
|
-
"USDPUSDT",
|
|
64
|
-
"DAIUSDT"
|
|
65
|
-
]);
|
|
66
59
|
var safeDivide = (num, den) => Number.isFinite(num) && Number.isFinite(den) && den !== 0 ? num / den : null;
|
|
67
60
|
var mean = (values) => values.length ? values.reduce((sum, value) => sum + value, 0) / values.length : null;
|
|
68
61
|
var standardDeviation = (values) => {
|
|
@@ -106,9 +99,6 @@ var classifyBtcAltRegime = ({
|
|
|
106
99
|
if (btcVsAltReturn24h < -5e-3) return "alt_lead";
|
|
107
100
|
return "neutral";
|
|
108
101
|
};
|
|
109
|
-
var selectBreadthUniverseFromTickers = (tickers, limit) => tickers.filter(
|
|
110
|
-
(ticker) => ticker.symbol.endsWith("USDT") && ticker.symbol !== "BTCUSDT" && !STABLE_QUOTE_SYMBOLS.has(ticker.symbol) && Number.isFinite(ticker.turnover24h) && ticker.turnover24h > 0
|
|
111
|
-
).sort((a, b) => b.turnover24h - a.turnover24h).slice(0, Math.max(0, limit)).map((ticker) => ticker.symbol);
|
|
112
102
|
var aggregateAggTradesToRows = ({
|
|
113
103
|
symbol,
|
|
114
104
|
interval,
|
|
@@ -590,10 +580,6 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
590
580
|
process.env.BINANCE_MARKET_CONTEXT_TRADE_FLOW_SYMBOL_LIMIT,
|
|
591
581
|
2
|
|
592
582
|
);
|
|
593
|
-
const breadthLimit = asInt(
|
|
594
|
-
process.env.BINANCE_MARKET_CONTEXT_BREADTH_LIMIT,
|
|
595
|
-
30
|
|
596
|
-
);
|
|
597
583
|
const breadthChunkDays = asFloat(
|
|
598
584
|
process.env.BINANCE_MARKET_CONTEXT_BREADTH_CHUNK_DAYS,
|
|
599
585
|
30
|
|
@@ -716,88 +702,113 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
716
702
|
}
|
|
717
703
|
}
|
|
718
704
|
if (includeBreadth) {
|
|
719
|
-
const
|
|
720
|
-
const breadthSymbols =
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
);
|
|
724
|
-
const universe = `binance_top${breadthSymbols.length}_usdt`;
|
|
725
|
-
const coverage = await (0, import_timescale.getMarketBreadthCoverage)({
|
|
726
|
-
universe,
|
|
727
|
-
interval,
|
|
728
|
-
startMs: breadthStartMs,
|
|
729
|
-
endMs
|
|
730
|
-
});
|
|
731
|
-
const hasBtcAltMetrics = (coverage?.btcAltMetricsRows ?? 0) >= Math.floor(Math.max(1, coverage?.rows ?? 0) * 0.9);
|
|
732
|
-
if (!hasCoverage({
|
|
733
|
-
coverage,
|
|
705
|
+
const breadthUniverses = (0, import_strategies.getBinanceBreadthUniverses)();
|
|
706
|
+
const breadthSymbols = breadthUniverses.at(-1)?.symbols ?? [];
|
|
707
|
+
const connectorInterval = marketIntervalToConnectorInterval(interval);
|
|
708
|
+
const chunks = buildBreadthBackfillChunks({
|
|
734
709
|
startMs: breadthStartMs,
|
|
735
710
|
endMs,
|
|
736
|
-
intervalMs
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
chunks,
|
|
747
|
-
coverage,
|
|
748
|
-
intervalMs
|
|
749
|
-
});
|
|
750
|
-
const bar = new import_progress.default(
|
|
751
|
-
"breadth :current/:total [:bar][:percent] :etas(s) candles=:candles skip=:skip chunk=:chunk :symbol",
|
|
752
|
-
{
|
|
753
|
-
total: Math.max(1, missingChunks.length * breadthSymbols.length),
|
|
754
|
-
width: 24
|
|
755
|
-
}
|
|
756
|
-
);
|
|
757
|
-
let candlesRead = 0;
|
|
758
|
-
let skippedBreadthChunks = chunks.length - missingChunks.length;
|
|
759
|
-
if (!missingChunks.length) {
|
|
760
|
-
bar.tick(1, {
|
|
761
|
-
candles: 0,
|
|
762
|
-
skip: skippedBreadthChunks,
|
|
763
|
-
chunk: "cached",
|
|
764
|
-
symbol: universe
|
|
711
|
+
intervalMs,
|
|
712
|
+
chunkDays: breadthChunkDays
|
|
713
|
+
});
|
|
714
|
+
const plans = await Promise.all(
|
|
715
|
+
breadthUniverses.map(async (definition) => {
|
|
716
|
+
const coverage = await (0, import_timescale.getMarketBreadthCoverage)({
|
|
717
|
+
universe: definition.universe,
|
|
718
|
+
interval,
|
|
719
|
+
startMs: breadthStartMs,
|
|
720
|
+
endMs
|
|
765
721
|
});
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
candlesBySymbol[symbol] = candles;
|
|
782
|
-
candlesRead += candles.length;
|
|
783
|
-
bar.tick(1, {
|
|
784
|
-
candles: candlesRead,
|
|
785
|
-
skip: skippedBreadthChunks,
|
|
786
|
-
chunk: `${originalChunkIndex + 1}/${chunks.length}`,
|
|
787
|
-
symbol
|
|
788
|
-
});
|
|
722
|
+
const hasBtcAltMetrics = (coverage?.btcAltMetricsRows ?? 0) >= Math.floor(Math.max(1, coverage?.rows ?? 0) * 0.9);
|
|
723
|
+
const missingChunks2 = !hasCoverage({
|
|
724
|
+
coverage,
|
|
725
|
+
startMs: breadthStartMs,
|
|
726
|
+
endMs,
|
|
727
|
+
intervalMs
|
|
728
|
+
}) || !hasBtcAltMetrics ? !hasBtcAltMetrics ? chunks : filterMissingBreadthBackfillChunks({
|
|
729
|
+
chunks,
|
|
730
|
+
coverage,
|
|
731
|
+
intervalMs
|
|
732
|
+
}) : [];
|
|
733
|
+
if (!missingChunks2.length) {
|
|
734
|
+
console.log(
|
|
735
|
+
import_chalk.default.gray(`breadth cached: universe=${definition.universe}`)
|
|
736
|
+
);
|
|
789
737
|
}
|
|
790
|
-
|
|
791
|
-
|
|
738
|
+
return {
|
|
739
|
+
definition,
|
|
740
|
+
missingChunkKeys: new Set(
|
|
741
|
+
missingChunks2.map((chunk) => `${chunk.startMs}:${chunk.endMs}`)
|
|
742
|
+
)
|
|
743
|
+
};
|
|
744
|
+
})
|
|
745
|
+
);
|
|
746
|
+
const missingChunks = chunks.filter((chunk) => {
|
|
747
|
+
const key = `${chunk.startMs}:${chunk.endMs}`;
|
|
748
|
+
return plans.some((plan) => plan.missingChunkKeys.has(key));
|
|
749
|
+
});
|
|
750
|
+
const bar = new import_progress.default(
|
|
751
|
+
"breadth :current/:total [:bar][:percent] :etas(s) candles=:candles skip=:skip chunk=:chunk :symbol",
|
|
752
|
+
{
|
|
753
|
+
total: Math.max(1, missingChunks.length * breadthSymbols.length),
|
|
754
|
+
width: 24
|
|
755
|
+
}
|
|
756
|
+
);
|
|
757
|
+
let candlesRead = 0;
|
|
758
|
+
const skippedBreadthChunks = chunks.length - missingChunks.length;
|
|
759
|
+
if (!missingChunks.length) {
|
|
760
|
+
bar.tick(1, {
|
|
761
|
+
candles: 0,
|
|
762
|
+
skip: skippedBreadthChunks,
|
|
763
|
+
chunk: "cached",
|
|
764
|
+
symbol: "top5/top10/top30/top50/top100"
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
for (let chunkIndex = 0; chunkIndex < missingChunks.length; chunkIndex += 1) {
|
|
768
|
+
const chunk = missingChunks[chunkIndex];
|
|
769
|
+
const originalChunkIndex = chunks.findIndex(
|
|
770
|
+
(item) => item.startMs === chunk.startMs && item.endMs === chunk.endMs
|
|
771
|
+
);
|
|
772
|
+
const candlesBySymbol = {};
|
|
773
|
+
for (const symbol of breadthSymbols) {
|
|
774
|
+
const candles = await connector.kline({
|
|
775
|
+
symbol,
|
|
792
776
|
interval: connectorInterval,
|
|
793
777
|
start: chunk.fetchStartMs,
|
|
794
778
|
end: chunk.endMs,
|
|
795
779
|
silent: true
|
|
796
780
|
});
|
|
781
|
+
candlesBySymbol[symbol] = candles;
|
|
782
|
+
candlesRead += candles.length;
|
|
783
|
+
bar.tick(1, {
|
|
784
|
+
candles: candlesRead,
|
|
785
|
+
skip: skippedBreadthChunks,
|
|
786
|
+
chunk: `${originalChunkIndex + 1}/${chunks.length}`,
|
|
787
|
+
symbol
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
const btcCandles = await connector.kline({
|
|
791
|
+
symbol: "BTCUSDT",
|
|
792
|
+
interval: connectorInterval,
|
|
793
|
+
start: chunk.fetchStartMs,
|
|
794
|
+
end: chunk.endMs,
|
|
795
|
+
silent: true
|
|
796
|
+
});
|
|
797
|
+
const chunkKey = `${chunk.startMs}:${chunk.endMs}`;
|
|
798
|
+
for (const plan of plans) {
|
|
799
|
+
if (!plan.missingChunkKeys.has(chunkKey)) {
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
const symbolSet = new Set(plan.definition.symbols);
|
|
803
|
+
const universeCandles = Object.fromEntries(
|
|
804
|
+
Object.entries(candlesBySymbol).filter(
|
|
805
|
+
([symbol]) => symbolSet.has(symbol)
|
|
806
|
+
)
|
|
807
|
+
);
|
|
797
808
|
const rows = buildMarketBreadthRows({
|
|
798
|
-
universe,
|
|
809
|
+
universe: plan.definition.universe,
|
|
799
810
|
interval,
|
|
800
|
-
candlesBySymbol,
|
|
811
|
+
candlesBySymbol: universeCandles,
|
|
801
812
|
btcCandles
|
|
802
813
|
}).filter((row) => {
|
|
803
814
|
const ts = row.ts.getTime();
|
|
@@ -806,8 +817,6 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
806
817
|
await (0, import_timescale.upsertMarketBreadthRows)(rows);
|
|
807
818
|
breadthRows += rows.length;
|
|
808
819
|
}
|
|
809
|
-
} else {
|
|
810
|
-
console.log(import_chalk.default.gray(`breadth cached: universe=${universe}`));
|
|
811
820
|
}
|
|
812
821
|
}
|
|
813
822
|
console.log(
|
|
@@ -106,14 +106,17 @@ var estimateBinanceMarketDataVolume = ({
|
|
|
106
106
|
interval,
|
|
107
107
|
includeAggTrades,
|
|
108
108
|
includeBreadth,
|
|
109
|
-
|
|
109
|
+
breadthSizes
|
|
110
110
|
}) => {
|
|
111
111
|
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
|
|
112
112
|
const bucketRowsPerSymbol = Math.ceil(days * 864e5 / intervalMs);
|
|
113
113
|
const aggTradeBucketRows = includeAggTrades ? symbols.length * bucketRowsPerSymbol : 0;
|
|
114
|
-
const
|
|
114
|
+
const normalizedBreadthSizes = breadthSizes.filter(
|
|
115
|
+
(size) => Number.isFinite(size) && size > 0
|
|
116
|
+
);
|
|
117
|
+
const breadthSymbols = includeBreadth ? Math.max(0, ...normalizedBreadthSizes) : 0;
|
|
115
118
|
const breadthCandleRows = breadthSymbols * bucketRowsPerSymbol;
|
|
116
|
-
const breadthRows = includeBreadth ? bucketRowsPerSymbol : 0;
|
|
119
|
+
const breadthRows = includeBreadth ? bucketRowsPerSymbol * normalizedBreadthSizes.length : 0;
|
|
117
120
|
return {
|
|
118
121
|
interval,
|
|
119
122
|
days,
|
|
@@ -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(args) {
|
|
@@ -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(...args) {
|
|
746
|
-
return process.stderr.write(util.
|
|
761
|
+
return process.stderr.write(util.formatWithOptions(exports2.inspectOpts, ...args) + "\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();
|
|
@@ -1634,6 +1649,7 @@ var import_progress = __toESM(require("progress"));
|
|
|
1634
1649
|
var import_chalk = __toESM(require("chalk"));
|
|
1635
1650
|
var import_connectors = require("@tradejs/connectors");
|
|
1636
1651
|
var import_connectors2 = require("@tradejs/node/connectors");
|
|
1652
|
+
var import_strategies = require("@tradejs/node/strategies");
|
|
1637
1653
|
var import_timescale = require("@tradejs/infra/timescale");
|
|
1638
1654
|
|
|
1639
1655
|
// src/lib/binanceMarketData.ts
|
|
@@ -1643,14 +1659,6 @@ var MARKET_FEATURE_INTERVAL_MS = {
|
|
|
1643
1659
|
"15m": 9e5,
|
|
1644
1660
|
"1h": 36e5
|
|
1645
1661
|
};
|
|
1646
|
-
var STABLE_QUOTE_SYMBOLS = /* @__PURE__ */ new Set([
|
|
1647
|
-
"USDCUSDT",
|
|
1648
|
-
"FDUSDUSDT",
|
|
1649
|
-
"TUSDUSDT",
|
|
1650
|
-
"BUSDUSDT",
|
|
1651
|
-
"USDPUSDT",
|
|
1652
|
-
"DAIUSDT"
|
|
1653
|
-
]);
|
|
1654
1662
|
var safeDivide = (num, den) => Number.isFinite(num) && Number.isFinite(den) && den !== 0 ? num / den : null;
|
|
1655
1663
|
var mean = (values) => values.length ? values.reduce((sum, value) => sum + value, 0) / values.length : null;
|
|
1656
1664
|
var standardDeviation = (values) => {
|
|
@@ -1694,9 +1702,6 @@ var classifyBtcAltRegime = ({
|
|
|
1694
1702
|
if (btcVsAltReturn24h < -5e-3) return "alt_lead";
|
|
1695
1703
|
return "neutral";
|
|
1696
1704
|
};
|
|
1697
|
-
var selectBreadthUniverseFromTickers = (tickers, limit) => tickers.filter(
|
|
1698
|
-
(ticker) => ticker.symbol.endsWith("USDT") && ticker.symbol !== "BTCUSDT" && !STABLE_QUOTE_SYMBOLS.has(ticker.symbol) && Number.isFinite(ticker.turnover24h) && ticker.turnover24h > 0
|
|
1699
|
-
).sort((a, b) => b.turnover24h - a.turnover24h).slice(0, Math.max(0, limit)).map((ticker) => ticker.symbol);
|
|
1700
1705
|
var aggregateAggTradesToRows = ({
|
|
1701
1706
|
symbol,
|
|
1702
1707
|
interval,
|
|
@@ -2178,10 +2183,6 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
2178
2183
|
process.env.BINANCE_MARKET_CONTEXT_TRADE_FLOW_SYMBOL_LIMIT,
|
|
2179
2184
|
2
|
|
2180
2185
|
);
|
|
2181
|
-
const breadthLimit = asInt(
|
|
2182
|
-
process.env.BINANCE_MARKET_CONTEXT_BREADTH_LIMIT,
|
|
2183
|
-
30
|
|
2184
|
-
);
|
|
2185
2186
|
const breadthChunkDays = asFloat(
|
|
2186
2187
|
process.env.BINANCE_MARKET_CONTEXT_BREADTH_CHUNK_DAYS,
|
|
2187
2188
|
30
|
|
@@ -2304,88 +2305,113 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
2304
2305
|
}
|
|
2305
2306
|
}
|
|
2306
2307
|
if (includeBreadth) {
|
|
2307
|
-
const
|
|
2308
|
-
const breadthSymbols =
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
);
|
|
2312
|
-
const universe = `binance_top${breadthSymbols.length}_usdt`;
|
|
2313
|
-
const coverage = await (0, import_timescale.getMarketBreadthCoverage)({
|
|
2314
|
-
universe,
|
|
2315
|
-
interval,
|
|
2316
|
-
startMs: breadthStartMs,
|
|
2317
|
-
endMs
|
|
2318
|
-
});
|
|
2319
|
-
const hasBtcAltMetrics = (coverage?.btcAltMetricsRows ?? 0) >= Math.floor(Math.max(1, coverage?.rows ?? 0) * 0.9);
|
|
2320
|
-
if (!hasCoverage({
|
|
2321
|
-
coverage,
|
|
2308
|
+
const breadthUniverses = (0, import_strategies.getBinanceBreadthUniverses)();
|
|
2309
|
+
const breadthSymbols = breadthUniverses.at(-1)?.symbols ?? [];
|
|
2310
|
+
const connectorInterval = marketIntervalToConnectorInterval(interval);
|
|
2311
|
+
const chunks = buildBreadthBackfillChunks({
|
|
2322
2312
|
startMs: breadthStartMs,
|
|
2323
2313
|
endMs,
|
|
2324
|
-
intervalMs
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
chunks,
|
|
2335
|
-
coverage,
|
|
2336
|
-
intervalMs
|
|
2337
|
-
});
|
|
2338
|
-
const bar = new import_progress.default(
|
|
2339
|
-
"breadth :current/:total [:bar][:percent] :etas(s) candles=:candles skip=:skip chunk=:chunk :symbol",
|
|
2340
|
-
{
|
|
2341
|
-
total: Math.max(1, missingChunks.length * breadthSymbols.length),
|
|
2342
|
-
width: 24
|
|
2343
|
-
}
|
|
2344
|
-
);
|
|
2345
|
-
let candlesRead = 0;
|
|
2346
|
-
let skippedBreadthChunks = chunks.length - missingChunks.length;
|
|
2347
|
-
if (!missingChunks.length) {
|
|
2348
|
-
bar.tick(1, {
|
|
2349
|
-
candles: 0,
|
|
2350
|
-
skip: skippedBreadthChunks,
|
|
2351
|
-
chunk: "cached",
|
|
2352
|
-
symbol: universe
|
|
2314
|
+
intervalMs,
|
|
2315
|
+
chunkDays: breadthChunkDays
|
|
2316
|
+
});
|
|
2317
|
+
const plans = await Promise.all(
|
|
2318
|
+
breadthUniverses.map(async (definition) => {
|
|
2319
|
+
const coverage = await (0, import_timescale.getMarketBreadthCoverage)({
|
|
2320
|
+
universe: definition.universe,
|
|
2321
|
+
interval,
|
|
2322
|
+
startMs: breadthStartMs,
|
|
2323
|
+
endMs
|
|
2353
2324
|
});
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
candlesBySymbol[symbol] = candles;
|
|
2370
|
-
candlesRead += candles.length;
|
|
2371
|
-
bar.tick(1, {
|
|
2372
|
-
candles: candlesRead,
|
|
2373
|
-
skip: skippedBreadthChunks,
|
|
2374
|
-
chunk: `${originalChunkIndex + 1}/${chunks.length}`,
|
|
2375
|
-
symbol
|
|
2376
|
-
});
|
|
2325
|
+
const hasBtcAltMetrics = (coverage?.btcAltMetricsRows ?? 0) >= Math.floor(Math.max(1, coverage?.rows ?? 0) * 0.9);
|
|
2326
|
+
const missingChunks2 = !hasCoverage({
|
|
2327
|
+
coverage,
|
|
2328
|
+
startMs: breadthStartMs,
|
|
2329
|
+
endMs,
|
|
2330
|
+
intervalMs
|
|
2331
|
+
}) || !hasBtcAltMetrics ? !hasBtcAltMetrics ? chunks : filterMissingBreadthBackfillChunks({
|
|
2332
|
+
chunks,
|
|
2333
|
+
coverage,
|
|
2334
|
+
intervalMs
|
|
2335
|
+
}) : [];
|
|
2336
|
+
if (!missingChunks2.length) {
|
|
2337
|
+
console.log(
|
|
2338
|
+
import_chalk.default.gray(`breadth cached: universe=${definition.universe}`)
|
|
2339
|
+
);
|
|
2377
2340
|
}
|
|
2378
|
-
|
|
2379
|
-
|
|
2341
|
+
return {
|
|
2342
|
+
definition,
|
|
2343
|
+
missingChunkKeys: new Set(
|
|
2344
|
+
missingChunks2.map((chunk) => `${chunk.startMs}:${chunk.endMs}`)
|
|
2345
|
+
)
|
|
2346
|
+
};
|
|
2347
|
+
})
|
|
2348
|
+
);
|
|
2349
|
+
const missingChunks = chunks.filter((chunk) => {
|
|
2350
|
+
const key = `${chunk.startMs}:${chunk.endMs}`;
|
|
2351
|
+
return plans.some((plan) => plan.missingChunkKeys.has(key));
|
|
2352
|
+
});
|
|
2353
|
+
const bar = new import_progress.default(
|
|
2354
|
+
"breadth :current/:total [:bar][:percent] :etas(s) candles=:candles skip=:skip chunk=:chunk :symbol",
|
|
2355
|
+
{
|
|
2356
|
+
total: Math.max(1, missingChunks.length * breadthSymbols.length),
|
|
2357
|
+
width: 24
|
|
2358
|
+
}
|
|
2359
|
+
);
|
|
2360
|
+
let candlesRead = 0;
|
|
2361
|
+
const skippedBreadthChunks = chunks.length - missingChunks.length;
|
|
2362
|
+
if (!missingChunks.length) {
|
|
2363
|
+
bar.tick(1, {
|
|
2364
|
+
candles: 0,
|
|
2365
|
+
skip: skippedBreadthChunks,
|
|
2366
|
+
chunk: "cached",
|
|
2367
|
+
symbol: "top5/top10/top30/top50/top100"
|
|
2368
|
+
});
|
|
2369
|
+
}
|
|
2370
|
+
for (let chunkIndex = 0; chunkIndex < missingChunks.length; chunkIndex += 1) {
|
|
2371
|
+
const chunk = missingChunks[chunkIndex];
|
|
2372
|
+
const originalChunkIndex = chunks.findIndex(
|
|
2373
|
+
(item) => item.startMs === chunk.startMs && item.endMs === chunk.endMs
|
|
2374
|
+
);
|
|
2375
|
+
const candlesBySymbol = {};
|
|
2376
|
+
for (const symbol of breadthSymbols) {
|
|
2377
|
+
const candles = await connector.kline({
|
|
2378
|
+
symbol,
|
|
2380
2379
|
interval: connectorInterval,
|
|
2381
2380
|
start: chunk.fetchStartMs,
|
|
2382
2381
|
end: chunk.endMs,
|
|
2383
2382
|
silent: true
|
|
2384
2383
|
});
|
|
2384
|
+
candlesBySymbol[symbol] = candles;
|
|
2385
|
+
candlesRead += candles.length;
|
|
2386
|
+
bar.tick(1, {
|
|
2387
|
+
candles: candlesRead,
|
|
2388
|
+
skip: skippedBreadthChunks,
|
|
2389
|
+
chunk: `${originalChunkIndex + 1}/${chunks.length}`,
|
|
2390
|
+
symbol
|
|
2391
|
+
});
|
|
2392
|
+
}
|
|
2393
|
+
const btcCandles = await connector.kline({
|
|
2394
|
+
symbol: "BTCUSDT",
|
|
2395
|
+
interval: connectorInterval,
|
|
2396
|
+
start: chunk.fetchStartMs,
|
|
2397
|
+
end: chunk.endMs,
|
|
2398
|
+
silent: true
|
|
2399
|
+
});
|
|
2400
|
+
const chunkKey = `${chunk.startMs}:${chunk.endMs}`;
|
|
2401
|
+
for (const plan of plans) {
|
|
2402
|
+
if (!plan.missingChunkKeys.has(chunkKey)) {
|
|
2403
|
+
continue;
|
|
2404
|
+
}
|
|
2405
|
+
const symbolSet = new Set(plan.definition.symbols);
|
|
2406
|
+
const universeCandles = Object.fromEntries(
|
|
2407
|
+
Object.entries(candlesBySymbol).filter(
|
|
2408
|
+
([symbol]) => symbolSet.has(symbol)
|
|
2409
|
+
)
|
|
2410
|
+
);
|
|
2385
2411
|
const rows = buildMarketBreadthRows({
|
|
2386
|
-
universe,
|
|
2412
|
+
universe: plan.definition.universe,
|
|
2387
2413
|
interval,
|
|
2388
|
-
candlesBySymbol,
|
|
2414
|
+
candlesBySymbol: universeCandles,
|
|
2389
2415
|
btcCandles
|
|
2390
2416
|
}).filter((row) => {
|
|
2391
2417
|
const ts = row.ts.getTime();
|
|
@@ -2394,8 +2420,6 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
2394
2420
|
await (0, import_timescale.upsertMarketBreadthRows)(rows);
|
|
2395
2421
|
breadthRows += rows.length;
|
|
2396
2422
|
}
|
|
2397
|
-
} else {
|
|
2398
|
-
console.log(import_chalk.default.gray(`breadth cached: universe=${universe}`));
|
|
2399
2423
|
}
|
|
2400
2424
|
}
|
|
2401
2425
|
console.log(
|