@tradejs/cli 2.0.0 → 2.0.2
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 +384 -122
- package/dist/lib/aiTrainCharts.js +49 -2
- package/dist/lib/aiTrainMetrics.js +49 -2
- package/dist/lib/aiTrainResearch.js +58 -4
- package/dist/lib/derivativesContextBackfill.js +262 -107
- package/dist/lib/marketContextPrepare.js +256 -107
- package/dist/scripts/aiPocketSearch.js +49 -2
- package/dist/scripts/aiTrain.js +76 -4
- package/dist/scripts/backtest.js +256 -107
- package/dist/scripts/derivativesIngest.js +11 -4
- package/dist/scripts/derivativesIngestCoinalyzeAll.js +38 -4
- package/dist/scripts/replay.js +256 -107
- package/dist/scripts/replayRunner.js +256 -107
- package/dist/scripts/runtimeParity.js +256 -107
- package/dist/scripts/signals.js +256 -107
- package/dist/scripts/signalsDaemon.js +256 -107
- package/package.json +9 -9
|
@@ -33,6 +33,7 @@ __export(derivativesContextBackfill_exports, {
|
|
|
33
33
|
backfillDerivativesContextForBacktest: () => backfillDerivativesContextForBacktest,
|
|
34
34
|
backfillDerivativesContextForSignals: () => backfillDerivativesContextForSignals,
|
|
35
35
|
formatCoinalyzeRequestError: () => formatCoinalyzeRequestError,
|
|
36
|
+
getMissingClosedDerivativesSymbols: () => getMissingClosedDerivativesSymbols,
|
|
36
37
|
groupDerivativesContextMissingFetchRanges: () => groupDerivativesContextMissingFetchRanges,
|
|
37
38
|
hasDerivativesContextCoverageRange: () => hasDerivativesContextCoverageRange,
|
|
38
39
|
isBacktestDerivativesContextEnabled: () => isBacktestDerivativesContextEnabled,
|
|
@@ -40,11 +41,13 @@ __export(derivativesContextBackfill_exports, {
|
|
|
40
41
|
isSignalsDerivativesContextEnabled: () => isSignalsDerivativesContextEnabled,
|
|
41
42
|
resolveDerivativesContextBackfillSymbols: () => resolveDerivativesContextBackfillSymbols,
|
|
42
43
|
resolveDerivativesContextBackfillWindow: () => resolveDerivativesContextBackfillWindow,
|
|
44
|
+
resolveDerivativesContextFetchFromMs: () => resolveDerivativesContextFetchFromMs,
|
|
43
45
|
resolveDerivativesContextIntervalBackfillWindow: () => resolveDerivativesContextIntervalBackfillWindow,
|
|
44
46
|
resolveDerivativesContextIntervals: () => resolveDerivativesContextIntervals,
|
|
45
47
|
resolveDerivativesContextLookbackMs: () => resolveDerivativesContextLookbackMs,
|
|
46
48
|
resolveDerivativesContextMissingCoverageFetchFromMs: () => resolveDerivativesContextMissingCoverageFetchFromMs,
|
|
47
49
|
resolveDerivativesContextMissingFetchFromMs: () => resolveDerivativesContextMissingFetchFromMs,
|
|
50
|
+
resolveDerivativesContextRequiredFetchFromMs: () => resolveDerivativesContextRequiredFetchFromMs,
|
|
48
51
|
shouldBackfillDerivativesContextForBacktest: () => shouldBackfillDerivativesContextForBacktest,
|
|
49
52
|
shouldBackfillDerivativesContextForSignals: () => shouldBackfillDerivativesContextForSignals
|
|
50
53
|
});
|
|
@@ -59,7 +62,7 @@ var import_userSettings = require("@tradejs/infra/userSettings");
|
|
|
59
62
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
60
63
|
var DAY_MS = 24 * HOUR_MS;
|
|
61
64
|
var DEFAULT_LOOKBACK_HOURS = 48;
|
|
62
|
-
var
|
|
65
|
+
var SOURCE_INTERVALS = ["15m"];
|
|
63
66
|
var coinalyzeIntervalMap = {
|
|
64
67
|
"15m": "15min",
|
|
65
68
|
"1h": "1hour"
|
|
@@ -120,10 +123,7 @@ var isDerivativesContextBackfillEnabled = (env) => {
|
|
|
120
123
|
var shouldBackfillDerivativesContextForBacktest = (params) => !params.cacheOnly && (params.aiEnabled || params.mlEnabled) && isBacktestDerivativesContextEnabled();
|
|
121
124
|
var shouldBackfillDerivativesContextForSignals = (params) => !params.cacheOnly && isSignalsDerivativesContextEnabled();
|
|
122
125
|
var resolveDerivativesContextIntervals = () => {
|
|
123
|
-
|
|
124
|
-
process.env.DERIVATIVES_CONTEXT_INTERVALS
|
|
125
|
-
);
|
|
126
|
-
return intervals.length ? intervals : DEFAULT_INTERVALS;
|
|
126
|
+
return [...SOURCE_INTERVALS];
|
|
127
127
|
};
|
|
128
128
|
var resolveDerivativesContextLookbackMs = () => {
|
|
129
129
|
const hours = Number(process.env.DERIVATIVES_CONTEXT_LOOKBACK_HOURS);
|
|
@@ -158,9 +158,10 @@ var resolveDerivativesContextBackfillWindow = (params) => {
|
|
|
158
158
|
};
|
|
159
159
|
var resolveDerivativesContextIntervalBackfillWindow = (params) => {
|
|
160
160
|
const intervalMs = derivativesIntervalMs(params.interval);
|
|
161
|
+
const alignedToMs = params.closedOnly ? (0, import_indicators.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs) * intervalMs;
|
|
161
162
|
return {
|
|
162
163
|
fromMs: Math.floor(params.fromMs / intervalMs) * intervalMs,
|
|
163
|
-
toMs:
|
|
164
|
+
toMs: alignedToMs,
|
|
164
165
|
intervalMs
|
|
165
166
|
};
|
|
166
167
|
};
|
|
@@ -178,6 +179,39 @@ var resolveDerivativesContextMissingFetchFromMs = (params) => {
|
|
|
178
179
|
}
|
|
179
180
|
return null;
|
|
180
181
|
};
|
|
182
|
+
var resolveDerivativesContextFetchFromMs = (params) => resolveDerivativesContextMissingFetchFromMs(params) ?? (params.refreshClosedTail ? params.toMs : null);
|
|
183
|
+
var resolveDerivativesContextRequiredFetchFromMs = (params) => {
|
|
184
|
+
const dataCoverageFromMs = params.dataCoverageKeyExists ? null : params.mode === "signals" ? params.fromMs : resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
185
|
+
ranges: params.dataCoverageRanges,
|
|
186
|
+
fromMs: params.fromMs,
|
|
187
|
+
toMs: params.toMs,
|
|
188
|
+
intervalMs: params.intervalMs
|
|
189
|
+
});
|
|
190
|
+
const edgesFromMs = dataCoverageFromMs == null ? null : resolveDerivativesContextFetchFromMs({
|
|
191
|
+
edges: params.edges,
|
|
192
|
+
fromMs: params.fromMs,
|
|
193
|
+
toMs: params.toMs,
|
|
194
|
+
intervalMs: params.intervalMs,
|
|
195
|
+
refreshClosedTail: params.mode === "signals"
|
|
196
|
+
});
|
|
197
|
+
const dataFetchFromMs = dataCoverageFromMs != null && edgesFromMs != null ? Math.max(dataCoverageFromMs, edgesFromMs) : null;
|
|
198
|
+
const confirmedLiquidationWindow = (0, import_indicators.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
199
|
+
interval: params.interval,
|
|
200
|
+
fromMs: params.fromMs,
|
|
201
|
+
toMs: params.toMs,
|
|
202
|
+
nowMs: params.nowMs
|
|
203
|
+
});
|
|
204
|
+
const liquidationFetchFromMs = confirmedLiquidationWindow ? resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
205
|
+
ranges: params.liquidationCoverageRanges,
|
|
206
|
+
fromMs: confirmedLiquidationWindow.fromMs,
|
|
207
|
+
toMs: confirmedLiquidationWindow.toMs,
|
|
208
|
+
intervalMs: params.intervalMs
|
|
209
|
+
}) : null;
|
|
210
|
+
const fetchStarts = [dataFetchFromMs, liquidationFetchFromMs].filter(
|
|
211
|
+
(value) => value != null
|
|
212
|
+
);
|
|
213
|
+
return fetchStarts.length ? Math.min(...fetchStarts) : null;
|
|
214
|
+
};
|
|
181
215
|
var countBackfillWindows = (params) => {
|
|
182
216
|
let count = 0;
|
|
183
217
|
let cursor = params.fromMs;
|
|
@@ -244,6 +278,14 @@ var groupDerivativesContextMissingFetchRanges = (ranges) => {
|
|
|
244
278
|
}
|
|
245
279
|
return [...groups.entries()].sort(([a], [b]) => a - b).map(([fromMs, items]) => ({ fromMs, items }));
|
|
246
280
|
};
|
|
281
|
+
var getMissingClosedDerivativesSymbols = (params) => {
|
|
282
|
+
const availableSymbols = new Set(
|
|
283
|
+
params.rows.filter((row) => row.ts.getTime() === params.expectedTimestamp).map((row) => row.symbol.trim().toUpperCase())
|
|
284
|
+
);
|
|
285
|
+
return params.symbols.filter(
|
|
286
|
+
(symbol) => !availableSymbols.has(symbol.trim().toUpperCase())
|
|
287
|
+
);
|
|
288
|
+
};
|
|
247
289
|
var coverageKey = (params) => [
|
|
248
290
|
params.symbol.trim().toUpperCase(),
|
|
249
291
|
params.interval,
|
|
@@ -508,7 +550,8 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
508
550
|
mode,
|
|
509
551
|
startMs,
|
|
510
552
|
endMs,
|
|
511
|
-
preloadStartMs: params.preloadStartMs
|
|
553
|
+
preloadStartMs: params.preloadStartMs,
|
|
554
|
+
nowMs: Date.now()
|
|
512
555
|
});
|
|
513
556
|
if (safeEndMs <= fromMs) {
|
|
514
557
|
return skippedBackfillResult();
|
|
@@ -523,7 +566,8 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
523
566
|
...resolveDerivativesContextIntervalBackfillWindow({
|
|
524
567
|
fromMs,
|
|
525
568
|
toMs: safeEndMs,
|
|
526
|
-
interval
|
|
569
|
+
interval,
|
|
570
|
+
closedOnly: mode === "signals"
|
|
527
571
|
})
|
|
528
572
|
})).filter((item) => item.toMs > item.fromMs);
|
|
529
573
|
if (!intervalWindows.length) {
|
|
@@ -541,15 +585,33 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
541
585
|
);
|
|
542
586
|
const coverageKeysByInterval = /* @__PURE__ */ new Map();
|
|
543
587
|
const coverageRangesByInterval = /* @__PURE__ */ new Map();
|
|
588
|
+
const liquidationCoverageRangesByInterval = /* @__PURE__ */ new Map();
|
|
589
|
+
const coverageNowMs = Date.now();
|
|
544
590
|
await Promise.all(
|
|
545
591
|
intervalWindows.map(async (window) => {
|
|
546
|
-
const
|
|
547
|
-
source: "coinalyze",
|
|
548
|
-
symbols,
|
|
592
|
+
const confirmedLiquidationWindow = (0, import_indicators.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
549
593
|
interval: window.interval,
|
|
550
594
|
fromMs: window.fromMs,
|
|
551
|
-
toMs: window.toMs
|
|
595
|
+
toMs: window.toMs,
|
|
596
|
+
nowMs: coverageNowMs
|
|
552
597
|
});
|
|
598
|
+
const [coverageRows, liquidationCoverageRows] = await Promise.all([
|
|
599
|
+
(0, import_timescale.getDerivativesBackfillCoverage)({
|
|
600
|
+
source: "coinalyze",
|
|
601
|
+
symbols,
|
|
602
|
+
interval: window.interval,
|
|
603
|
+
fromMs: window.fromMs,
|
|
604
|
+
toMs: window.toMs
|
|
605
|
+
}),
|
|
606
|
+
confirmedLiquidationWindow ? (0, import_timescale.getDerivativesMetricCoverage)({
|
|
607
|
+
source: "coinalyze",
|
|
608
|
+
metric: "liquidation",
|
|
609
|
+
symbols,
|
|
610
|
+
interval: window.interval,
|
|
611
|
+
fromMs: confirmedLiquidationWindow.fromMs,
|
|
612
|
+
toMs: confirmedLiquidationWindow.toMs
|
|
613
|
+
}) : Promise.resolve([])
|
|
614
|
+
]);
|
|
553
615
|
coverageKeysByInterval.set(
|
|
554
616
|
window.interval,
|
|
555
617
|
new Set(
|
|
@@ -571,6 +633,17 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
571
633
|
rangesBySymbol.set(symbol, ranges);
|
|
572
634
|
}
|
|
573
635
|
coverageRangesByInterval.set(window.interval, rangesBySymbol);
|
|
636
|
+
const liquidationRangesBySymbol = /* @__PURE__ */ new Map();
|
|
637
|
+
for (const row of liquidationCoverageRows) {
|
|
638
|
+
const symbol = row.symbol.toUpperCase();
|
|
639
|
+
const ranges = liquidationRangesBySymbol.get(symbol) ?? [];
|
|
640
|
+
ranges.push({ fromMs: row.fromMs, toMs: row.toMs });
|
|
641
|
+
liquidationRangesBySymbol.set(symbol, ranges);
|
|
642
|
+
}
|
|
643
|
+
liquidationCoverageRangesByInterval.set(
|
|
644
|
+
window.interval,
|
|
645
|
+
liquidationRangesBySymbol
|
|
646
|
+
);
|
|
574
647
|
})
|
|
575
648
|
);
|
|
576
649
|
const cachedWindows = intervalWindows.reduce(
|
|
@@ -582,7 +655,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
582
655
|
}),
|
|
583
656
|
0
|
|
584
657
|
);
|
|
585
|
-
const allBackfillWindowsCached = intervalWindows.every((window) => {
|
|
658
|
+
const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window) => {
|
|
586
659
|
const edgesBySymbol = edgesByInterval.get(window.interval);
|
|
587
660
|
const coverageKeys = coverageKeysByInterval.get(window.interval);
|
|
588
661
|
const backfillWindows = buildBackfillWindows({
|
|
@@ -595,7 +668,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
595
668
|
(symbol) => backfillWindows.every((backfillWindow) => {
|
|
596
669
|
const normalizedSymbol = symbol.toUpperCase();
|
|
597
670
|
const coverageRanges = coverageRangesByInterval.get(window.interval)?.get(normalizedSymbol) ?? [];
|
|
598
|
-
|
|
671
|
+
const dataCovered = hasDerivativesWindowCoverage({
|
|
599
672
|
edges: edgesBySymbol?.get(normalizedSymbol),
|
|
600
673
|
fromMs: backfillWindow.fromMs,
|
|
601
674
|
toMs: backfillWindow.toMs
|
|
@@ -612,6 +685,19 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
612
685
|
toMs: backfillWindow.toMs
|
|
613
686
|
})
|
|
614
687
|
);
|
|
688
|
+
const confirmedLiquidationWindow = (0, import_indicators.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
689
|
+
interval: window.interval,
|
|
690
|
+
fromMs: backfillWindow.fromMs,
|
|
691
|
+
toMs: backfillWindow.toMs,
|
|
692
|
+
nowMs: coverageNowMs
|
|
693
|
+
});
|
|
694
|
+
const liquidationCovered = confirmedLiquidationWindow == null || resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
695
|
+
ranges: liquidationCoverageRangesByInterval.get(window.interval)?.get(normalizedSymbol) ?? [],
|
|
696
|
+
fromMs: confirmedLiquidationWindow.fromMs,
|
|
697
|
+
toMs: confirmedLiquidationWindow.toMs,
|
|
698
|
+
intervalMs: window.intervalMs
|
|
699
|
+
}) == null;
|
|
700
|
+
return dataCovered && liquidationCovered;
|
|
615
701
|
})
|
|
616
702
|
);
|
|
617
703
|
});
|
|
@@ -696,6 +782,11 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
696
782
|
coverageKeysByInterval.set(interval, coverageKeys);
|
|
697
783
|
const coverageRangesBySymbol = coverageRangesByInterval.get(interval) ?? /* @__PURE__ */ new Map();
|
|
698
784
|
coverageRangesByInterval.set(interval, coverageRangesBySymbol);
|
|
785
|
+
const liquidationCoverageRangesBySymbol = liquidationCoverageRangesByInterval.get(interval) ?? /* @__PURE__ */ new Map();
|
|
786
|
+
liquidationCoverageRangesByInterval.set(
|
|
787
|
+
interval,
|
|
788
|
+
liquidationCoverageRangesBySymbol
|
|
789
|
+
);
|
|
699
790
|
for (let batchIdx = 0; batchIdx < symbolBatches.length; batchIdx += 1) {
|
|
700
791
|
const batch = symbolBatches[batchIdx];
|
|
701
792
|
let cursor = window.fromMs;
|
|
@@ -708,30 +799,26 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
708
799
|
fromMs: cursor,
|
|
709
800
|
toMs
|
|
710
801
|
});
|
|
711
|
-
if (coverageKeys.has(key)) {
|
|
712
|
-
return null;
|
|
713
|
-
}
|
|
714
802
|
const normalizedSymbol = item.symbol.toUpperCase();
|
|
715
|
-
const
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
}
|
|
734
|
-
return { item, fromMs: Math.max(coverageFromMs, edgesFromMs) };
|
|
803
|
+
const requiredFromMs = resolveDerivativesContextRequiredFetchFromMs(
|
|
804
|
+
{
|
|
805
|
+
mode,
|
|
806
|
+
interval,
|
|
807
|
+
intervalMs,
|
|
808
|
+
fromMs: cursor,
|
|
809
|
+
toMs,
|
|
810
|
+
nowMs: coverageNowMs,
|
|
811
|
+
dataCoverageKeyExists: coverageKeys.has(key),
|
|
812
|
+
dataCoverageRanges: coverageRangesBySymbol.get(normalizedSymbol),
|
|
813
|
+
liquidationCoverageRanges: liquidationCoverageRangesBySymbol.get(normalizedSymbol),
|
|
814
|
+
edges: edgesBySymbol.get(normalizedSymbol)
|
|
815
|
+
}
|
|
816
|
+
);
|
|
817
|
+
if (requiredFromMs == null) return null;
|
|
818
|
+
return {
|
|
819
|
+
item,
|
|
820
|
+
fromMs: requiredFromMs
|
|
821
|
+
};
|
|
735
822
|
}).filter(
|
|
736
823
|
(item) => item != null
|
|
737
824
|
);
|
|
@@ -745,85 +832,150 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
745
832
|
const marketSymbols = missingBatch.map(
|
|
746
833
|
(item) => item.marketSymbol
|
|
747
834
|
);
|
|
748
|
-
const
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
metric: "liq",
|
|
769
|
-
marketSymbols,
|
|
770
|
-
apiKey,
|
|
771
|
-
interval,
|
|
772
|
-
fromMs: group.fromMs,
|
|
773
|
-
toMs
|
|
774
|
-
});
|
|
775
|
-
const rows = missingBatch.flatMap((item) => {
|
|
776
|
-
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
777
|
-
const points = (0, import_indicators.mergeCoinalyzeMetrics)({
|
|
778
|
-
symbol: item.symbol,
|
|
779
|
-
oiRaw: oiMap.get(marketSymbol) ?? [],
|
|
780
|
-
fundingRaw: fundingMap.get(marketSymbol) ?? [],
|
|
781
|
-
liqRaw: liqMap.get(marketSymbol) ?? []
|
|
835
|
+
const maxClosedBarAttempts = mode === "signals" ? asInt(
|
|
836
|
+
process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_MAX_ATTEMPTS,
|
|
837
|
+
3
|
|
838
|
+
) : 1;
|
|
839
|
+
const closedBarRetryDelayMs = asInt(
|
|
840
|
+
process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_RETRY_DELAY_MS,
|
|
841
|
+
2e3
|
|
842
|
+
);
|
|
843
|
+
let rows = [];
|
|
844
|
+
let missingClosedSymbols = [];
|
|
845
|
+
let liquidationRowsByMarket = /* @__PURE__ */ new Map();
|
|
846
|
+
for (let attempt = 1; attempt <= maxClosedBarAttempts; attempt += 1) {
|
|
847
|
+
const oiMap = await fetchMetricBatch({
|
|
848
|
+
endpoint: oiPath,
|
|
849
|
+
metric: "oi",
|
|
850
|
+
marketSymbols,
|
|
851
|
+
apiKey,
|
|
852
|
+
interval,
|
|
853
|
+
fromMs: group.fromMs,
|
|
854
|
+
toMs
|
|
782
855
|
});
|
|
783
|
-
|
|
784
|
-
|
|
856
|
+
const fundingMap = await fetchMetricBatch({
|
|
857
|
+
endpoint: fundingPath,
|
|
858
|
+
metric: "funding",
|
|
859
|
+
marketSymbols,
|
|
860
|
+
apiKey,
|
|
861
|
+
interval,
|
|
862
|
+
fromMs: group.fromMs,
|
|
863
|
+
toMs
|
|
864
|
+
});
|
|
865
|
+
liquidationRowsByMarket = await fetchMetricBatch({
|
|
866
|
+
endpoint: liqPath,
|
|
867
|
+
metric: "liq",
|
|
868
|
+
marketSymbols,
|
|
869
|
+
apiKey,
|
|
870
|
+
interval,
|
|
871
|
+
fromMs: group.fromMs,
|
|
872
|
+
toMs
|
|
873
|
+
});
|
|
874
|
+
rows = missingBatch.flatMap((item) => {
|
|
875
|
+
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
876
|
+
const points = (0, import_indicators.mergeCoinalyzeMetrics)({
|
|
877
|
+
symbol: item.symbol,
|
|
878
|
+
oiRaw: oiMap.get(marketSymbol) ?? [],
|
|
879
|
+
fundingRaw: fundingMap.get(marketSymbol) ?? [],
|
|
880
|
+
liqRaw: liquidationRowsByMarket.get(marketSymbol) ?? []
|
|
881
|
+
});
|
|
882
|
+
return (0, import_indicators.coinalyzePointsToRows)(points, interval, "coinalyze");
|
|
883
|
+
});
|
|
884
|
+
missingClosedSymbols = mode === "signals" ? getMissingClosedDerivativesSymbols({
|
|
885
|
+
symbols: missingBatch.map((item) => item.symbol),
|
|
886
|
+
rows,
|
|
887
|
+
expectedTimestamp: toMs
|
|
888
|
+
}) : [];
|
|
889
|
+
if (!missingClosedSymbols.length) break;
|
|
890
|
+
if (attempt < maxClosedBarAttempts) {
|
|
891
|
+
await (0, import_async.delay)(closedBarRetryDelayMs);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
if (missingClosedSymbols.length) {
|
|
895
|
+
throw new Error(
|
|
896
|
+
`Coinalyze closed ${interval} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
|
|
897
|
+
);
|
|
898
|
+
}
|
|
785
899
|
if (rows.length) {
|
|
786
900
|
await (0, import_timescale.upsertDerivatives)(rows);
|
|
787
901
|
totalRows += rows.length;
|
|
788
902
|
}
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
(rowsCountBySymbol.get(symbol) ?? 0) + 1
|
|
795
|
-
);
|
|
796
|
-
}
|
|
797
|
-
const coverageRows = missingBatch.map((item) => {
|
|
798
|
-
const normalizedSymbol = item.symbol.toUpperCase();
|
|
799
|
-
const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
|
|
800
|
-
return {
|
|
801
|
-
source: "coinalyze",
|
|
802
|
-
symbol: item.symbol,
|
|
803
|
-
interval,
|
|
804
|
-
fromMs: cursor,
|
|
805
|
-
toMs,
|
|
806
|
-
rowsCount
|
|
807
|
-
};
|
|
903
|
+
const confirmedLiquidationWindow = (0, import_indicators.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
904
|
+
interval,
|
|
905
|
+
fromMs: group.fromMs,
|
|
906
|
+
toMs,
|
|
907
|
+
nowMs: coverageNowMs
|
|
808
908
|
});
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
909
|
+
if (confirmedLiquidationWindow) {
|
|
910
|
+
const metricCoverageRows = missingBatch.map((item) => {
|
|
911
|
+
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
912
|
+
const eventRowsCount = (liquidationRowsByMarket.get(marketSymbol) ?? []).filter((point) => {
|
|
913
|
+
const timestamp = (0, import_indicators.toCoinalyzeTimestampMs)(
|
|
914
|
+
point.t ?? point.ts ?? point.time ?? point.timestamp
|
|
915
|
+
);
|
|
916
|
+
return timestamp != null && timestamp >= confirmedLiquidationWindow.fromMs && timestamp <= confirmedLiquidationWindow.toMs;
|
|
917
|
+
}).length;
|
|
918
|
+
return {
|
|
919
|
+
source: "coinalyze",
|
|
920
|
+
metric: "liquidation",
|
|
921
|
+
symbol: item.symbol,
|
|
922
|
+
interval,
|
|
923
|
+
fromMs: confirmedLiquidationWindow.fromMs,
|
|
924
|
+
toMs: confirmedLiquidationWindow.toMs,
|
|
925
|
+
eventRowsCount
|
|
926
|
+
};
|
|
927
|
+
});
|
|
928
|
+
await (0, import_timescale.applyDerivativesMetricCoverage)(metricCoverageRows);
|
|
929
|
+
for (const coverageRow of metricCoverageRows) {
|
|
930
|
+
const symbol = coverageRow.symbol.toUpperCase();
|
|
931
|
+
const ranges = liquidationCoverageRangesBySymbol.get(symbol) ?? [];
|
|
932
|
+
ranges.push({
|
|
933
|
+
fromMs: coverageRow.fromMs,
|
|
934
|
+
toMs: coverageRow.toMs
|
|
935
|
+
});
|
|
936
|
+
liquidationCoverageRangesBySymbol.set(symbol, ranges);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
if (mode === "backtest") {
|
|
940
|
+
const rowsCountBySymbol = /* @__PURE__ */ new Map();
|
|
941
|
+
for (const row of rows) {
|
|
942
|
+
const symbol = row.symbol.toUpperCase();
|
|
943
|
+
rowsCountBySymbol.set(
|
|
818
944
|
symbol,
|
|
945
|
+
(rowsCountBySymbol.get(symbol) ?? 0) + 1
|
|
946
|
+
);
|
|
947
|
+
}
|
|
948
|
+
const coverageRows = missingBatch.map((item) => {
|
|
949
|
+
const normalizedSymbol = item.symbol.toUpperCase();
|
|
950
|
+
const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
|
|
951
|
+
return {
|
|
952
|
+
source: "coinalyze",
|
|
953
|
+
symbol: item.symbol,
|
|
819
954
|
interval,
|
|
820
955
|
fromMs: cursor,
|
|
821
|
-
toMs
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
956
|
+
toMs,
|
|
957
|
+
rowsCount
|
|
958
|
+
};
|
|
959
|
+
});
|
|
960
|
+
await (0, import_timescale.upsertDerivativesBackfillCoverage)(coverageRows);
|
|
961
|
+
for (const coverageRow of coverageRows) {
|
|
962
|
+
const symbol = coverageRow.symbol.toUpperCase();
|
|
963
|
+
edgesBySymbol.set(
|
|
964
|
+
symbol,
|
|
965
|
+
extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
|
|
966
|
+
);
|
|
967
|
+
coverageKeys.add(
|
|
968
|
+
coverageKey({
|
|
969
|
+
symbol,
|
|
970
|
+
interval,
|
|
971
|
+
fromMs: cursor,
|
|
972
|
+
toMs
|
|
973
|
+
})
|
|
974
|
+
);
|
|
975
|
+
const coverageRanges = coverageRangesBySymbol.get(symbol) ?? [];
|
|
976
|
+
coverageRanges.push({ fromMs: cursor, toMs });
|
|
977
|
+
coverageRangesBySymbol.set(symbol, coverageRanges);
|
|
978
|
+
}
|
|
827
979
|
}
|
|
828
980
|
}
|
|
829
981
|
}
|
|
@@ -883,6 +1035,7 @@ var backfillDerivativesContextForSignals = async (params) => backfillDerivatives
|
|
|
883
1035
|
backfillDerivativesContextForBacktest,
|
|
884
1036
|
backfillDerivativesContextForSignals,
|
|
885
1037
|
formatCoinalyzeRequestError,
|
|
1038
|
+
getMissingClosedDerivativesSymbols,
|
|
886
1039
|
groupDerivativesContextMissingFetchRanges,
|
|
887
1040
|
hasDerivativesContextCoverageRange,
|
|
888
1041
|
isBacktestDerivativesContextEnabled,
|
|
@@ -890,11 +1043,13 @@ var backfillDerivativesContextForSignals = async (params) => backfillDerivatives
|
|
|
890
1043
|
isSignalsDerivativesContextEnabled,
|
|
891
1044
|
resolveDerivativesContextBackfillSymbols,
|
|
892
1045
|
resolveDerivativesContextBackfillWindow,
|
|
1046
|
+
resolveDerivativesContextFetchFromMs,
|
|
893
1047
|
resolveDerivativesContextIntervalBackfillWindow,
|
|
894
1048
|
resolveDerivativesContextIntervals,
|
|
895
1049
|
resolveDerivativesContextLookbackMs,
|
|
896
1050
|
resolveDerivativesContextMissingCoverageFetchFromMs,
|
|
897
1051
|
resolveDerivativesContextMissingFetchFromMs,
|
|
1052
|
+
resolveDerivativesContextRequiredFetchFromMs,
|
|
898
1053
|
shouldBackfillDerivativesContextForBacktest,
|
|
899
1054
|
shouldBackfillDerivativesContextForSignals
|
|
900
1055
|
});
|