@tradejs/cli 1.0.9 → 1.0.10
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 +29497 -13537
- package/dist/lib/aiPocketSearch.js +1316 -0
- package/dist/lib/aiTrainCharts.js +711 -0
- package/dist/lib/aiTrainDataset.js +40 -0
- package/dist/lib/aiTrainEvaluationDump.js +76 -0
- package/dist/lib/aiTrainMetrics.js +148 -8
- package/dist/lib/aiTrainOptions.js +130 -0
- package/dist/lib/aiTrainQuarantine.js +199 -0
- package/dist/lib/aiTrainResearch.js +467 -0
- package/dist/lib/binanceMarketContextBackfill.js +841 -0
- package/dist/lib/binanceMarketData.js +392 -0
- package/dist/lib/coinMarketCapContextBackfill.js +1088 -0
- package/dist/lib/continuity.js +60 -0
- package/dist/lib/derivativesContextBackfill.js +490 -77
- package/dist/lib/executionCalibration.js +705 -0
- package/dist/lib/marketContextPrepare.js +4403 -0
- package/dist/lib/paritySummary.js +101 -0
- package/dist/lib/runBot.js +1 -0
- package/dist/lib/runEnvironment.js +2254 -0
- package/dist/lib/runFormatting.js +1657 -0
- package/dist/lib/runtimeDebugEvidence.js +526 -0
- package/dist/lib/runtimeModeConfig.js +53 -0
- package/dist/lib/runtimeParity.js +88 -11
- package/dist/lib/runtimeParityDetails.js +751 -0
- package/dist/lib/runtimeRedis.js +157 -0
- package/dist/lib/runtimeSignalsLoader.js +40 -6
- package/dist/lib/runtimeSignalsStorage.js +45 -22
- package/dist/lib/runtimeStrategyBacktest.js +134 -0
- package/dist/lib/runtimeTradeSync.js +263 -0
- package/dist/lib/telegramReports.js +9 -0
- package/dist/lib/tickerUniverseCache.js +116 -0
- package/dist/lib/timeWindow.js +3 -3
- package/dist/scripts/agentRun.js +14 -8
- package/dist/scripts/aiExport.js +1721 -7
- package/dist/scripts/aiExportSelect.js +16 -4
- package/dist/scripts/aiPocketSearch.js +4190 -0
- package/dist/scripts/aiTrain.js +1866 -87
- package/dist/scripts/backtest.js +4509 -818
- package/dist/scripts/binanceMarketIngest.js +565 -0
- package/dist/scripts/bot.js +16 -2
- package/dist/scripts/candlesMigrateProvider.js +32 -22
- package/dist/scripts/cleanDir.js +15 -2
- package/dist/scripts/cleanRedis.js +15 -2
- package/dist/scripts/cleanTests.js +38 -2
- package/dist/scripts/cleanupMarketContext.js +69 -0
- package/dist/scripts/continuity.js +148 -67
- package/dist/scripts/derivativesIngest.js +14 -4
- package/dist/scripts/derivativesIngestCoinalyzeAll.js +14 -4
- package/dist/scripts/doctor.js +14 -4
- package/dist/scripts/executionCalibration.js +792 -0
- package/dist/scripts/infraCommon.js +10 -0
- package/dist/scripts/infraDown.js +14 -4
- package/dist/scripts/infraInit.js +24 -4
- package/dist/scripts/infraUp.js +14 -4
- package/dist/scripts/marketWs.js +222 -0
- package/dist/scripts/migration.js +15 -2
- package/dist/scripts/mlExport.js +1698 -10
- package/dist/scripts/mlExportSelect.js +16 -4
- package/dist/scripts/mlInspect.js +13 -3
- package/dist/scripts/mlTrainLatestSelect.js +14 -4
- package/dist/scripts/replay.js +8824 -0
- package/dist/scripts/replayRunner.js +8827 -0
- package/dist/scripts/replayRuntimeEvidence.js +868 -0
- package/dist/scripts/researchAuto.js +286 -59
- package/dist/scripts/results.js +3 -3
- package/dist/scripts/runtimeEvidence.js +605 -0
- package/dist/scripts/runtimeParity.js +6362 -1043
- package/dist/scripts/serverHealth.js +588 -0
- package/dist/scripts/signals.js +5590 -511
- package/dist/scripts/signalsDaemon.js +6167 -0
- package/dist/scripts/signalsSummary.js +833 -248
- package/dist/scripts/test-ml.js +25 -3
- package/dist/scripts/test.js +26 -1
- package/dist/scripts/user-add.js +15 -2
- package/dist/workers/testerWorker.js +130 -21
- package/package.json +18 -12
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/scripts/binanceMarketIngest.ts
|
|
31
|
+
var binanceMarketIngest_exports = {};
|
|
32
|
+
__export(binanceMarketIngest_exports, {
|
|
33
|
+
main: () => main
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(binanceMarketIngest_exports);
|
|
36
|
+
var import_config = require("dotenv/config");
|
|
37
|
+
var import_args = __toESM(require("args"));
|
|
38
|
+
var import_chalk = __toESM(require("chalk"));
|
|
39
|
+
var import_connectors = require("@tradejs/connectors");
|
|
40
|
+
var import_timescale = require("@tradejs/infra/timescale");
|
|
41
|
+
|
|
42
|
+
// src/lib/binanceMarketData.ts
|
|
43
|
+
var MARKET_FEATURE_INTERVAL_MS = {
|
|
44
|
+
"1m": 6e4,
|
|
45
|
+
"5m": 3e5,
|
|
46
|
+
"15m": 9e5,
|
|
47
|
+
"1h": 36e5
|
|
48
|
+
};
|
|
49
|
+
var STABLE_QUOTE_SYMBOLS = /* @__PURE__ */ new Set([
|
|
50
|
+
"USDCUSDT",
|
|
51
|
+
"FDUSDUSDT",
|
|
52
|
+
"TUSDUSDT",
|
|
53
|
+
"BUSDUSDT",
|
|
54
|
+
"USDPUSDT",
|
|
55
|
+
"DAIUSDT"
|
|
56
|
+
]);
|
|
57
|
+
var safeDivide = (num, den) => Number.isFinite(num) && Number.isFinite(den) && den !== 0 ? num / den : null;
|
|
58
|
+
var mean = (values) => values.length ? values.reduce((sum, value) => sum + value, 0) / values.length : null;
|
|
59
|
+
var standardDeviation = (values) => {
|
|
60
|
+
const avg = mean(values);
|
|
61
|
+
if (avg == null || values.length < 2) return null;
|
|
62
|
+
const variance = values.reduce((sum, value) => sum + (value - avg) ** 2, 0) / values.length;
|
|
63
|
+
return Math.sqrt(variance);
|
|
64
|
+
};
|
|
65
|
+
var buildPrefixSum = (values) => {
|
|
66
|
+
const prefix = [0];
|
|
67
|
+
for (const value of values) prefix.push(prefix[prefix.length - 1] + value);
|
|
68
|
+
return prefix;
|
|
69
|
+
};
|
|
70
|
+
var sumPrefixRange = (prefix, startIndex, endIndexInclusive) => {
|
|
71
|
+
if (endIndexInclusive < startIndex) return 0;
|
|
72
|
+
const start = Math.max(0, startIndex);
|
|
73
|
+
const end = Math.min(prefix.length - 2, endIndexInclusive);
|
|
74
|
+
if (end < start) return 0;
|
|
75
|
+
return prefix[end + 1] - prefix[start];
|
|
76
|
+
};
|
|
77
|
+
var windowReturn = (candles, index, lookbackBars) => {
|
|
78
|
+
const previous = candles[index - lookbackBars];
|
|
79
|
+
const current = candles[index];
|
|
80
|
+
return previous && previous.close > 0 ? (current.close - previous.close) / previous.close : null;
|
|
81
|
+
};
|
|
82
|
+
var classifyBtcAltRegime = ({
|
|
83
|
+
btcReturn24h,
|
|
84
|
+
altBasketReturn24h,
|
|
85
|
+
btcVsAltReturn24h
|
|
86
|
+
}) => {
|
|
87
|
+
if (btcReturn24h == null || altBasketReturn24h == null || btcVsAltReturn24h == null) {
|
|
88
|
+
return "unknown";
|
|
89
|
+
}
|
|
90
|
+
if (btcReturn24h < -0.015 && altBasketReturn24h < -0.025) {
|
|
91
|
+
return "risk_off";
|
|
92
|
+
}
|
|
93
|
+
if (btcReturn24h > 5e-3 && altBasketReturn24h > 5e-3 && altBasketReturn24h > btcReturn24h) {
|
|
94
|
+
return "risk_on";
|
|
95
|
+
}
|
|
96
|
+
if (btcVsAltReturn24h > 5e-3) return "btc_lead";
|
|
97
|
+
if (btcVsAltReturn24h < -5e-3) return "alt_lead";
|
|
98
|
+
return "neutral";
|
|
99
|
+
};
|
|
100
|
+
var normalizeMarketFeatureInterval = (value) => {
|
|
101
|
+
const normalized = String(value || "15m").trim().toLowerCase();
|
|
102
|
+
if (normalized === "1" || normalized === "1m") return "1m";
|
|
103
|
+
if (normalized === "5" || normalized === "5m") return "5m";
|
|
104
|
+
if (normalized === "15" || normalized === "15m") return "15m";
|
|
105
|
+
if (normalized === "60" || normalized === "1h") return "1h";
|
|
106
|
+
return "15m";
|
|
107
|
+
};
|
|
108
|
+
var normalizeBinanceSymbols = (value) => String(value || "").split(",").map((item) => item.trim().toUpperCase()).filter(Boolean);
|
|
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
|
+
var estimateBinanceMarketDataVolume = ({
|
|
113
|
+
symbols,
|
|
114
|
+
days,
|
|
115
|
+
interval,
|
|
116
|
+
includeAggTrades,
|
|
117
|
+
includeBreadth,
|
|
118
|
+
breadthLimit
|
|
119
|
+
}) => {
|
|
120
|
+
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
|
|
121
|
+
const bucketRowsPerSymbol = Math.ceil(days * 864e5 / intervalMs);
|
|
122
|
+
const aggTradeBucketRows = includeAggTrades ? symbols.length * bucketRowsPerSymbol : 0;
|
|
123
|
+
const breadthSymbols = includeBreadth ? Math.max(0, breadthLimit) : 0;
|
|
124
|
+
const breadthCandleRows = breadthSymbols * bucketRowsPerSymbol;
|
|
125
|
+
const breadthRows = includeBreadth ? bucketRowsPerSymbol : 0;
|
|
126
|
+
return {
|
|
127
|
+
interval,
|
|
128
|
+
days,
|
|
129
|
+
symbols: symbols.length,
|
|
130
|
+
bucketRowsPerSymbol,
|
|
131
|
+
aggTradeBucketRows,
|
|
132
|
+
breadthSymbols,
|
|
133
|
+
breadthCandleRows,
|
|
134
|
+
breadthRows,
|
|
135
|
+
estimatedStoredRows: aggTradeBucketRows + breadthRows
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
var aggregateAggTradesToRows = ({
|
|
139
|
+
symbol,
|
|
140
|
+
interval,
|
|
141
|
+
trades,
|
|
142
|
+
source = "binance_agg_trades"
|
|
143
|
+
}) => {
|
|
144
|
+
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
|
|
145
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
146
|
+
for (const trade of trades) {
|
|
147
|
+
const bucketTs = Math.floor(trade.timestamp / intervalMs) * intervalMs;
|
|
148
|
+
const row = buckets.get(bucketTs) ?? {
|
|
149
|
+
symbol,
|
|
150
|
+
interval,
|
|
151
|
+
ts: new Date(bucketTs),
|
|
152
|
+
trades: 0,
|
|
153
|
+
buyBaseVolume: 0,
|
|
154
|
+
sellBaseVolume: 0,
|
|
155
|
+
buyQuoteVolume: 0,
|
|
156
|
+
sellQuoteVolume: 0,
|
|
157
|
+
netBaseDelta: 0,
|
|
158
|
+
netQuoteDelta: 0,
|
|
159
|
+
buyPressurePct: null,
|
|
160
|
+
source
|
|
161
|
+
};
|
|
162
|
+
const quote = trade.price * trade.quantity;
|
|
163
|
+
const isAggressiveSell = trade.isBuyerMaker;
|
|
164
|
+
row.trades += 1;
|
|
165
|
+
if (isAggressiveSell) {
|
|
166
|
+
row.sellBaseVolume = (row.sellBaseVolume ?? 0) + trade.quantity;
|
|
167
|
+
row.sellQuoteVolume = (row.sellQuoteVolume ?? 0) + quote;
|
|
168
|
+
} else {
|
|
169
|
+
row.buyBaseVolume = (row.buyBaseVolume ?? 0) + trade.quantity;
|
|
170
|
+
row.buyQuoteVolume = (row.buyQuoteVolume ?? 0) + quote;
|
|
171
|
+
}
|
|
172
|
+
row.netBaseDelta = (row.buyBaseVolume ?? 0) - (row.sellBaseVolume ?? 0);
|
|
173
|
+
row.netQuoteDelta = (row.buyQuoteVolume ?? 0) - (row.sellQuoteVolume ?? 0);
|
|
174
|
+
row.buyPressurePct = safeDivide(
|
|
175
|
+
row.buyBaseVolume ?? 0,
|
|
176
|
+
(row.buyBaseVolume ?? 0) + (row.sellBaseVolume ?? 0)
|
|
177
|
+
);
|
|
178
|
+
buckets.set(bucketTs, row);
|
|
179
|
+
}
|
|
180
|
+
return [...buckets.values()].sort((a, b) => a.ts.getTime() - b.ts.getTime());
|
|
181
|
+
};
|
|
182
|
+
var buildMarketBreadthRows = ({
|
|
183
|
+
universe,
|
|
184
|
+
interval,
|
|
185
|
+
candlesBySymbol,
|
|
186
|
+
btcCandles,
|
|
187
|
+
source = "binance_klines"
|
|
188
|
+
}) => {
|
|
189
|
+
const timestamps = /* @__PURE__ */ new Set();
|
|
190
|
+
const indexedSymbols = Object.values(candlesBySymbol).map((candles) => ({
|
|
191
|
+
candles,
|
|
192
|
+
byTimestamp: new Map(
|
|
193
|
+
candles.map((candle, index) => [candle.timestamp, index])
|
|
194
|
+
),
|
|
195
|
+
turnoverPrefix: buildPrefixSum(
|
|
196
|
+
candles.map((candle) => Math.max(0, candle.turnover ?? 0))
|
|
197
|
+
),
|
|
198
|
+
closePrefix: buildPrefixSum(candles.map((candle) => candle.close))
|
|
199
|
+
}));
|
|
200
|
+
const btcIndexed = btcCandles ? {
|
|
201
|
+
candles: btcCandles,
|
|
202
|
+
byTimestamp: new Map(
|
|
203
|
+
btcCandles.map((candle, index) => [candle.timestamp, index])
|
|
204
|
+
),
|
|
205
|
+
turnoverPrefix: buildPrefixSum(
|
|
206
|
+
btcCandles.map((candle) => Math.max(0, candle.turnover ?? 0))
|
|
207
|
+
)
|
|
208
|
+
} : null;
|
|
209
|
+
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
|
|
210
|
+
const bars1h = Math.max(1, Math.round(36e5 / intervalMs));
|
|
211
|
+
const bars4h = Math.max(1, Math.round(144e5 / intervalMs));
|
|
212
|
+
const bars24h = Math.max(1, Math.round(864e5 / intervalMs));
|
|
213
|
+
for (const candles of Object.values(candlesBySymbol)) {
|
|
214
|
+
for (const candle of candles) timestamps.add(candle.timestamp);
|
|
215
|
+
}
|
|
216
|
+
return [...timestamps].sort((a, b) => a - b).map((timestamp) => {
|
|
217
|
+
const returns = [];
|
|
218
|
+
const weightedReturns = [];
|
|
219
|
+
let advancers = 0;
|
|
220
|
+
let decliners = 0;
|
|
221
|
+
let unchanged = 0;
|
|
222
|
+
let aboveMa20 = 0;
|
|
223
|
+
let aboveMa20Eligible = 0;
|
|
224
|
+
let aboveMa50 = 0;
|
|
225
|
+
let aboveMa50Eligible = 0;
|
|
226
|
+
const altReturns1h = [];
|
|
227
|
+
const altReturns4h = [];
|
|
228
|
+
const altReturns24h = [];
|
|
229
|
+
let altTurnover1h = 0;
|
|
230
|
+
let altTurnover24h = 0;
|
|
231
|
+
let previousAltTurnover24h = 0;
|
|
232
|
+
for (const indexed of indexedSymbols) {
|
|
233
|
+
const { candles, byTimestamp, turnoverPrefix, closePrefix } = indexed;
|
|
234
|
+
const index = byTimestamp.get(timestamp);
|
|
235
|
+
if (index == null) continue;
|
|
236
|
+
const candle = candles[index];
|
|
237
|
+
const previous = candles[index - 1];
|
|
238
|
+
const ret = previous && previous.close > 0 ? (candle.close - previous.close) / previous.close : 0;
|
|
239
|
+
if (ret > 0) advancers += 1;
|
|
240
|
+
else if (ret < 0) decliners += 1;
|
|
241
|
+
else unchanged += 1;
|
|
242
|
+
returns.push(ret);
|
|
243
|
+
weightedReturns.push({
|
|
244
|
+
value: ret,
|
|
245
|
+
weight: Math.max(0, candle.turnover ?? 0)
|
|
246
|
+
});
|
|
247
|
+
const ma20Start = index - 19;
|
|
248
|
+
if (ma20Start >= 0) {
|
|
249
|
+
aboveMa20Eligible += 1;
|
|
250
|
+
const ma20 = sumPrefixRange(closePrefix, ma20Start, index) / 20;
|
|
251
|
+
if (candle.close > ma20) aboveMa20 += 1;
|
|
252
|
+
}
|
|
253
|
+
const ma50Start = index - 49;
|
|
254
|
+
if (ma50Start >= 0) {
|
|
255
|
+
aboveMa50Eligible += 1;
|
|
256
|
+
const ma50 = sumPrefixRange(closePrefix, ma50Start, index) / 50;
|
|
257
|
+
if (candle.close > ma50) aboveMa50 += 1;
|
|
258
|
+
}
|
|
259
|
+
const altReturn1h = windowReturn(candles, index, bars1h);
|
|
260
|
+
const altReturn4h = windowReturn(candles, index, bars4h);
|
|
261
|
+
const altReturn24h = windowReturn(candles, index, bars24h);
|
|
262
|
+
if (altReturn1h != null) altReturns1h.push(altReturn1h);
|
|
263
|
+
if (altReturn4h != null) altReturns4h.push(altReturn4h);
|
|
264
|
+
if (altReturn24h != null) altReturns24h.push(altReturn24h);
|
|
265
|
+
altTurnover1h += sumPrefixRange(
|
|
266
|
+
turnoverPrefix,
|
|
267
|
+
index - bars1h + 1,
|
|
268
|
+
index
|
|
269
|
+
);
|
|
270
|
+
altTurnover24h += sumPrefixRange(
|
|
271
|
+
turnoverPrefix,
|
|
272
|
+
index - bars24h + 1,
|
|
273
|
+
index
|
|
274
|
+
);
|
|
275
|
+
previousAltTurnover24h += sumPrefixRange(
|
|
276
|
+
turnoverPrefix,
|
|
277
|
+
index - bars24h * 2 + 1,
|
|
278
|
+
index - bars24h
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
const weightSum = weightedReturns.reduce(
|
|
282
|
+
(sum, item) => sum + item.weight,
|
|
283
|
+
0
|
|
284
|
+
);
|
|
285
|
+
const volumeWeightedReturn = weightSum > 0 ? weightedReturns.reduce(
|
|
286
|
+
(sum, item) => sum + item.value * item.weight,
|
|
287
|
+
0
|
|
288
|
+
) / weightSum : null;
|
|
289
|
+
const btcIndex = btcIndexed?.byTimestamp.get(timestamp);
|
|
290
|
+
const btcReturn1h = btcIndexed && btcIndex != null ? windowReturn(btcIndexed.candles, btcIndex, bars1h) : null;
|
|
291
|
+
const btcReturn4h = btcIndexed && btcIndex != null ? windowReturn(btcIndexed.candles, btcIndex, bars4h) : null;
|
|
292
|
+
const btcReturn24h = btcIndexed && btcIndex != null ? windowReturn(btcIndexed.candles, btcIndex, bars24h) : null;
|
|
293
|
+
const btcTurnover1h = btcIndexed && btcIndex != null ? sumPrefixRange(
|
|
294
|
+
btcIndexed.turnoverPrefix,
|
|
295
|
+
btcIndex - bars1h + 1,
|
|
296
|
+
btcIndex
|
|
297
|
+
) : null;
|
|
298
|
+
const btcTurnover24h = btcIndexed && btcIndex != null ? sumPrefixRange(
|
|
299
|
+
btcIndexed.turnoverPrefix,
|
|
300
|
+
btcIndex - bars24h + 1,
|
|
301
|
+
btcIndex
|
|
302
|
+
) : null;
|
|
303
|
+
const previousBtcTurnover24h = btcIndexed && btcIndex != null ? sumPrefixRange(
|
|
304
|
+
btcIndexed.turnoverPrefix,
|
|
305
|
+
btcIndex - bars24h * 2 + 1,
|
|
306
|
+
btcIndex - bars24h
|
|
307
|
+
) : null;
|
|
308
|
+
const altBasketReturn1h = mean(altReturns1h);
|
|
309
|
+
const altBasketReturn4h = mean(altReturns4h);
|
|
310
|
+
const altBasketReturn24h = mean(altReturns24h);
|
|
311
|
+
const btcVsAltReturn1h = btcReturn1h == null || altBasketReturn1h == null ? null : btcReturn1h - altBasketReturn1h;
|
|
312
|
+
const btcVsAltReturn4h = btcReturn4h == null || altBasketReturn4h == null ? null : btcReturn4h - altBasketReturn4h;
|
|
313
|
+
const btcVsAltReturn24h = btcReturn24h == null || altBasketReturn24h == null ? null : btcReturn24h - altBasketReturn24h;
|
|
314
|
+
const btcTurnoverShare1h = btcTurnover1h == null ? null : safeDivide(btcTurnover1h, btcTurnover1h + altTurnover1h);
|
|
315
|
+
const btcTurnoverShare24h = btcTurnover24h == null ? null : safeDivide(btcTurnover24h, btcTurnover24h + altTurnover24h);
|
|
316
|
+
const previousBtcTurnoverShare24h = previousBtcTurnover24h == null ? null : safeDivide(
|
|
317
|
+
previousBtcTurnover24h,
|
|
318
|
+
previousBtcTurnover24h + previousAltTurnover24h
|
|
319
|
+
);
|
|
320
|
+
const btcTurnoverShareChange24h = btcTurnoverShare24h == null || previousBtcTurnoverShare24h == null ? null : btcTurnoverShare24h - previousBtcTurnoverShare24h;
|
|
321
|
+
return {
|
|
322
|
+
universe,
|
|
323
|
+
interval,
|
|
324
|
+
ts: new Date(timestamp),
|
|
325
|
+
symbolsCount: returns.length,
|
|
326
|
+
advancers,
|
|
327
|
+
decliners,
|
|
328
|
+
unchanged,
|
|
329
|
+
advanceDeclineRatio: safeDivide(advancers, decliners || 1),
|
|
330
|
+
pctAboveMa20: safeDivide(aboveMa20, aboveMa20Eligible),
|
|
331
|
+
pctAboveMa50: safeDivide(aboveMa50, aboveMa50Eligible),
|
|
332
|
+
equalWeightedReturn: mean(returns),
|
|
333
|
+
volumeWeightedReturn,
|
|
334
|
+
dispersion: standardDeviation(returns),
|
|
335
|
+
btcReturn1h,
|
|
336
|
+
btcReturn4h,
|
|
337
|
+
btcReturn24h,
|
|
338
|
+
altBasketReturn1h,
|
|
339
|
+
altBasketReturn4h,
|
|
340
|
+
altBasketReturn24h,
|
|
341
|
+
btcVsAltReturn1h,
|
|
342
|
+
btcVsAltReturn4h,
|
|
343
|
+
btcVsAltReturn24h,
|
|
344
|
+
btcTurnoverShare1h,
|
|
345
|
+
btcTurnoverShare24h,
|
|
346
|
+
btcTurnoverShareChange24h,
|
|
347
|
+
altVolToBtcVol24h: btcTurnover24h == null ? null : safeDivide(altTurnover24h, btcTurnover24h),
|
|
348
|
+
altDispersion24h: standardDeviation(altReturns24h),
|
|
349
|
+
btcAltRegime: classifyBtcAltRegime({
|
|
350
|
+
btcReturn24h,
|
|
351
|
+
altBasketReturn24h,
|
|
352
|
+
btcVsAltReturn24h
|
|
353
|
+
}),
|
|
354
|
+
source
|
|
355
|
+
};
|
|
356
|
+
}).filter((row) => row.symbolsCount > 0);
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// src/scripts/binanceMarketIngest.ts
|
|
360
|
+
import_args.default.example(
|
|
361
|
+
"yarn cli:node8g binance:market-ingest --all --symbols BTCUSDT,ETHUSDT --days 0.05 --interval 1m --write",
|
|
362
|
+
"Ingest Binance public market breadth and historical aggTrades buckets"
|
|
363
|
+
);
|
|
364
|
+
import_args.default.option(
|
|
365
|
+
["s", "symbols"],
|
|
366
|
+
"Comma-separated target symbols",
|
|
367
|
+
"BTCUSDT,ETHUSDT"
|
|
368
|
+
);
|
|
369
|
+
import_args.default.option(["i", "interval"], "Aggregation interval: 1m,5m,15m,1h", "1m");
|
|
370
|
+
import_args.default.option(["d", "days"], "Lookback window in days", "1");
|
|
371
|
+
import_args.default.option(["h", "hours"], "Lookback window in hours; overrides --days");
|
|
372
|
+
import_args.default.option(["a", "aggTrades"], "Fetch and bucket Binance aggTrades");
|
|
373
|
+
import_args.default.option(
|
|
374
|
+
["b", "breadth"],
|
|
375
|
+
"Build alt-basket market breadth from Binance klines"
|
|
376
|
+
);
|
|
377
|
+
import_args.default.option(["A", "all"], "Enable aggTrades and breadth");
|
|
378
|
+
import_args.default.option(
|
|
379
|
+
["w", "write"],
|
|
380
|
+
"Write rows to Timescale; without this flag only estimate"
|
|
381
|
+
);
|
|
382
|
+
import_args.default.option(
|
|
383
|
+
["B", "breadthLimit"],
|
|
384
|
+
"Top USDT symbols used for breadth universe",
|
|
385
|
+
30
|
|
386
|
+
);
|
|
387
|
+
import_args.default.option(
|
|
388
|
+
["M", "batchMinutes"],
|
|
389
|
+
"aggTrades request window size in minutes",
|
|
390
|
+
15
|
|
391
|
+
);
|
|
392
|
+
import_args.default.option(
|
|
393
|
+
["r", "requestDelayMs"],
|
|
394
|
+
"Delay between Binance aggTrades requests",
|
|
395
|
+
75
|
|
396
|
+
);
|
|
397
|
+
var flags = import_args.default.parse(process.argv);
|
|
398
|
+
var asFloat = (value, fallback) => {
|
|
399
|
+
const parsed = Number.parseFloat(String(value ?? ""));
|
|
400
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
401
|
+
};
|
|
402
|
+
var asInt = (value, fallback) => {
|
|
403
|
+
const parsed = Number.parseInt(String(value ?? ""), 10);
|
|
404
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
405
|
+
};
|
|
406
|
+
var sleep = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
|
|
407
|
+
var intervalToConnectorInterval = (interval) => {
|
|
408
|
+
if (interval === "1m") return "1";
|
|
409
|
+
if (interval === "5m") return "5";
|
|
410
|
+
if (interval === "15m") return "15";
|
|
411
|
+
return "60";
|
|
412
|
+
};
|
|
413
|
+
var fetchAggTradesForWindow = async ({
|
|
414
|
+
connector,
|
|
415
|
+
symbol,
|
|
416
|
+
fromMs,
|
|
417
|
+
toMs,
|
|
418
|
+
batchMinutes,
|
|
419
|
+
requestDelayMs
|
|
420
|
+
}) => {
|
|
421
|
+
if (!connector.getAggTrades) return [];
|
|
422
|
+
const rows = [];
|
|
423
|
+
const batchMs = Math.max(1, batchMinutes) * 6e4;
|
|
424
|
+
let cursor = fromMs;
|
|
425
|
+
while (cursor <= toMs) {
|
|
426
|
+
const endTime = Math.min(toMs, cursor + batchMs - 1);
|
|
427
|
+
let pageCursor = cursor;
|
|
428
|
+
while (pageCursor <= endTime) {
|
|
429
|
+
const page = await connector.getAggTrades({
|
|
430
|
+
symbol,
|
|
431
|
+
startTime: pageCursor,
|
|
432
|
+
endTime,
|
|
433
|
+
limit: 1e3
|
|
434
|
+
});
|
|
435
|
+
if (!page.length) break;
|
|
436
|
+
rows.push(...page);
|
|
437
|
+
const lastTs = page[page.length - 1]?.timestamp;
|
|
438
|
+
if (page.length < 1e3 || !Number.isFinite(lastTs)) break;
|
|
439
|
+
const nextCursor = Math.max(pageCursor + 1, Number(lastTs) + 1);
|
|
440
|
+
if (nextCursor > endTime) break;
|
|
441
|
+
pageCursor = nextCursor;
|
|
442
|
+
await sleep(requestDelayMs);
|
|
443
|
+
}
|
|
444
|
+
cursor = endTime + 1;
|
|
445
|
+
await sleep(requestDelayMs);
|
|
446
|
+
}
|
|
447
|
+
return rows;
|
|
448
|
+
};
|
|
449
|
+
var printEstimate = (estimate) => {
|
|
450
|
+
console.log(import_chalk.default.cyan("Binance market ingest estimate"));
|
|
451
|
+
console.log(`interval: ${estimate.interval}`);
|
|
452
|
+
console.log(`days: ${estimate.days}`);
|
|
453
|
+
console.log(`target symbols: ${estimate.symbols}`);
|
|
454
|
+
console.log(`bucket rows/symbol: ${estimate.bucketRowsPerSymbol}`);
|
|
455
|
+
console.log(`aggTrades bucket rows: ${estimate.aggTradeBucketRows}`);
|
|
456
|
+
console.log(`breadth symbols: ${estimate.breadthSymbols}`);
|
|
457
|
+
console.log(`breadth candle reads: ${estimate.breadthCandleRows}`);
|
|
458
|
+
console.log(`breadth rows: ${estimate.breadthRows}`);
|
|
459
|
+
console.log(`estimated stored rows: ${estimate.estimatedStoredRows}`);
|
|
460
|
+
};
|
|
461
|
+
var main = async () => {
|
|
462
|
+
const symbols = normalizeBinanceSymbols(flags.symbols);
|
|
463
|
+
const interval = normalizeMarketFeatureInterval(flags.interval);
|
|
464
|
+
const hours = flags.hours == null ? null : asFloat(flags.hours, 0);
|
|
465
|
+
const days = hours != null && hours > 0 ? hours / 24 : asFloat(flags.days, 1);
|
|
466
|
+
const breadthLimit = asInt(flags.breadthLimit, 30);
|
|
467
|
+
const batchMinutes = asInt(flags.batchMinutes, 15);
|
|
468
|
+
const requestDelayMs = asInt(flags.requestDelayMs, 75);
|
|
469
|
+
const includeAll = Boolean(flags.all);
|
|
470
|
+
const includeAggTrades = includeAll || Boolean(flags.aggTrades);
|
|
471
|
+
const includeBreadth = includeAll || Boolean(flags.breadth);
|
|
472
|
+
const anyMode = includeAggTrades || includeBreadth;
|
|
473
|
+
const modes = {
|
|
474
|
+
includeAggTrades: anyMode ? includeAggTrades : true,
|
|
475
|
+
includeBreadth: anyMode ? includeBreadth : true
|
|
476
|
+
};
|
|
477
|
+
if (!symbols.length) throw new Error("No symbols provided");
|
|
478
|
+
const estimate = estimateBinanceMarketDataVolume({
|
|
479
|
+
symbols,
|
|
480
|
+
days,
|
|
481
|
+
interval,
|
|
482
|
+
includeAggTrades: modes.includeAggTrades,
|
|
483
|
+
includeBreadth: modes.includeBreadth,
|
|
484
|
+
breadthLimit
|
|
485
|
+
});
|
|
486
|
+
printEstimate(estimate);
|
|
487
|
+
if (!flags.write) {
|
|
488
|
+
console.log(import_chalk.default.yellow("Dry run only. Pass --write to ingest."));
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
await (0, import_timescale.waitForDbReady)();
|
|
492
|
+
const connector = await import_connectors.connectors[import_connectors.ConnectorNames.Binance]({
|
|
493
|
+
userName: "root"
|
|
494
|
+
});
|
|
495
|
+
const toMs = Math.floor(Date.now() / MARKET_FEATURE_INTERVAL_MS[interval]) * MARKET_FEATURE_INTERVAL_MS[interval];
|
|
496
|
+
const fromMs = toMs - days * 864e5;
|
|
497
|
+
let aggTradesRaw = 0;
|
|
498
|
+
let tradeFlowRows = 0;
|
|
499
|
+
let breadthRows = 0;
|
|
500
|
+
let breadthCandleRows = 0;
|
|
501
|
+
if (modes.includeAggTrades) {
|
|
502
|
+
for (const symbol of symbols) {
|
|
503
|
+
process.stdout.write(import_chalk.default.cyan(`aggTrades ${symbol}... `));
|
|
504
|
+
const trades = await fetchAggTradesForWindow({
|
|
505
|
+
connector,
|
|
506
|
+
symbol,
|
|
507
|
+
fromMs,
|
|
508
|
+
toMs,
|
|
509
|
+
batchMinutes,
|
|
510
|
+
requestDelayMs
|
|
511
|
+
});
|
|
512
|
+
const rows = aggregateAggTradesToRows({ symbol, interval, trades });
|
|
513
|
+
await (0, import_timescale.upsertMarketTradeFlowRows)(rows);
|
|
514
|
+
aggTradesRaw += trades.length;
|
|
515
|
+
tradeFlowRows += rows.length;
|
|
516
|
+
process.stdout.write(
|
|
517
|
+
`${trades.length} trades -> ${rows.length} buckets
|
|
518
|
+
`
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
if (modes.includeBreadth) {
|
|
523
|
+
const tickers = await connector.getTickers();
|
|
524
|
+
const breadthSymbols = selectBreadthUniverseFromTickers(
|
|
525
|
+
tickers,
|
|
526
|
+
breadthLimit
|
|
527
|
+
);
|
|
528
|
+
const connectorInterval = intervalToConnectorInterval(interval);
|
|
529
|
+
const candlesBySymbol = {};
|
|
530
|
+
for (const symbol of breadthSymbols) {
|
|
531
|
+
process.stdout.write(import_chalk.default.cyan(`breadth candles ${symbol}... `));
|
|
532
|
+
const candles = await connector.kline({
|
|
533
|
+
symbol,
|
|
534
|
+
interval: connectorInterval,
|
|
535
|
+
start: fromMs,
|
|
536
|
+
end: toMs,
|
|
537
|
+
silent: true
|
|
538
|
+
});
|
|
539
|
+
candlesBySymbol[symbol] = candles;
|
|
540
|
+
breadthCandleRows += candles.length;
|
|
541
|
+
process.stdout.write(`${candles.length}
|
|
542
|
+
`);
|
|
543
|
+
}
|
|
544
|
+
const universe = `binance_top${breadthSymbols.length}_usdt`;
|
|
545
|
+
const rows = buildMarketBreadthRows({
|
|
546
|
+
universe,
|
|
547
|
+
interval,
|
|
548
|
+
candlesBySymbol
|
|
549
|
+
});
|
|
550
|
+
await (0, import_timescale.upsertMarketBreadthRows)(rows);
|
|
551
|
+
breadthRows += rows.length;
|
|
552
|
+
}
|
|
553
|
+
console.log(import_chalk.default.green("Binance market ingest done"));
|
|
554
|
+
console.log(`aggTrades raw rows: ${aggTradesRaw}`);
|
|
555
|
+
console.log(`trade-flow bucket rows: ${tradeFlowRows}`);
|
|
556
|
+
console.log(`breadth candle rows read: ${breadthCandleRows}`);
|
|
557
|
+
console.log(`breadth rows: ${breadthRows}`);
|
|
558
|
+
console.log(
|
|
559
|
+
`stored rows: ${tradeFlowRows + breadthRows} (raw aggTrades are not stored)`
|
|
560
|
+
);
|
|
561
|
+
};
|
|
562
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
563
|
+
0 && (module.exports = {
|
|
564
|
+
main
|
|
565
|
+
});
|
package/dist/scripts/bot.js
CHANGED
|
@@ -5,6 +5,10 @@ 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 __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
8
12
|
var __copyProps = (to, from, except, desc) => {
|
|
9
13
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
14
|
for (let key of __getOwnPropNames(from))
|
|
@@ -21,8 +25,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
25
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
26
|
mod
|
|
23
27
|
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
24
29
|
|
|
25
30
|
// src/scripts/bot.ts
|
|
31
|
+
var bot_exports = {};
|
|
32
|
+
__export(bot_exports, {
|
|
33
|
+
main: () => main
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(bot_exports);
|
|
26
36
|
var import_config = require("dotenv/config");
|
|
27
37
|
|
|
28
38
|
// src/lib/runBot.ts
|
|
@@ -128,6 +138,7 @@ var runBot = async () => {
|
|
|
128
138
|
const btcCandle = btcData.pop();
|
|
129
139
|
const strategy = await strategyCreator({
|
|
130
140
|
userName,
|
|
141
|
+
connectorName,
|
|
131
142
|
config: strategyConfig,
|
|
132
143
|
symbol,
|
|
133
144
|
data,
|
|
@@ -155,8 +166,11 @@ var runBot = async () => {
|
|
|
155
166
|
};
|
|
156
167
|
|
|
157
168
|
// src/scripts/bot.ts
|
|
158
|
-
var
|
|
169
|
+
var main = async () => {
|
|
159
170
|
await runBot();
|
|
160
171
|
process.exit();
|
|
161
172
|
};
|
|
162
|
-
|
|
173
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
174
|
+
0 && (module.exports = {
|
|
175
|
+
main
|
|
176
|
+
});
|
|
@@ -8,6 +8,10 @@ var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
|
8
8
|
var __commonJS = (cb, mod) => function __require() {
|
|
9
9
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
10
|
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
11
15
|
var __copyProps = (to, from, except, desc) => {
|
|
12
16
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
17
|
for (let key of __getOwnPropNames(from))
|
|
@@ -24,6 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
28
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
29
|
mod
|
|
26
30
|
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
32
|
|
|
28
33
|
// ../../node_modules/postgres-array/index.js
|
|
29
34
|
var require_postgres_array = __commonJS({
|
|
@@ -4957,6 +4962,11 @@ var require_lib2 = __commonJS({
|
|
|
4957
4962
|
});
|
|
4958
4963
|
|
|
4959
4964
|
// src/scripts/candlesMigrateProvider.ts
|
|
4965
|
+
var candlesMigrateProvider_exports = {};
|
|
4966
|
+
__export(candlesMigrateProvider_exports, {
|
|
4967
|
+
main: () => main
|
|
4968
|
+
});
|
|
4969
|
+
module.exports = __toCommonJS(candlesMigrateProvider_exports);
|
|
4960
4970
|
var import_args = __toESM(require("args"));
|
|
4961
4971
|
var import_chalk = __toESM(require("chalk"));
|
|
4962
4972
|
|
|
@@ -5276,27 +5286,27 @@ var printProgress = (message) => {
|
|
|
5276
5286
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
|
|
5277
5287
|
console.log(import_chalk.default.gray(`[${timestamp}] ${message}`));
|
|
5278
5288
|
};
|
|
5279
|
-
var
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
flags.
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5289
|
+
var main = async () => {
|
|
5290
|
+
try {
|
|
5291
|
+
printProgress(
|
|
5292
|
+
`Start candles provider migration for ${String(flags.schema || "public")}.${String(
|
|
5293
|
+
flags.table || "candles"
|
|
5294
|
+
)}${flags["dry-run"] ? " (dry-run)" : ""}`
|
|
5295
|
+
);
|
|
5296
|
+
const summary = await runCandlesProviderMigration(pool, {
|
|
5297
|
+
schema: String(flags.schema || "public"),
|
|
5298
|
+
table: String(flags.table || "candles"),
|
|
5299
|
+
dryRun: Boolean(flags["dry-run"]),
|
|
5300
|
+
recompress: !Boolean(flags["skip-recompress"]),
|
|
5301
|
+
keepPolicyPaused: Boolean(flags["keep-policy-paused"]),
|
|
5302
|
+
onProgress: printProgress
|
|
5303
|
+
});
|
|
5304
|
+
printSummary(summary);
|
|
5305
|
+
} finally {
|
|
5306
|
+
await pool.end().catch(() => void 0);
|
|
5307
|
+
}
|
|
5294
5308
|
};
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
);
|
|
5299
|
-
process.exitCode = 1;
|
|
5300
|
-
}).finally(async () => {
|
|
5301
|
-
await pool.end().catch(() => void 0);
|
|
5309
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
5310
|
+
0 && (module.exports = {
|
|
5311
|
+
main
|
|
5302
5312
|
});
|