@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.
@@ -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 DEFAULT_INTERVALS = ["15m", "1h"];
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
- const intervals = (0, import_indicators.normalizeDerivativesIntervals)(
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: Math.floor(params.toMs / intervalMs) * intervalMs,
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 coverageRows = await (0, import_timescale.getDerivativesBackfillCoverage)({
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
- return hasDerivativesWindowCoverage({
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 coverageFromMs = resolveDerivativesContextMissingCoverageFetchFromMs({
716
- ranges: coverageRangesBySymbol.get(normalizedSymbol),
717
- fromMs: cursor,
718
- toMs,
719
- intervalMs
720
- });
721
- if (coverageFromMs == null) {
722
- return null;
723
- }
724
- const edges = edgesBySymbol.get(normalizedSymbol);
725
- const edgesFromMs = resolveDerivativesContextMissingFetchFromMs({
726
- edges,
727
- fromMs: cursor,
728
- toMs,
729
- intervalMs
730
- });
731
- if (edgesFromMs == null) {
732
- return null;
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 oiMap = await fetchMetricBatch({
749
- endpoint: oiPath,
750
- metric: "oi",
751
- marketSymbols,
752
- apiKey,
753
- interval,
754
- fromMs: group.fromMs,
755
- toMs
756
- });
757
- const fundingMap = await fetchMetricBatch({
758
- endpoint: fundingPath,
759
- metric: "funding",
760
- marketSymbols,
761
- apiKey,
762
- interval,
763
- fromMs: group.fromMs,
764
- toMs
765
- });
766
- const liqMap = await fetchMetricBatch({
767
- endpoint: liqPath,
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
- return (0, import_indicators.coinalyzePointsToRows)(points, interval, "coinalyze");
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 rowsCountBySymbol = /* @__PURE__ */ new Map();
790
- for (const row of rows) {
791
- const symbol = row.symbol.toUpperCase();
792
- rowsCountBySymbol.set(
793
- symbol,
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
- await (0, import_timescale.upsertDerivativesBackfillCoverage)(coverageRows);
810
- for (const coverageRow of coverageRows) {
811
- const symbol = coverageRow.symbol.toUpperCase();
812
- edgesBySymbol.set(
813
- symbol,
814
- extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
815
- );
816
- coverageKeys.add(
817
- coverageKey({
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
- const coverageRanges = coverageRangesBySymbol.get(symbol) ?? [];
825
- coverageRanges.push({ fromMs: cursor, toMs });
826
- coverageRangesBySymbol.set(symbol, coverageRanges);
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
  });