@tradejs/cli 1.0.12 → 2.0.1
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/LICENSE +96 -0
- package/README.md +9 -1
- package/dist/cli.js +143 -93
- package/dist/lib/aiTrainResearch.js +0 -1
- package/dist/lib/derivativesContextBackfill.js +127 -83
- package/dist/lib/marketContextPrepare.js +123 -83
- package/dist/scripts/aiTrain.js +0 -1
- package/dist/scripts/backtest.js +123 -83
- package/dist/scripts/derivativesIngest.js +11 -4
- package/dist/scripts/derivativesIngestCoinalyzeAll.js +8 -4
- package/dist/scripts/replay.js +123 -83
- package/dist/scripts/replayRunner.js +123 -83
- package/dist/scripts/runtimeParity.js +123 -83
- package/dist/scripts/signals.js +123 -83
- package/dist/scripts/signalsDaemon.js +123 -83
- package/package.json +11 -11
package/LICENSE
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
Parameters
|
|
4
|
+
|
|
5
|
+
Licensor: TradeJS-Dev
|
|
6
|
+
|
|
7
|
+
Licensed Work: The software contained in this package, version 2.0.0 and later.
|
|
8
|
+
|
|
9
|
+
Additional Use Grant: You may make production use of the Licensed Work,
|
|
10
|
+
provided that you do not use the Licensed Work to offer a Competing Offering
|
|
11
|
+
to third parties.
|
|
12
|
+
|
|
13
|
+
A "Competing Offering" is a product or hosted or managed service whose primary
|
|
14
|
+
purpose is to provide a substantial portion of the functionality of TradeJS,
|
|
15
|
+
including strategy authoring, backtesting, live signal generation, automated
|
|
16
|
+
trading, or machine-learning training and inference workflows.
|
|
17
|
+
|
|
18
|
+
Internal use by you or your organization, including use for your own trading,
|
|
19
|
+
research, analytics, or operations, is not a Competing Offering.
|
|
20
|
+
|
|
21
|
+
Change Date: 2030-07-17
|
|
22
|
+
|
|
23
|
+
Change License: GNU Affero General Public License Version 3
|
|
24
|
+
|
|
25
|
+
For commercial licensing of a Competing Offering, contact the TradeJS-Dev
|
|
26
|
+
maintainers through https://github.com/TradeJS-Dev/TradeJS.
|
|
27
|
+
|
|
28
|
+
License text copyright © 2017 MariaDB Corporation Ab, All Rights Reserved.
|
|
29
|
+
"Business Source License" is a trademark of MariaDB Corporation Ab.
|
|
30
|
+
|
|
31
|
+
Terms
|
|
32
|
+
|
|
33
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
34
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
35
|
+
Licensor may make an Additional Use Grant, above, permitting limited
|
|
36
|
+
production use.
|
|
37
|
+
|
|
38
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
39
|
+
available distribution of a specific version of the Licensed Work under this
|
|
40
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
41
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
42
|
+
above terminate.
|
|
43
|
+
|
|
44
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
45
|
+
currently in effect as described in this License, you must purchase a
|
|
46
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
47
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
48
|
+
|
|
49
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
50
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
51
|
+
separately for each version of the Licensed Work and the Change Date may vary
|
|
52
|
+
for each version of the Licensed Work released by Licensor.
|
|
53
|
+
|
|
54
|
+
You must conspicuously display this License on each original or modified copy
|
|
55
|
+
of the Licensed Work. If you receive the Licensed Work in original or
|
|
56
|
+
modified form from a third party, the terms and conditions set forth in this
|
|
57
|
+
License apply to your use of that work.
|
|
58
|
+
|
|
59
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
60
|
+
terminate your rights under this License for the current and all other
|
|
61
|
+
versions of the Licensed Work.
|
|
62
|
+
|
|
63
|
+
This License does not grant you any right in any trademark or logo of
|
|
64
|
+
Licensor or its affiliates (provided that you may use a trademark or logo of
|
|
65
|
+
Licensor as expressly required by this License).
|
|
66
|
+
|
|
67
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
68
|
+
AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
69
|
+
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
70
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
71
|
+
TITLE.
|
|
72
|
+
|
|
73
|
+
MariaDB hereby grants you permission to use this License’s text to license
|
|
74
|
+
your works, and to refer to it using the trademark “Business Source License”,
|
|
75
|
+
as long as you comply with the Covenants of Licensor below.
|
|
76
|
+
|
|
77
|
+
Covenants of Licensor
|
|
78
|
+
|
|
79
|
+
In consideration of the right to use this License’s text and the “Business
|
|
80
|
+
Source License” name and trademark, Licensor covenants to MariaDB, and to all
|
|
81
|
+
other recipients of the licensed work to be provided by Licensor:
|
|
82
|
+
|
|
83
|
+
1. To specify as the Change License the GPL Version 2.0 or any later version,
|
|
84
|
+
or a license that is compatible with GPL Version 2.0 or a later version,
|
|
85
|
+
where “compatible” means that software provided under the Change License can
|
|
86
|
+
be included in a program with software provided under GPL Version 2.0 or a
|
|
87
|
+
later version. Licensor may specify additional Change Licenses without
|
|
88
|
+
limitation.
|
|
89
|
+
|
|
90
|
+
2. To either: (a) specify an additional grant of rights to use that does not
|
|
91
|
+
impose any additional restriction on the right granted in this License, as
|
|
92
|
+
the Additional Use Grant; or (b) insert the text “None”.
|
|
93
|
+
|
|
94
|
+
3. To specify a Change Date.
|
|
95
|
+
|
|
96
|
+
4. Not to modify this License in any other way.
|
package/README.md
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
# @tradejs/cli
|
|
2
2
|
|
|
3
|
-
Official CLI for the TradeJS
|
|
3
|
+
Official CLI for the TradeJS TypeScript framework.
|
|
4
4
|
|
|
5
5
|
- Homepage: https://tradejs.dev
|
|
6
6
|
- Documentation: https://docs.tradejs.dev
|
|
7
7
|
- CLI API docs: https://docs.tradejs.dev/api/cli
|
|
8
8
|
- Quickstart: https://docs.tradejs.dev/getting-started/quickstart
|
|
9
9
|
|
|
10
|
+
## License
|
|
11
|
+
|
|
12
|
+
Version 2.0.0 and later is licensed under Business Source License 1.1. The
|
|
13
|
+
Additional Use Grant permits internal and other non-competing production use;
|
|
14
|
+
providing a competing product or service requires a commercial license.
|
|
15
|
+
Earlier releases remain MIT-licensed. See the
|
|
16
|
+
[TradeJS licensing policy](https://github.com/TradeJS-Dev/TradeJS/blob/stable/LICENSING.md).
|
|
17
|
+
|
|
10
18
|
## Where It Fits
|
|
11
19
|
|
|
12
20
|
`@tradejs/cli` is the operational entrypoint for the standard external TradeJS project flow:
|
package/dist/cli.js
CHANGED
|
@@ -6151,7 +6151,6 @@ var init_aiTrainResearch = __esm({
|
|
|
6151
6151
|
"INTERVAL",
|
|
6152
6152
|
"DERIVATIVES_CONTEXT_ENABLED",
|
|
6153
6153
|
"DERIVATIVES_CONTEXT_TARGET_ENABLED",
|
|
6154
|
-
"DERIVATIVES_CONTEXT_INTERVALS",
|
|
6155
6154
|
"DERIVATIVES_CONTEXT_LOOKBACK_HOURS",
|
|
6156
6155
|
"DERIVATIVES_CONTEXT_EXTRA_REFERENCE_SYMBOLS",
|
|
6157
6156
|
"DERIVATIVES_CONTEXT_EXCHANGE_PRIORITY",
|
|
@@ -8591,7 +8590,7 @@ var init_binanceMarketContextBackfill = __esm({
|
|
|
8591
8590
|
});
|
|
8592
8591
|
|
|
8593
8592
|
// src/lib/derivativesContextBackfill.ts
|
|
8594
|
-
var import_chalk7, import_progress4, import_async, import_constants5, import_indicators, import_timescale2, import_userSettings2, HOUR_MS, DAY_MS6, DEFAULT_LOOKBACK_HOURS,
|
|
8593
|
+
var import_chalk7, import_progress4, import_async, import_constants5, import_indicators, import_timescale2, import_userSettings2, HOUR_MS, DAY_MS6, DEFAULT_LOOKBACK_HOURS, SOURCE_INTERVALS, coinalyzeIntervalMap, derivativesIntervalMs, lastRequestTs, asInt2, parseList, parseBooleanFlag, normalizeSymbols, isDerivativesTargetContextEnabled, resolveDerivativesContextBackfillSymbols, chunkArray, isBacktestDerivativesContextEnabled, isSignalsDerivativesContextEnabled, isDerivativesContextBackfillEnabled, shouldBackfillDerivativesContextForBacktest, shouldBackfillDerivativesContextForSignals, resolveDerivativesContextIntervals, resolveDerivativesContextLookbackMs, resolveDerivativesContextBackfillWindow, resolveDerivativesContextIntervalBackfillWindow, resolveDerivativesContextMissingFetchFromMs, resolveDerivativesContextFetchFromMs, countBackfillWindows, buildBackfillWindows, hasDerivativesWindowCoverage, resolveDerivativesContextMissingCoverageFetchFromMs, groupDerivativesContextMissingFetchRanges, getMissingClosedDerivativesSymbols, coverageKey, extendEdges, getCoinalyzeApiKey, getCoinalyzeBaseUrl, getRequestDelayMs, getRequestTimeoutMs, networkErrorCodes, getNestedErrorValue, getCoinalyzeErrorCause, isRetryableCoinalyzeFetchError, formatCoinalyzeRequestError, fetchJsonWithRateLimit, fetchCoinalyzeMarkets, selectBestMarket, buildMatches, normalizeMetricPoint, toSeriesMap, fetchMetricBatch, skippedBackfillResult2, backfillDerivativesContext, backfillDerivativesContextForBacktest, backfillDerivativesContextForSignals;
|
|
8595
8594
|
var init_derivativesContextBackfill = __esm({
|
|
8596
8595
|
"src/lib/derivativesContextBackfill.ts"() {
|
|
8597
8596
|
"use strict";
|
|
@@ -8605,7 +8604,7 @@ var init_derivativesContextBackfill = __esm({
|
|
|
8605
8604
|
HOUR_MS = 60 * 60 * 1e3;
|
|
8606
8605
|
DAY_MS6 = 24 * HOUR_MS;
|
|
8607
8606
|
DEFAULT_LOOKBACK_HOURS = 48;
|
|
8608
|
-
|
|
8607
|
+
SOURCE_INTERVALS = ["15m"];
|
|
8609
8608
|
coinalyzeIntervalMap = {
|
|
8610
8609
|
"15m": "15min",
|
|
8611
8610
|
"1h": "1hour"
|
|
@@ -8666,10 +8665,7 @@ var init_derivativesContextBackfill = __esm({
|
|
|
8666
8665
|
shouldBackfillDerivativesContextForBacktest = (params) => !params.cacheOnly && (params.aiEnabled || params.mlEnabled) && isBacktestDerivativesContextEnabled();
|
|
8667
8666
|
shouldBackfillDerivativesContextForSignals = (params) => !params.cacheOnly && isSignalsDerivativesContextEnabled();
|
|
8668
8667
|
resolveDerivativesContextIntervals = () => {
|
|
8669
|
-
|
|
8670
|
-
process.env.DERIVATIVES_CONTEXT_INTERVALS
|
|
8671
|
-
);
|
|
8672
|
-
return intervals.length ? intervals : DEFAULT_INTERVALS;
|
|
8668
|
+
return [...SOURCE_INTERVALS];
|
|
8673
8669
|
};
|
|
8674
8670
|
resolveDerivativesContextLookbackMs = () => {
|
|
8675
8671
|
const hours = Number(process.env.DERIVATIVES_CONTEXT_LOOKBACK_HOURS);
|
|
@@ -8704,9 +8700,10 @@ var init_derivativesContextBackfill = __esm({
|
|
|
8704
8700
|
};
|
|
8705
8701
|
resolveDerivativesContextIntervalBackfillWindow = (params) => {
|
|
8706
8702
|
const intervalMs2 = derivativesIntervalMs(params.interval);
|
|
8703
|
+
const alignedToMs = params.closedOnly ? (0, import_indicators.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs2) * intervalMs2;
|
|
8707
8704
|
return {
|
|
8708
8705
|
fromMs: Math.floor(params.fromMs / intervalMs2) * intervalMs2,
|
|
8709
|
-
toMs:
|
|
8706
|
+
toMs: alignedToMs,
|
|
8710
8707
|
intervalMs: intervalMs2
|
|
8711
8708
|
};
|
|
8712
8709
|
};
|
|
@@ -8724,6 +8721,7 @@ var init_derivativesContextBackfill = __esm({
|
|
|
8724
8721
|
}
|
|
8725
8722
|
return null;
|
|
8726
8723
|
};
|
|
8724
|
+
resolveDerivativesContextFetchFromMs = (params) => resolveDerivativesContextMissingFetchFromMs(params) ?? (params.refreshClosedTail ? params.toMs : null);
|
|
8727
8725
|
countBackfillWindows = (params) => {
|
|
8728
8726
|
let count = 0;
|
|
8729
8727
|
let cursor = params.fromMs;
|
|
@@ -8787,6 +8785,14 @@ var init_derivativesContextBackfill = __esm({
|
|
|
8787
8785
|
}
|
|
8788
8786
|
return [...groups.entries()].sort(([a], [b]) => a - b).map(([fromMs, items]) => ({ fromMs, items }));
|
|
8789
8787
|
};
|
|
8788
|
+
getMissingClosedDerivativesSymbols = (params) => {
|
|
8789
|
+
const availableSymbols = new Set(
|
|
8790
|
+
params.rows.filter((row) => row.ts.getTime() === params.expectedTimestamp).map((row) => row.symbol.trim().toUpperCase())
|
|
8791
|
+
);
|
|
8792
|
+
return params.symbols.filter(
|
|
8793
|
+
(symbol) => !availableSymbols.has(symbol.trim().toUpperCase())
|
|
8794
|
+
);
|
|
8795
|
+
};
|
|
8790
8796
|
coverageKey = (params) => [
|
|
8791
8797
|
params.symbol.trim().toUpperCase(),
|
|
8792
8798
|
params.interval,
|
|
@@ -9066,7 +9072,8 @@ var init_derivativesContextBackfill = __esm({
|
|
|
9066
9072
|
...resolveDerivativesContextIntervalBackfillWindow({
|
|
9067
9073
|
fromMs,
|
|
9068
9074
|
toMs: safeEndMs,
|
|
9069
|
-
interval: interval5
|
|
9075
|
+
interval: interval5,
|
|
9076
|
+
closedOnly: mode === "signals"
|
|
9070
9077
|
})
|
|
9071
9078
|
})).filter((item) => item.toMs > item.fromMs);
|
|
9072
9079
|
if (!intervalWindows.length) {
|
|
@@ -9125,7 +9132,7 @@ var init_derivativesContextBackfill = __esm({
|
|
|
9125
9132
|
}),
|
|
9126
9133
|
0
|
|
9127
9134
|
);
|
|
9128
|
-
const allBackfillWindowsCached = intervalWindows.every((window2) => {
|
|
9135
|
+
const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window2) => {
|
|
9129
9136
|
const edgesBySymbol = edgesByInterval.get(window2.interval);
|
|
9130
9137
|
const coverageKeys = coverageKeysByInterval.get(window2.interval);
|
|
9131
9138
|
const backfillWindows = buildBackfillWindows({
|
|
@@ -9255,7 +9262,7 @@ var init_derivativesContextBackfill = __esm({
|
|
|
9255
9262
|
return null;
|
|
9256
9263
|
}
|
|
9257
9264
|
const normalizedSymbol = item.symbol.toUpperCase();
|
|
9258
|
-
const coverageFromMs = resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
9265
|
+
const coverageFromMs = mode === "signals" ? cursor : resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
9259
9266
|
ranges: coverageRangesBySymbol.get(normalizedSymbol),
|
|
9260
9267
|
fromMs: cursor,
|
|
9261
9268
|
toMs,
|
|
@@ -9265,16 +9272,20 @@ var init_derivativesContextBackfill = __esm({
|
|
|
9265
9272
|
return null;
|
|
9266
9273
|
}
|
|
9267
9274
|
const edges = edgesBySymbol.get(normalizedSymbol);
|
|
9268
|
-
const edgesFromMs =
|
|
9275
|
+
const edgesFromMs = resolveDerivativesContextFetchFromMs({
|
|
9269
9276
|
edges,
|
|
9270
9277
|
fromMs: cursor,
|
|
9271
9278
|
toMs,
|
|
9272
|
-
intervalMs: intervalMs2
|
|
9279
|
+
intervalMs: intervalMs2,
|
|
9280
|
+
refreshClosedTail: mode === "signals"
|
|
9273
9281
|
});
|
|
9274
9282
|
if (edgesFromMs == null) {
|
|
9275
9283
|
return null;
|
|
9276
9284
|
}
|
|
9277
|
-
return {
|
|
9285
|
+
return {
|
|
9286
|
+
item,
|
|
9287
|
+
fromMs: Math.max(coverageFromMs, edgesFromMs)
|
|
9288
|
+
};
|
|
9278
9289
|
}).filter(
|
|
9279
9290
|
(item) => item != null
|
|
9280
9291
|
);
|
|
@@ -9288,85 +9299,113 @@ var init_derivativesContextBackfill = __esm({
|
|
|
9288
9299
|
const marketSymbols = missingBatch.map(
|
|
9289
9300
|
(item) => item.marketSymbol
|
|
9290
9301
|
);
|
|
9291
|
-
const
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
const
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9302
|
+
const maxClosedBarAttempts = mode === "signals" ? asInt2(
|
|
9303
|
+
process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_MAX_ATTEMPTS,
|
|
9304
|
+
3
|
|
9305
|
+
) : 1;
|
|
9306
|
+
const closedBarRetryDelayMs = asInt2(
|
|
9307
|
+
process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_RETRY_DELAY_MS,
|
|
9308
|
+
2e3
|
|
9309
|
+
);
|
|
9310
|
+
let rows = [];
|
|
9311
|
+
let missingClosedSymbols = [];
|
|
9312
|
+
for (let attempt = 1; attempt <= maxClosedBarAttempts; attempt += 1) {
|
|
9313
|
+
const oiMap = await fetchMetricBatch({
|
|
9314
|
+
endpoint: oiPath,
|
|
9315
|
+
metric: "oi",
|
|
9316
|
+
marketSymbols,
|
|
9317
|
+
apiKey,
|
|
9318
|
+
interval: interval5,
|
|
9319
|
+
fromMs: group.fromMs,
|
|
9320
|
+
toMs
|
|
9321
|
+
});
|
|
9322
|
+
const fundingMap = await fetchMetricBatch({
|
|
9323
|
+
endpoint: fundingPath,
|
|
9324
|
+
metric: "funding",
|
|
9325
|
+
marketSymbols,
|
|
9326
|
+
apiKey,
|
|
9327
|
+
interval: interval5,
|
|
9328
|
+
fromMs: group.fromMs,
|
|
9329
|
+
toMs
|
|
9330
|
+
});
|
|
9331
|
+
const liqMap = await fetchMetricBatch({
|
|
9332
|
+
endpoint: liqPath,
|
|
9333
|
+
metric: "liq",
|
|
9334
|
+
marketSymbols,
|
|
9335
|
+
apiKey,
|
|
9336
|
+
interval: interval5,
|
|
9337
|
+
fromMs: group.fromMs,
|
|
9338
|
+
toMs
|
|
9325
9339
|
});
|
|
9326
|
-
|
|
9327
|
-
|
|
9340
|
+
rows = missingBatch.flatMap((item) => {
|
|
9341
|
+
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
9342
|
+
const points = (0, import_indicators.mergeCoinalyzeMetrics)({
|
|
9343
|
+
symbol: item.symbol,
|
|
9344
|
+
oiRaw: oiMap.get(marketSymbol) ?? [],
|
|
9345
|
+
fundingRaw: fundingMap.get(marketSymbol) ?? [],
|
|
9346
|
+
liqRaw: liqMap.get(marketSymbol) ?? []
|
|
9347
|
+
});
|
|
9348
|
+
return (0, import_indicators.coinalyzePointsToRows)(points, interval5, "coinalyze");
|
|
9349
|
+
});
|
|
9350
|
+
missingClosedSymbols = mode === "signals" ? getMissingClosedDerivativesSymbols({
|
|
9351
|
+
symbols: missingBatch.map((item) => item.symbol),
|
|
9352
|
+
rows,
|
|
9353
|
+
expectedTimestamp: toMs
|
|
9354
|
+
}) : [];
|
|
9355
|
+
if (!missingClosedSymbols.length) break;
|
|
9356
|
+
if (attempt < maxClosedBarAttempts) {
|
|
9357
|
+
await (0, import_async.delay)(closedBarRetryDelayMs);
|
|
9358
|
+
}
|
|
9359
|
+
}
|
|
9360
|
+
if (missingClosedSymbols.length) {
|
|
9361
|
+
throw new Error(
|
|
9362
|
+
`Coinalyze closed ${interval5} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
|
|
9363
|
+
);
|
|
9364
|
+
}
|
|
9328
9365
|
if (rows.length) {
|
|
9329
9366
|
await (0, import_timescale2.upsertDerivatives)(rows);
|
|
9330
9367
|
totalRows += rows.length;
|
|
9331
9368
|
}
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
const
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
(rowsCountBySymbol.get(symbol) ?? 0) + 1
|
|
9338
|
-
);
|
|
9339
|
-
}
|
|
9340
|
-
const coverageRows = missingBatch.map((item) => {
|
|
9341
|
-
const normalizedSymbol = item.symbol.toUpperCase();
|
|
9342
|
-
const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
|
|
9343
|
-
return {
|
|
9344
|
-
source: "coinalyze",
|
|
9345
|
-
symbol: item.symbol,
|
|
9346
|
-
interval: interval5,
|
|
9347
|
-
fromMs: cursor,
|
|
9348
|
-
toMs,
|
|
9349
|
-
rowsCount
|
|
9350
|
-
};
|
|
9351
|
-
});
|
|
9352
|
-
await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
|
|
9353
|
-
for (const coverageRow of coverageRows) {
|
|
9354
|
-
const symbol = coverageRow.symbol.toUpperCase();
|
|
9355
|
-
edgesBySymbol.set(
|
|
9356
|
-
symbol,
|
|
9357
|
-
extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
|
|
9358
|
-
);
|
|
9359
|
-
coverageKeys.add(
|
|
9360
|
-
coverageKey({
|
|
9369
|
+
if (mode === "backtest") {
|
|
9370
|
+
const rowsCountBySymbol = /* @__PURE__ */ new Map();
|
|
9371
|
+
for (const row of rows) {
|
|
9372
|
+
const symbol = row.symbol.toUpperCase();
|
|
9373
|
+
rowsCountBySymbol.set(
|
|
9361
9374
|
symbol,
|
|
9375
|
+
(rowsCountBySymbol.get(symbol) ?? 0) + 1
|
|
9376
|
+
);
|
|
9377
|
+
}
|
|
9378
|
+
const coverageRows = missingBatch.map((item) => {
|
|
9379
|
+
const normalizedSymbol = item.symbol.toUpperCase();
|
|
9380
|
+
const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
|
|
9381
|
+
return {
|
|
9382
|
+
source: "coinalyze",
|
|
9383
|
+
symbol: item.symbol,
|
|
9362
9384
|
interval: interval5,
|
|
9363
9385
|
fromMs: cursor,
|
|
9364
|
-
toMs
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9386
|
+
toMs,
|
|
9387
|
+
rowsCount
|
|
9388
|
+
};
|
|
9389
|
+
});
|
|
9390
|
+
await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
|
|
9391
|
+
for (const coverageRow of coverageRows) {
|
|
9392
|
+
const symbol = coverageRow.symbol.toUpperCase();
|
|
9393
|
+
edgesBySymbol.set(
|
|
9394
|
+
symbol,
|
|
9395
|
+
extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
|
|
9396
|
+
);
|
|
9397
|
+
coverageKeys.add(
|
|
9398
|
+
coverageKey({
|
|
9399
|
+
symbol,
|
|
9400
|
+
interval: interval5,
|
|
9401
|
+
fromMs: cursor,
|
|
9402
|
+
toMs
|
|
9403
|
+
})
|
|
9404
|
+
);
|
|
9405
|
+
const coverageRanges = coverageRangesBySymbol.get(symbol) ?? [];
|
|
9406
|
+
coverageRanges.push({ fromMs: cursor, toMs });
|
|
9407
|
+
coverageRangesBySymbol.set(symbol, coverageRanges);
|
|
9408
|
+
}
|
|
9370
9409
|
}
|
|
9371
9410
|
}
|
|
9372
9411
|
}
|
|
@@ -18915,11 +18954,11 @@ var init_derivativesIngest = __esm({
|
|
|
18915
18954
|
import_userSettings4 = require("@tradejs/infra/userSettings");
|
|
18916
18955
|
import_connectors9 = require("@tradejs/connectors");
|
|
18917
18956
|
import_args12.default.example(
|
|
18918
|
-
"yarn ts-node ./src/scripts/derivativesIngest --provider coinalyze --symbols BTCUSDT,ETHUSDT --intervals 15m
|
|
18957
|
+
"yarn ts-node ./src/scripts/derivativesIngest --provider coinalyze --symbols BTCUSDT,ETHUSDT --intervals 15m --days 120",
|
|
18919
18958
|
"Ingest market features (derivatives/spread) into Timescale by provider"
|
|
18920
18959
|
);
|
|
18921
18960
|
import_args12.default.option(["s", "symbols"], "Comma-separated symbols", "BTCUSDT,ETHUSDT");
|
|
18922
|
-
import_args12.default.option(["t", "intervals"], "Comma-separated intervals: 15m,1h", "15m
|
|
18961
|
+
import_args12.default.option(["t", "intervals"], "Comma-separated intervals: 15m,1h", "15m");
|
|
18923
18962
|
import_args12.default.option(["d", "days"], "Lookback in days", 120);
|
|
18924
18963
|
import_args12.default.option(
|
|
18925
18964
|
["p", "provider"],
|
|
@@ -18956,9 +18995,16 @@ var init_derivativesIngest = __esm({
|
|
|
18956
18995
|
let totalSpreadRows = 0;
|
|
18957
18996
|
for (const symbol of symbols) {
|
|
18958
18997
|
for (const interval5 of intervals) {
|
|
18998
|
+
const lastClosedStartMs = (0, import_indicators2.getLastClosedDerivativesBarStartMs)(
|
|
18999
|
+
now2,
|
|
19000
|
+
interval5
|
|
19001
|
+
);
|
|
18959
19002
|
let cursor = fromMs;
|
|
18960
|
-
while (cursor <
|
|
18961
|
-
const toMs = Math.min(
|
|
19003
|
+
while (cursor < lastClosedStartMs) {
|
|
19004
|
+
const toMs = Math.min(
|
|
19005
|
+
lastClosedStartMs,
|
|
19006
|
+
cursor + batchDays * 24 * 60 * 60 * 1e3
|
|
19007
|
+
);
|
|
18962
19008
|
process.stdout.write(
|
|
18963
19009
|
`\r${import_chalk20.default.cyan(providerName)} ${import_chalk20.default.yellow(symbol)} ${interval5} ${new Date(cursor).toISOString()} .. ${new Date(toMs).toISOString()} `
|
|
18964
19010
|
);
|
|
@@ -19018,7 +19064,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
19018
19064
|
"1h": "1hour"
|
|
19019
19065
|
};
|
|
19020
19066
|
import_args13.default.example(
|
|
19021
|
-
"yarn ts-node ./src/scripts/derivativesIngestCoinalyzeAll --days 120 --intervals 15m
|
|
19067
|
+
"yarn ts-node ./src/scripts/derivativesIngestCoinalyzeAll --days 120 --intervals 15m",
|
|
19022
19068
|
"Fetch derivatives for all getTickers symbols matched to Coinalyze markets"
|
|
19023
19069
|
);
|
|
19024
19070
|
import_args13.default.option(["U", "user"], "User settings profile name from Redis", "root");
|
|
@@ -19026,7 +19072,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
19026
19072
|
import_args13.default.option(["e", "exclude"], "Comma-separated exclude symbols");
|
|
19027
19073
|
import_args13.default.option(["l", "tickersLimit"], "Tickers limit");
|
|
19028
19074
|
import_args13.default.option(["c", "chunk"], "Chunk selector, e.g. 1/4");
|
|
19029
|
-
import_args13.default.option(["i", "intervals"], "Intervals: 15m,1h", "15m
|
|
19075
|
+
import_args13.default.option(["i", "intervals"], "Intervals: 15m,1h", "15m");
|
|
19030
19076
|
import_args13.default.option(["d", "days"], "Lookback in days", 120);
|
|
19031
19077
|
import_args13.default.option(["b", "batchDays"], "Request chunk size in days", 120);
|
|
19032
19078
|
import_args13.default.option(
|
|
@@ -19295,12 +19341,16 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
19295
19341
|
let totalRows = 0;
|
|
19296
19342
|
let failedWindows = 0;
|
|
19297
19343
|
for (const interval5 of intervals) {
|
|
19344
|
+
const lastClosedStartMs = (0, import_indicators3.getLastClosedDerivativesBarStartMs)(now2, interval5);
|
|
19298
19345
|
for (let batchIdx = 0; batchIdx < symbolBatches.length; batchIdx += 1) {
|
|
19299
19346
|
const batch = symbolBatches[batchIdx];
|
|
19300
19347
|
const marketSymbols = batch.map((item) => item.marketSymbol);
|
|
19301
19348
|
let cursor = fromMs;
|
|
19302
|
-
while (cursor <
|
|
19303
|
-
const toMs = Math.min(
|
|
19349
|
+
while (cursor < lastClosedStartMs) {
|
|
19350
|
+
const toMs = Math.min(
|
|
19351
|
+
lastClosedStartMs,
|
|
19352
|
+
cursor + batchDays * 24 * 60 * 60 * 1e3
|
|
19353
|
+
);
|
|
19304
19354
|
try {
|
|
19305
19355
|
const oiMap = await fetchMetricBatch2({
|
|
19306
19356
|
endpoint: oiPath,
|
|
@@ -273,7 +273,6 @@ var RESEARCH_CONTEXT_ENV_KEYS = [
|
|
|
273
273
|
"INTERVAL",
|
|
274
274
|
"DERIVATIVES_CONTEXT_ENABLED",
|
|
275
275
|
"DERIVATIVES_CONTEXT_TARGET_ENABLED",
|
|
276
|
-
"DERIVATIVES_CONTEXT_INTERVALS",
|
|
277
276
|
"DERIVATIVES_CONTEXT_LOOKBACK_HOURS",
|
|
278
277
|
"DERIVATIVES_CONTEXT_EXTRA_REFERENCE_SYMBOLS",
|
|
279
278
|
"DERIVATIVES_CONTEXT_EXCHANGE_PRIORITY",
|