@tradejs/infra 2.0.1 → 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.
@@ -50,6 +50,34 @@ declare function upsertDerivativesBackfillCoverage(rows: Array<{
50
50
  toMs: number;
51
51
  rowsCount: number;
52
52
  }>): Promise<void>;
53
+ type DerivativesMetricCoverageMetric = 'liquidation';
54
+ declare function getDerivativesMetricCoverage(params: {
55
+ source: string;
56
+ metric: DerivativesMetricCoverageMetric;
57
+ symbols: string[];
58
+ interval: DerivativesInterval;
59
+ fromMs: number;
60
+ toMs: number;
61
+ }): Promise<{
62
+ symbol: string;
63
+ interval: DerivativesInterval;
64
+ fromMs: number;
65
+ toMs: number;
66
+ eventRowsCount: number;
67
+ zeroRowsCount: number;
68
+ }[]>;
69
+ declare function applyDerivativesMetricCoverage(rows: Array<{
70
+ source: string;
71
+ metric: DerivativesMetricCoverageMetric;
72
+ symbol: string;
73
+ interval: DerivativesInterval;
74
+ fromMs: number;
75
+ toMs: number;
76
+ eventRowsCount: number;
77
+ }>): Promise<{
78
+ symbol: string;
79
+ zeroRowsCount: number;
80
+ }[]>;
53
81
  declare function getDerivativesWindow(params: {
54
82
  symbol: string;
55
83
  intervals: DerivativesInterval[];
@@ -271,4 +299,4 @@ declare function findContinuityGap(provider: string, symbol: string, interval: n
271
299
  diffSeconds: number;
272
300
  } | null>;
273
301
 
274
- export { type CandleRow, type DeprecatedMarketContextCleanupItem, type MarketFeatureAsOf, cleanupDeprecatedMarketContext, closeTimescalePool, deleteCandles, findContinuityGap, getCandlesRange, getDataEdges, getDataEdgesForSymbols, getDerivativesBackfillCoverage, getDerivativesDataEdgesForSymbols, getDerivativesRangeForSymbols, getDerivativesSummary, getDerivativesWindow, getLatestMarketBreadth, getLatestMarketCmcExchangeLiquidityContext, getLatestMarketCmcFearGreedContext, getLatestMarketCmcIndexContexts, getLatestMarketGlobalContext, getLatestMarketReferenceAssetContexts, getLatestMarketTradeFlow, getMarketBreadthCoverage, getMarketCmcExchangeLiquidityContextCoverage, getMarketCmcFearGreedContextCoverage, getMarketCmcIndexContextCoverage, getMarketContextBackfillCoverage, getMarketGlobalContextCoverage, getMarketReferenceAssetContextCoverage, getMarketTradeFlowCoverage, getSpreadRangeForSymbols, getSpreadSummary, toRows, upsertCandles, upsertDerivatives, upsertDerivativesBackfillCoverage, upsertMarketBreadthRows, upsertMarketCmcExchangeLiquidityContextRows, upsertMarketCmcFearGreedContextRows, upsertMarketCmcIndexContextRows, upsertMarketContextBackfillCoverage, upsertMarketGlobalContextRows, upsertMarketReferenceAssetContextRows, upsertMarketTradeFlowRows, upsertSpreadRows, waitForDbReady };
302
+ export { type CandleRow, type DeprecatedMarketContextCleanupItem, type DerivativesMetricCoverageMetric, type MarketFeatureAsOf, applyDerivativesMetricCoverage, cleanupDeprecatedMarketContext, closeTimescalePool, deleteCandles, findContinuityGap, getCandlesRange, getDataEdges, getDataEdgesForSymbols, getDerivativesBackfillCoverage, getDerivativesDataEdgesForSymbols, getDerivativesMetricCoverage, getDerivativesRangeForSymbols, getDerivativesSummary, getDerivativesWindow, getLatestMarketBreadth, getLatestMarketCmcExchangeLiquidityContext, getLatestMarketCmcFearGreedContext, getLatestMarketCmcIndexContexts, getLatestMarketGlobalContext, getLatestMarketReferenceAssetContexts, getLatestMarketTradeFlow, getMarketBreadthCoverage, getMarketCmcExchangeLiquidityContextCoverage, getMarketCmcFearGreedContextCoverage, getMarketCmcIndexContextCoverage, getMarketContextBackfillCoverage, getMarketGlobalContextCoverage, getMarketReferenceAssetContextCoverage, getMarketTradeFlowCoverage, getSpreadRangeForSymbols, getSpreadSummary, toRows, upsertCandles, upsertDerivatives, upsertDerivativesBackfillCoverage, upsertMarketBreadthRows, upsertMarketCmcExchangeLiquidityContextRows, upsertMarketCmcFearGreedContextRows, upsertMarketCmcIndexContextRows, upsertMarketContextBackfillCoverage, upsertMarketGlobalContextRows, upsertMarketReferenceAssetContextRows, upsertMarketTradeFlowRows, upsertSpreadRows, waitForDbReady };
@@ -50,6 +50,34 @@ declare function upsertDerivativesBackfillCoverage(rows: Array<{
50
50
  toMs: number;
51
51
  rowsCount: number;
52
52
  }>): Promise<void>;
53
+ type DerivativesMetricCoverageMetric = 'liquidation';
54
+ declare function getDerivativesMetricCoverage(params: {
55
+ source: string;
56
+ metric: DerivativesMetricCoverageMetric;
57
+ symbols: string[];
58
+ interval: DerivativesInterval;
59
+ fromMs: number;
60
+ toMs: number;
61
+ }): Promise<{
62
+ symbol: string;
63
+ interval: DerivativesInterval;
64
+ fromMs: number;
65
+ toMs: number;
66
+ eventRowsCount: number;
67
+ zeroRowsCount: number;
68
+ }[]>;
69
+ declare function applyDerivativesMetricCoverage(rows: Array<{
70
+ source: string;
71
+ metric: DerivativesMetricCoverageMetric;
72
+ symbol: string;
73
+ interval: DerivativesInterval;
74
+ fromMs: number;
75
+ toMs: number;
76
+ eventRowsCount: number;
77
+ }>): Promise<{
78
+ symbol: string;
79
+ zeroRowsCount: number;
80
+ }[]>;
53
81
  declare function getDerivativesWindow(params: {
54
82
  symbol: string;
55
83
  intervals: DerivativesInterval[];
@@ -271,4 +299,4 @@ declare function findContinuityGap(provider: string, symbol: string, interval: n
271
299
  diffSeconds: number;
272
300
  } | null>;
273
301
 
274
- export { type CandleRow, type DeprecatedMarketContextCleanupItem, type MarketFeatureAsOf, cleanupDeprecatedMarketContext, closeTimescalePool, deleteCandles, findContinuityGap, getCandlesRange, getDataEdges, getDataEdgesForSymbols, getDerivativesBackfillCoverage, getDerivativesDataEdgesForSymbols, getDerivativesRangeForSymbols, getDerivativesSummary, getDerivativesWindow, getLatestMarketBreadth, getLatestMarketCmcExchangeLiquidityContext, getLatestMarketCmcFearGreedContext, getLatestMarketCmcIndexContexts, getLatestMarketGlobalContext, getLatestMarketReferenceAssetContexts, getLatestMarketTradeFlow, getMarketBreadthCoverage, getMarketCmcExchangeLiquidityContextCoverage, getMarketCmcFearGreedContextCoverage, getMarketCmcIndexContextCoverage, getMarketContextBackfillCoverage, getMarketGlobalContextCoverage, getMarketReferenceAssetContextCoverage, getMarketTradeFlowCoverage, getSpreadRangeForSymbols, getSpreadSummary, toRows, upsertCandles, upsertDerivatives, upsertDerivativesBackfillCoverage, upsertMarketBreadthRows, upsertMarketCmcExchangeLiquidityContextRows, upsertMarketCmcFearGreedContextRows, upsertMarketCmcIndexContextRows, upsertMarketContextBackfillCoverage, upsertMarketGlobalContextRows, upsertMarketReferenceAssetContextRows, upsertMarketTradeFlowRows, upsertSpreadRows, waitForDbReady };
302
+ export { type CandleRow, type DeprecatedMarketContextCleanupItem, type DerivativesMetricCoverageMetric, type MarketFeatureAsOf, applyDerivativesMetricCoverage, cleanupDeprecatedMarketContext, closeTimescalePool, deleteCandles, findContinuityGap, getCandlesRange, getDataEdges, getDataEdgesForSymbols, getDerivativesBackfillCoverage, getDerivativesDataEdgesForSymbols, getDerivativesMetricCoverage, getDerivativesRangeForSymbols, getDerivativesSummary, getDerivativesWindow, getLatestMarketBreadth, getLatestMarketCmcExchangeLiquidityContext, getLatestMarketCmcFearGreedContext, getLatestMarketCmcIndexContexts, getLatestMarketGlobalContext, getLatestMarketReferenceAssetContexts, getLatestMarketTradeFlow, getMarketBreadthCoverage, getMarketCmcExchangeLiquidityContextCoverage, getMarketCmcFearGreedContextCoverage, getMarketCmcIndexContextCoverage, getMarketContextBackfillCoverage, getMarketGlobalContextCoverage, getMarketReferenceAssetContextCoverage, getMarketTradeFlowCoverage, getSpreadRangeForSymbols, getSpreadSummary, toRows, upsertCandles, upsertDerivatives, upsertDerivativesBackfillCoverage, upsertMarketBreadthRows, upsertMarketCmcExchangeLiquidityContextRows, upsertMarketCmcFearGreedContextRows, upsertMarketCmcIndexContextRows, upsertMarketContextBackfillCoverage, upsertMarketGlobalContextRows, upsertMarketReferenceAssetContextRows, upsertMarketTradeFlowRows, upsertSpreadRows, waitForDbReady };
package/dist/timescale.js CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/timescale.ts
21
21
  var timescale_exports = {};
22
22
  __export(timescale_exports, {
23
+ applyDerivativesMetricCoverage: () => applyDerivativesMetricCoverage,
23
24
  cleanupDeprecatedMarketContext: () => cleanupDeprecatedMarketContext,
24
25
  closeTimescalePool: () => closeTimescalePool,
25
26
  deleteCandles: () => deleteCandles,
@@ -29,6 +30,7 @@ __export(timescale_exports, {
29
30
  getDataEdgesForSymbols: () => getDataEdgesForSymbols,
30
31
  getDerivativesBackfillCoverage: () => getDerivativesBackfillCoverage,
31
32
  getDerivativesDataEdgesForSymbols: () => getDerivativesDataEdgesForSymbols,
33
+ getDerivativesMetricCoverage: () => getDerivativesMetricCoverage,
32
34
  getDerivativesRangeForSymbols: () => getDerivativesRangeForSymbols,
33
35
  getDerivativesSummary: () => getDerivativesSummary,
34
36
  getDerivativesWindow: () => getDerivativesWindow,
@@ -339,6 +341,31 @@ var ensureDerivativesSchema = async () => {
339
341
  CREATE INDEX IF NOT EXISTS derivatives_backfill_coverage_lookup_idx
340
342
  ON derivatives_backfill_coverage (source, symbol, interval, from_ts, to_ts)
341
343
  `);
344
+ await pool.query(`
345
+ CREATE TABLE IF NOT EXISTS derivatives_metric_coverage (
346
+ source text NOT NULL,
347
+ metric text NOT NULL,
348
+ symbol text NOT NULL,
349
+ interval text NOT NULL,
350
+ from_ts timestamptz NOT NULL,
351
+ to_ts timestamptz NOT NULL,
352
+ event_rows_count integer NOT NULL DEFAULT 0,
353
+ zero_rows_count integer NOT NULL DEFAULT 0,
354
+ checked_at timestamptz NOT NULL DEFAULT now(),
355
+ PRIMARY KEY (source, metric, symbol, interval, from_ts, to_ts)
356
+ )
357
+ `);
358
+ await pool.query(`
359
+ CREATE INDEX IF NOT EXISTS derivatives_metric_coverage_lookup_idx
360
+ ON derivatives_metric_coverage (
361
+ source,
362
+ metric,
363
+ symbol,
364
+ interval,
365
+ from_ts,
366
+ to_ts
367
+ )
368
+ `);
342
369
  derivativesSchemaReady = true;
343
370
  }
344
371
  ).finally(() => {
@@ -849,6 +876,147 @@ async function upsertDerivativesBackfillCoverage(rows) {
849
876
  flat
850
877
  );
851
878
  }
879
+ async function getDerivativesMetricCoverage(params) {
880
+ const normalizedSource = String(params.source || "").trim().toLowerCase();
881
+ const normalizedSymbols = [
882
+ ...new Set(
883
+ params.symbols.map(
884
+ (symbol) => String(symbol || "").trim().toUpperCase()
885
+ ).filter(Boolean)
886
+ )
887
+ ];
888
+ if (!normalizedSource || !normalizedSymbols.length) {
889
+ return [];
890
+ }
891
+ await ensureDerivativesSchema();
892
+ const pool = getPool();
893
+ const res = await pool.query(
894
+ `
895
+ SELECT
896
+ symbol,
897
+ interval,
898
+ extract(epoch from from_ts)*1000 AS from_ms,
899
+ extract(epoch from to_ts)*1000 AS to_ms,
900
+ event_rows_count,
901
+ zero_rows_count
902
+ FROM derivatives_metric_coverage
903
+ WHERE source = $1
904
+ AND metric = $2
905
+ AND symbol = ANY($3)
906
+ AND interval = $4
907
+ AND from_ts <= to_timestamp($6/1000.0)
908
+ AND to_ts >= to_timestamp($5/1000.0)
909
+ `,
910
+ [
911
+ normalizedSource,
912
+ params.metric,
913
+ normalizedSymbols,
914
+ params.interval,
915
+ params.fromMs,
916
+ params.toMs
917
+ ]
918
+ );
919
+ return res.rows.map((row) => ({
920
+ symbol: String(row.symbol).toUpperCase(),
921
+ interval: row.interval,
922
+ fromMs: Number(row.from_ms),
923
+ toMs: Number(row.to_ms),
924
+ eventRowsCount: Number(row.event_rows_count ?? 0),
925
+ zeroRowsCount: Number(row.zero_rows_count ?? 0)
926
+ }));
927
+ }
928
+ async function applyDerivativesMetricCoverage(rows) {
929
+ if (!rows.length)
930
+ return [];
931
+ await ensureDerivativesSchema();
932
+ const pool = getPool();
933
+ const client = await pool.connect();
934
+ const results = [];
935
+ try {
936
+ await client.query("BEGIN");
937
+ for (const row of rows) {
938
+ const source = String(row.source || "").trim().toLowerCase();
939
+ const symbol = String(row.symbol || "").trim().toUpperCase();
940
+ const fromMs = Math.trunc(row.fromMs);
941
+ const toMs = Math.trunc(row.toMs);
942
+ if (!source || !symbol || fromMs > toMs) continue;
943
+ await client.query(
944
+ `
945
+ UPDATE derivatives_market
946
+ SET
947
+ liq_long = 0,
948
+ liq_short = 0,
949
+ liq_total = 0,
950
+ ingested_at = now()
951
+ WHERE symbol = $1
952
+ AND interval = $2
953
+ AND ts >= to_timestamp($3/1000.0)
954
+ AND ts <= to_timestamp($4/1000.0)
955
+ AND liq_long IS NULL
956
+ AND liq_short IS NULL
957
+ AND liq_total IS NULL
958
+ `,
959
+ [symbol, row.interval, fromMs, toMs]
960
+ );
961
+ const zeroCountResult = await client.query(
962
+ `
963
+ SELECT COUNT(*)::integer AS count
964
+ FROM derivatives_market
965
+ WHERE symbol = $1
966
+ AND interval = $2
967
+ AND ts >= to_timestamp($3/1000.0)
968
+ AND ts <= to_timestamp($4/1000.0)
969
+ AND liq_long = 0
970
+ AND liq_short = 0
971
+ AND liq_total = 0
972
+ `,
973
+ [symbol, row.interval, fromMs, toMs]
974
+ );
975
+ const zeroRowsCount = Math.max(
976
+ 0,
977
+ Number(zeroCountResult.rows[0]?.count ?? 0)
978
+ );
979
+ await client.query(
980
+ `
981
+ INSERT INTO derivatives_metric_coverage (
982
+ source,
983
+ metric,
984
+ symbol,
985
+ interval,
986
+ from_ts,
987
+ to_ts,
988
+ event_rows_count,
989
+ zero_rows_count
990
+ )
991
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
992
+ ON CONFLICT (source, metric, symbol, interval, from_ts, to_ts)
993
+ DO UPDATE SET
994
+ event_rows_count = EXCLUDED.event_rows_count,
995
+ zero_rows_count = EXCLUDED.zero_rows_count,
996
+ checked_at = now()
997
+ `,
998
+ [
999
+ source,
1000
+ row.metric,
1001
+ symbol,
1002
+ row.interval,
1003
+ new Date(fromMs),
1004
+ new Date(toMs),
1005
+ Math.max(0, Math.trunc(row.eventRowsCount)),
1006
+ zeroRowsCount
1007
+ ]
1008
+ );
1009
+ results.push({ symbol, zeroRowsCount });
1010
+ }
1011
+ await client.query("COMMIT");
1012
+ return results;
1013
+ } catch (error) {
1014
+ await client.query("ROLLBACK");
1015
+ throw error;
1016
+ } finally {
1017
+ client.release();
1018
+ }
1019
+ }
852
1020
  async function getDerivativesWindow(params) {
853
1021
  const { symbol, intervals, endMs, lookbackMs } = params;
854
1022
  const normalizedSymbol = String(symbol || "").trim().toUpperCase();
@@ -2502,6 +2670,7 @@ async function findContinuityGap(provider, symbol, interval) {
2502
2670
  }
2503
2671
  // Annotate the CommonJS export names for ESM import in node:
2504
2672
  0 && (module.exports = {
2673
+ applyDerivativesMetricCoverage,
2505
2674
  cleanupDeprecatedMarketContext,
2506
2675
  closeTimescalePool,
2507
2676
  deleteCandles,
@@ -2511,6 +2680,7 @@ async function findContinuityGap(provider, symbol, interval) {
2511
2680
  getDataEdgesForSymbols,
2512
2681
  getDerivativesBackfillCoverage,
2513
2682
  getDerivativesDataEdgesForSymbols,
2683
+ getDerivativesMetricCoverage,
2514
2684
  getDerivativesRangeForSymbols,
2515
2685
  getDerivativesSummary,
2516
2686
  getDerivativesWindow,
@@ -273,6 +273,31 @@ var ensureDerivativesSchema = async () => {
273
273
  CREATE INDEX IF NOT EXISTS derivatives_backfill_coverage_lookup_idx
274
274
  ON derivatives_backfill_coverage (source, symbol, interval, from_ts, to_ts)
275
275
  `);
276
+ await pool.query(`
277
+ CREATE TABLE IF NOT EXISTS derivatives_metric_coverage (
278
+ source text NOT NULL,
279
+ metric text NOT NULL,
280
+ symbol text NOT NULL,
281
+ interval text NOT NULL,
282
+ from_ts timestamptz NOT NULL,
283
+ to_ts timestamptz NOT NULL,
284
+ event_rows_count integer NOT NULL DEFAULT 0,
285
+ zero_rows_count integer NOT NULL DEFAULT 0,
286
+ checked_at timestamptz NOT NULL DEFAULT now(),
287
+ PRIMARY KEY (source, metric, symbol, interval, from_ts, to_ts)
288
+ )
289
+ `);
290
+ await pool.query(`
291
+ CREATE INDEX IF NOT EXISTS derivatives_metric_coverage_lookup_idx
292
+ ON derivatives_metric_coverage (
293
+ source,
294
+ metric,
295
+ symbol,
296
+ interval,
297
+ from_ts,
298
+ to_ts
299
+ )
300
+ `);
276
301
  derivativesSchemaReady = true;
277
302
  }
278
303
  ).finally(() => {
@@ -783,6 +808,147 @@ async function upsertDerivativesBackfillCoverage(rows) {
783
808
  flat
784
809
  );
785
810
  }
811
+ async function getDerivativesMetricCoverage(params) {
812
+ const normalizedSource = String(params.source || "").trim().toLowerCase();
813
+ const normalizedSymbols = [
814
+ ...new Set(
815
+ params.symbols.map(
816
+ (symbol) => String(symbol || "").trim().toUpperCase()
817
+ ).filter(Boolean)
818
+ )
819
+ ];
820
+ if (!normalizedSource || !normalizedSymbols.length) {
821
+ return [];
822
+ }
823
+ await ensureDerivativesSchema();
824
+ const pool = getPool();
825
+ const res = await pool.query(
826
+ `
827
+ SELECT
828
+ symbol,
829
+ interval,
830
+ extract(epoch from from_ts)*1000 AS from_ms,
831
+ extract(epoch from to_ts)*1000 AS to_ms,
832
+ event_rows_count,
833
+ zero_rows_count
834
+ FROM derivatives_metric_coverage
835
+ WHERE source = $1
836
+ AND metric = $2
837
+ AND symbol = ANY($3)
838
+ AND interval = $4
839
+ AND from_ts <= to_timestamp($6/1000.0)
840
+ AND to_ts >= to_timestamp($5/1000.0)
841
+ `,
842
+ [
843
+ normalizedSource,
844
+ params.metric,
845
+ normalizedSymbols,
846
+ params.interval,
847
+ params.fromMs,
848
+ params.toMs
849
+ ]
850
+ );
851
+ return res.rows.map((row) => ({
852
+ symbol: String(row.symbol).toUpperCase(),
853
+ interval: row.interval,
854
+ fromMs: Number(row.from_ms),
855
+ toMs: Number(row.to_ms),
856
+ eventRowsCount: Number(row.event_rows_count ?? 0),
857
+ zeroRowsCount: Number(row.zero_rows_count ?? 0)
858
+ }));
859
+ }
860
+ async function applyDerivativesMetricCoverage(rows) {
861
+ if (!rows.length)
862
+ return [];
863
+ await ensureDerivativesSchema();
864
+ const pool = getPool();
865
+ const client = await pool.connect();
866
+ const results = [];
867
+ try {
868
+ await client.query("BEGIN");
869
+ for (const row of rows) {
870
+ const source = String(row.source || "").trim().toLowerCase();
871
+ const symbol = String(row.symbol || "").trim().toUpperCase();
872
+ const fromMs = Math.trunc(row.fromMs);
873
+ const toMs = Math.trunc(row.toMs);
874
+ if (!source || !symbol || fromMs > toMs) continue;
875
+ await client.query(
876
+ `
877
+ UPDATE derivatives_market
878
+ SET
879
+ liq_long = 0,
880
+ liq_short = 0,
881
+ liq_total = 0,
882
+ ingested_at = now()
883
+ WHERE symbol = $1
884
+ AND interval = $2
885
+ AND ts >= to_timestamp($3/1000.0)
886
+ AND ts <= to_timestamp($4/1000.0)
887
+ AND liq_long IS NULL
888
+ AND liq_short IS NULL
889
+ AND liq_total IS NULL
890
+ `,
891
+ [symbol, row.interval, fromMs, toMs]
892
+ );
893
+ const zeroCountResult = await client.query(
894
+ `
895
+ SELECT COUNT(*)::integer AS count
896
+ FROM derivatives_market
897
+ WHERE symbol = $1
898
+ AND interval = $2
899
+ AND ts >= to_timestamp($3/1000.0)
900
+ AND ts <= to_timestamp($4/1000.0)
901
+ AND liq_long = 0
902
+ AND liq_short = 0
903
+ AND liq_total = 0
904
+ `,
905
+ [symbol, row.interval, fromMs, toMs]
906
+ );
907
+ const zeroRowsCount = Math.max(
908
+ 0,
909
+ Number(zeroCountResult.rows[0]?.count ?? 0)
910
+ );
911
+ await client.query(
912
+ `
913
+ INSERT INTO derivatives_metric_coverage (
914
+ source,
915
+ metric,
916
+ symbol,
917
+ interval,
918
+ from_ts,
919
+ to_ts,
920
+ event_rows_count,
921
+ zero_rows_count
922
+ )
923
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
924
+ ON CONFLICT (source, metric, symbol, interval, from_ts, to_ts)
925
+ DO UPDATE SET
926
+ event_rows_count = EXCLUDED.event_rows_count,
927
+ zero_rows_count = EXCLUDED.zero_rows_count,
928
+ checked_at = now()
929
+ `,
930
+ [
931
+ source,
932
+ row.metric,
933
+ symbol,
934
+ row.interval,
935
+ new Date(fromMs),
936
+ new Date(toMs),
937
+ Math.max(0, Math.trunc(row.eventRowsCount)),
938
+ zeroRowsCount
939
+ ]
940
+ );
941
+ results.push({ symbol, zeroRowsCount });
942
+ }
943
+ await client.query("COMMIT");
944
+ return results;
945
+ } catch (error) {
946
+ await client.query("ROLLBACK");
947
+ throw error;
948
+ } finally {
949
+ client.release();
950
+ }
951
+ }
786
952
  async function getDerivativesWindow(params) {
787
953
  const { symbol, intervals, endMs, lookbackMs } = params;
788
954
  const normalizedSymbol = String(symbol || "").trim().toUpperCase();
@@ -2435,6 +2601,7 @@ async function findContinuityGap(provider, symbol, interval) {
2435
2601
  };
2436
2602
  }
2437
2603
  export {
2604
+ applyDerivativesMetricCoverage,
2438
2605
  cleanupDeprecatedMarketContext,
2439
2606
  closeTimescalePool,
2440
2607
  deleteCandles,
@@ -2444,6 +2611,7 @@ export {
2444
2611
  getDataEdgesForSymbols,
2445
2612
  getDerivativesBackfillCoverage,
2446
2613
  getDerivativesDataEdgesForSymbols,
2614
+ getDerivativesMetricCoverage,
2447
2615
  getDerivativesRangeForSymbols,
2448
2616
  getDerivativesSummary,
2449
2617
  getDerivativesWindow,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/infra",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "MIT-licensed server infrastructure adapters for TradeJS: Redis, Timescale, ML, logging, and IO.",
5
5
  "keywords": [
6
6
  "tradejs",
@@ -93,7 +93,7 @@
93
93
  "dependencies": {
94
94
  "@grpc/grpc-js": "^1.10.7",
95
95
  "@grpc/proto-loader": "^0.8.0",
96
- "@tradejs/types": "^2.0.1",
96
+ "@tradejs/types": "^2.0.2",
97
97
  "chalk": "4.1.2",
98
98
  "ioredis": "5.8.0",
99
99
  "pg": "8.16.3",