@tradejs/infra 2.0.15 → 2.0.16
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/{chunk-EFCQ7NGN.mjs → chunk-6ZKAUA4Q.mjs} +2 -0
- package/dist/redis.d.mts +2 -0
- package/dist/redis.d.ts +2 -0
- package/dist/redis.js +2 -0
- package/dist/redis.mjs +1 -1
- package/dist/timescale.d.mts +39 -1
- package/dist/timescale.d.ts +39 -1
- package/dist/timescale.js +196 -55
- package/dist/timescale.mjs +190 -55
- package/dist/tradingAccounts.js +2 -0
- package/dist/tradingAccounts.mjs +1 -1
- package/dist/userSettings.js +2 -0
- package/dist/userSettings.mjs +1 -1
- package/package.json +2 -2
|
@@ -507,6 +507,8 @@ var redisKeys = {
|
|
|
507
507
|
runtimeTrade: (userName, orderId) => `users:${userName}:runtime:trade-records:${orderId}`,
|
|
508
508
|
runtimeTradeBuckets: (userName) => `users:${userName}:runtime:trade-records:days:`,
|
|
509
509
|
runtimeTradeBucket: (userName, dayKey) => `users:${userName}:runtime:trade-records:days:${dayKey}`,
|
|
510
|
+
runtimeClosedTradeBuckets: (userName) => `users:${userName}:runtime:closed-trade-records:days:`,
|
|
511
|
+
runtimeClosedTradeBucket: (userName, dayKey) => `users:${userName}:runtime:closed-trade-records:days:${dayKey}`,
|
|
510
512
|
runtimeActiveTrades: (userName) => `users:${userName}:runtime:active-trades:`,
|
|
511
513
|
runtimeActiveTrade: (userName, symbol, scopeId) => scopeId ? `users:${userName}:runtime:active-trades:${scopeId}:${symbol}` : `users:${userName}:runtime:active-trades:${symbol}`,
|
|
512
514
|
aiChatHistory: (userName, symbolKey) => `users:${userName}:ai:chats:${symbolKey}`,
|
package/dist/redis.d.mts
CHANGED
|
@@ -75,6 +75,8 @@ declare const redisKeys: {
|
|
|
75
75
|
runtimeTrade: (userName: string, orderId: string) => string;
|
|
76
76
|
runtimeTradeBuckets: (userName: string) => string;
|
|
77
77
|
runtimeTradeBucket: (userName: string, dayKey: string) => string;
|
|
78
|
+
runtimeClosedTradeBuckets: (userName: string) => string;
|
|
79
|
+
runtimeClosedTradeBucket: (userName: string, dayKey: string) => string;
|
|
78
80
|
runtimeActiveTrades: (userName: string) => string;
|
|
79
81
|
runtimeActiveTrade: (userName: string, symbol: string, scopeId?: string) => string;
|
|
80
82
|
aiChatHistory: (userName: string, symbolKey: string) => string;
|
package/dist/redis.d.ts
CHANGED
|
@@ -75,6 +75,8 @@ declare const redisKeys: {
|
|
|
75
75
|
runtimeTrade: (userName: string, orderId: string) => string;
|
|
76
76
|
runtimeTradeBuckets: (userName: string) => string;
|
|
77
77
|
runtimeTradeBucket: (userName: string, dayKey: string) => string;
|
|
78
|
+
runtimeClosedTradeBuckets: (userName: string) => string;
|
|
79
|
+
runtimeClosedTradeBucket: (userName: string, dayKey: string) => string;
|
|
78
80
|
runtimeActiveTrades: (userName: string) => string;
|
|
79
81
|
runtimeActiveTrade: (userName: string, symbol: string, scopeId?: string) => string;
|
|
80
82
|
aiChatHistory: (userName: string, symbolKey: string) => string;
|
package/dist/redis.js
CHANGED
|
@@ -557,6 +557,8 @@ var redisKeys = {
|
|
|
557
557
|
runtimeTrade: (userName, orderId) => `users:${userName}:runtime:trade-records:${orderId}`,
|
|
558
558
|
runtimeTradeBuckets: (userName) => `users:${userName}:runtime:trade-records:days:`,
|
|
559
559
|
runtimeTradeBucket: (userName, dayKey) => `users:${userName}:runtime:trade-records:days:${dayKey}`,
|
|
560
|
+
runtimeClosedTradeBuckets: (userName) => `users:${userName}:runtime:closed-trade-records:days:`,
|
|
561
|
+
runtimeClosedTradeBucket: (userName, dayKey) => `users:${userName}:runtime:closed-trade-records:days:${dayKey}`,
|
|
560
562
|
runtimeActiveTrades: (userName) => `users:${userName}:runtime:active-trades:`,
|
|
561
563
|
runtimeActiveTrade: (userName, symbol, scopeId) => scopeId ? `users:${userName}:runtime:active-trades:${scopeId}:${symbol}` : `users:${userName}:runtime:active-trades:${symbol}`,
|
|
562
564
|
aiChatHistory: (userName, symbolKey) => `users:${userName}:ai:chats:${symbolKey}`,
|
package/dist/redis.mjs
CHANGED
package/dist/timescale.d.mts
CHANGED
|
@@ -20,9 +20,25 @@ type CandleRow = {
|
|
|
20
20
|
takerSellBaseVolume?: number | null;
|
|
21
21
|
takerSellQuoteVolume?: number | null;
|
|
22
22
|
};
|
|
23
|
+
type TimescaleMarketContextSource = 'binance' | 'coinmarketcap' | 'derivatives' | 'hyperliquidWhales';
|
|
24
|
+
type TimescaleMarketContextQueryOptions = {
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
};
|
|
28
|
+
declare const configureTimescaleMarketContextSchemaMode: (mode: "ensure" | "verify") => void;
|
|
23
29
|
declare const closeTimescalePool: () => Promise<void>;
|
|
24
30
|
declare const toRows: (provider: string, symbol: string, interval: number, data: KlineChartData) => CandleRow[];
|
|
25
31
|
declare function upsertCandles(rows: CandleRow[]): Promise<void>;
|
|
32
|
+
declare const ensureDerivativesSchema: () => Promise<void>;
|
|
33
|
+
declare const ensureBinanceMarketSchema: () => Promise<void>;
|
|
34
|
+
declare const ensureHyperliquidWhaleSchema: () => Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* CoinMarketCap tables currently share the historical market-context migration
|
|
37
|
+
* with the Binance tables. Keeping a source-specific entrypoint lets process
|
|
38
|
+
* composition own schema preparation without exposing that storage detail.
|
|
39
|
+
*/
|
|
40
|
+
declare const ensureCoinMarketCapContextSchema: () => Promise<void>;
|
|
41
|
+
declare const ensureMarketContextSchemas: (sources: Iterable<TimescaleMarketContextSource>) => Promise<void>;
|
|
26
42
|
declare function upsertDerivatives(rows: DerivativesRow[]): Promise<void>;
|
|
27
43
|
declare function getDerivativesRangeForSymbols(symbols: string[], interval: DerivativesInterval, startMs: number, endMs: number): Promise<any[]>;
|
|
28
44
|
declare function getDerivativesDataEdgesForSymbols(symbols: string[], interval: DerivativesInterval): Promise<Map<string, {
|
|
@@ -83,6 +99,8 @@ declare function getDerivativesWindow(params: {
|
|
|
83
99
|
intervals: DerivativesInterval[];
|
|
84
100
|
endMs: number;
|
|
85
101
|
lookbackMs: number;
|
|
102
|
+
signal?: AbortSignal;
|
|
103
|
+
timeoutMs?: number;
|
|
86
104
|
}): Promise<Partial<Record<DerivativesInterval, DerivativesRow[]>>>;
|
|
87
105
|
declare function getDerivativesSummary(hours?: number, limit?: number, symbols?: string[]): Promise<{
|
|
88
106
|
hours: number;
|
|
@@ -153,6 +171,8 @@ declare function getLatestMarketTradeFlow(params: {
|
|
|
153
171
|
interval: MarketFeatureInterval;
|
|
154
172
|
atMs: number;
|
|
155
173
|
maxAgeMs?: number;
|
|
174
|
+
signal?: AbortSignal;
|
|
175
|
+
timeoutMs?: number;
|
|
156
176
|
}): Promise<MarketFeatureAsOf<MarketTradeFlowRow> | null>;
|
|
157
177
|
type HyperliquidWhaleWalletCoverageStatus = 'complete' | 'truncated' | 'failed';
|
|
158
178
|
declare function getHyperliquidWhaleWalletCoverage(params: {
|
|
@@ -200,6 +220,8 @@ declare function getHyperliquidWhaleCoverageSeriesRows(params: {
|
|
|
200
220
|
toMs: number;
|
|
201
221
|
universeFingerprint: string;
|
|
202
222
|
whaleRegistryFingerprint: string;
|
|
223
|
+
signal?: AbortSignal;
|
|
224
|
+
timeoutMs?: number;
|
|
203
225
|
}): Promise<HyperliquidWhaleCoverageSeriesRow[]>;
|
|
204
226
|
type HyperliquidWhaleFlowSeriesRow = {
|
|
205
227
|
ts: Date;
|
|
@@ -224,6 +246,8 @@ declare function getHyperliquidWhaleFlowSeriesRows(params: {
|
|
|
224
246
|
toMs: number;
|
|
225
247
|
universeFingerprint: string;
|
|
226
248
|
whaleRegistryFingerprint: string;
|
|
249
|
+
signal?: AbortSignal;
|
|
250
|
+
timeoutMs?: number;
|
|
227
251
|
}): Promise<HyperliquidWhaleFlowSeriesRow[]>;
|
|
228
252
|
type HyperliquidWhaleFlowAggregate = {
|
|
229
253
|
symbol: string;
|
|
@@ -265,6 +289,8 @@ declare function getHyperliquidWhaleFlowAggregate(params: {
|
|
|
265
289
|
universeFingerprint: string;
|
|
266
290
|
whaleRegistryFingerprint: string;
|
|
267
291
|
maxAgeMs?: number;
|
|
292
|
+
signal?: AbortSignal;
|
|
293
|
+
timeoutMs?: number;
|
|
268
294
|
}): Promise<HyperliquidWhaleFlowAggregate | null>;
|
|
269
295
|
declare function hasHyperliquidWhaleBackfillCoverage(params: {
|
|
270
296
|
fromMs: number;
|
|
@@ -277,11 +303,15 @@ declare function getLatestMarketBreadth(params: {
|
|
|
277
303
|
interval: MarketFeatureInterval;
|
|
278
304
|
atMs: number;
|
|
279
305
|
maxAgeMs?: number;
|
|
306
|
+
signal?: AbortSignal;
|
|
307
|
+
timeoutMs?: number;
|
|
280
308
|
}): Promise<MarketFeatureAsOf<MarketBreadthRow> | null>;
|
|
281
309
|
declare function getLatestMarketGlobalContext(params: {
|
|
282
310
|
source?: MarketGlobalContextRow['source'];
|
|
283
311
|
atMs: number;
|
|
284
312
|
maxAgeMs?: number;
|
|
313
|
+
signal?: AbortSignal;
|
|
314
|
+
timeoutMs?: number;
|
|
285
315
|
}): Promise<(MarketFeatureAsOf<MarketGlobalContextRow> & {
|
|
286
316
|
btcDominanceChange24hPct: number | null;
|
|
287
317
|
ethDominanceChange24hPct: number | null;
|
|
@@ -314,12 +344,16 @@ declare function getLatestMarketReferenceAssetContexts(params: {
|
|
|
314
344
|
interval?: MarketReferenceAssetContextRow['interval'];
|
|
315
345
|
atMs: number;
|
|
316
346
|
maxAgeMs?: number;
|
|
347
|
+
signal?: AbortSignal;
|
|
348
|
+
timeoutMs?: number;
|
|
317
349
|
}): Promise<Map<string, MarketFeatureAsOf<MarketReferenceAssetContextRow>>>;
|
|
318
350
|
declare function getLatestMarketCmcExchangeLiquidityContext(params: {
|
|
319
351
|
source?: MarketCmcExchangeLiquidityContextRow['source'];
|
|
320
352
|
interval?: MarketCmcExchangeLiquidityContextRow['interval'];
|
|
321
353
|
atMs: number;
|
|
322
354
|
maxAgeMs?: number;
|
|
355
|
+
signal?: AbortSignal;
|
|
356
|
+
timeoutMs?: number;
|
|
323
357
|
}): Promise<(MarketFeatureAsOf<MarketCmcExchangeLiquidityContextRow> & {
|
|
324
358
|
totalVolumeChange24hPct: number | null;
|
|
325
359
|
}) | null>;
|
|
@@ -329,6 +363,8 @@ declare function getLatestMarketCmcIndexContexts(params: {
|
|
|
329
363
|
interval?: MarketCmcIndexContextRow['interval'];
|
|
330
364
|
atMs: number;
|
|
331
365
|
maxAgeMs?: number;
|
|
366
|
+
signal?: AbortSignal;
|
|
367
|
+
timeoutMs?: number;
|
|
332
368
|
}): Promise<Map<MarketCmcIndexContextRow['indexSlug'], MarketFeatureAsOf<MarketCmcIndexContextRow> & {
|
|
333
369
|
valueChange24hPct: number | null;
|
|
334
370
|
}>>;
|
|
@@ -337,6 +373,8 @@ declare function getLatestMarketCmcFearGreedContext(params: {
|
|
|
337
373
|
interval?: MarketCmcFearGreedContextRow['interval'];
|
|
338
374
|
atMs: number;
|
|
339
375
|
maxAgeMs?: number;
|
|
376
|
+
signal?: AbortSignal;
|
|
377
|
+
timeoutMs?: number;
|
|
340
378
|
}): Promise<(MarketFeatureAsOf<MarketCmcFearGreedContextRow> & {
|
|
341
379
|
valueChange24h: number | null;
|
|
342
380
|
valueChange7d: number | null;
|
|
@@ -426,4 +464,4 @@ declare function findContinuityGap(provider: string, symbol: string, interval: n
|
|
|
426
464
|
diffSeconds: number;
|
|
427
465
|
} | null>;
|
|
428
466
|
|
|
429
|
-
export { type CandleRow, type DeprecatedMarketContextCleanupItem, type DerivativesMetricCoverageMetric, type HyperliquidWhaleCoverageSeriesRow, type HyperliquidWhaleFlowAggregate, type HyperliquidWhaleFlowSeriesRow, type HyperliquidWhaleWalletCoverageStatus, type MarketFeatureAsOf, applyDerivativesMetricCoverage, cleanupDeprecatedMarketContext, closeTimescalePool, deleteCandles, findContinuityGap, getCandlesRange, getDataEdges, getDataEdgesForSymbols, getDerivativesBackfillCoverage, getDerivativesDataEdgesForSymbols, getDerivativesMetricCoverage, getDerivativesRangeForSymbols, getDerivativesSummary, getDerivativesWindow, getHyperliquidWhaleCoverageSeriesRows, getHyperliquidWhaleFlowAggregate, getHyperliquidWhaleFlowSeriesRows, getHyperliquidWhaleWalletCoverage, getLatestMarketBreadth, getLatestMarketCmcExchangeLiquidityContext, getLatestMarketCmcFearGreedContext, getLatestMarketCmcIndexContexts, getLatestMarketGlobalContext, getLatestMarketReferenceAssetContexts, getLatestMarketTradeFlow, getMarketBreadthCoverage, getMarketCmcExchangeLiquidityContextCoverage, getMarketCmcFearGreedContextCoverage, getMarketCmcIndexContextCoverage, getMarketContextBackfillCoverage, getMarketGlobalContextCoverage, getMarketReferenceAssetContextCoverage, getMarketTradeFlowCoverage, getSpreadRangeForSymbols, getSpreadSummary, hasHyperliquidWhaleBackfillCoverage, rebuildHyperliquidWhaleCoverageRows, rebuildHyperliquidWhaleFlowRows, toRows, upsertCandles, upsertDerivatives, upsertDerivativesBackfillCoverage, upsertHyperliquidWhaleCoverageRows, upsertHyperliquidWhaleFlowRows, upsertHyperliquidWhaleTradeEvents, upsertHyperliquidWhaleWalletCoverage, upsertMarketBreadthRows, upsertMarketCmcExchangeLiquidityContextRows, upsertMarketCmcFearGreedContextRows, upsertMarketCmcIndexContextRows, upsertMarketContextBackfillCoverage, upsertMarketGlobalContextRows, upsertMarketReferenceAssetContextRows, upsertMarketTradeFlowRows, upsertSpreadRows, waitForDbReady };
|
|
467
|
+
export { type CandleRow, type DeprecatedMarketContextCleanupItem, type DerivativesMetricCoverageMetric, type HyperliquidWhaleCoverageSeriesRow, type HyperliquidWhaleFlowAggregate, type HyperliquidWhaleFlowSeriesRow, type HyperliquidWhaleWalletCoverageStatus, type MarketFeatureAsOf, type TimescaleMarketContextQueryOptions, type TimescaleMarketContextSource, applyDerivativesMetricCoverage, cleanupDeprecatedMarketContext, closeTimescalePool, configureTimescaleMarketContextSchemaMode, deleteCandles, ensureBinanceMarketSchema, ensureCoinMarketCapContextSchema, ensureDerivativesSchema, ensureHyperliquidWhaleSchema, ensureMarketContextSchemas, findContinuityGap, getCandlesRange, getDataEdges, getDataEdgesForSymbols, getDerivativesBackfillCoverage, getDerivativesDataEdgesForSymbols, getDerivativesMetricCoverage, getDerivativesRangeForSymbols, getDerivativesSummary, getDerivativesWindow, getHyperliquidWhaleCoverageSeriesRows, getHyperliquidWhaleFlowAggregate, getHyperliquidWhaleFlowSeriesRows, getHyperliquidWhaleWalletCoverage, getLatestMarketBreadth, getLatestMarketCmcExchangeLiquidityContext, getLatestMarketCmcFearGreedContext, getLatestMarketCmcIndexContexts, getLatestMarketGlobalContext, getLatestMarketReferenceAssetContexts, getLatestMarketTradeFlow, getMarketBreadthCoverage, getMarketCmcExchangeLiquidityContextCoverage, getMarketCmcFearGreedContextCoverage, getMarketCmcIndexContextCoverage, getMarketContextBackfillCoverage, getMarketGlobalContextCoverage, getMarketReferenceAssetContextCoverage, getMarketTradeFlowCoverage, getSpreadRangeForSymbols, getSpreadSummary, hasHyperliquidWhaleBackfillCoverage, rebuildHyperliquidWhaleCoverageRows, rebuildHyperliquidWhaleFlowRows, toRows, upsertCandles, upsertDerivatives, upsertDerivativesBackfillCoverage, upsertHyperliquidWhaleCoverageRows, upsertHyperliquidWhaleFlowRows, upsertHyperliquidWhaleTradeEvents, upsertHyperliquidWhaleWalletCoverage, upsertMarketBreadthRows, upsertMarketCmcExchangeLiquidityContextRows, upsertMarketCmcFearGreedContextRows, upsertMarketCmcIndexContextRows, upsertMarketContextBackfillCoverage, upsertMarketGlobalContextRows, upsertMarketReferenceAssetContextRows, upsertMarketTradeFlowRows, upsertSpreadRows, waitForDbReady };
|
package/dist/timescale.d.ts
CHANGED
|
@@ -20,9 +20,25 @@ type CandleRow = {
|
|
|
20
20
|
takerSellBaseVolume?: number | null;
|
|
21
21
|
takerSellQuoteVolume?: number | null;
|
|
22
22
|
};
|
|
23
|
+
type TimescaleMarketContextSource = 'binance' | 'coinmarketcap' | 'derivatives' | 'hyperliquidWhales';
|
|
24
|
+
type TimescaleMarketContextQueryOptions = {
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
};
|
|
28
|
+
declare const configureTimescaleMarketContextSchemaMode: (mode: "ensure" | "verify") => void;
|
|
23
29
|
declare const closeTimescalePool: () => Promise<void>;
|
|
24
30
|
declare const toRows: (provider: string, symbol: string, interval: number, data: KlineChartData) => CandleRow[];
|
|
25
31
|
declare function upsertCandles(rows: CandleRow[]): Promise<void>;
|
|
32
|
+
declare const ensureDerivativesSchema: () => Promise<void>;
|
|
33
|
+
declare const ensureBinanceMarketSchema: () => Promise<void>;
|
|
34
|
+
declare const ensureHyperliquidWhaleSchema: () => Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* CoinMarketCap tables currently share the historical market-context migration
|
|
37
|
+
* with the Binance tables. Keeping a source-specific entrypoint lets process
|
|
38
|
+
* composition own schema preparation without exposing that storage detail.
|
|
39
|
+
*/
|
|
40
|
+
declare const ensureCoinMarketCapContextSchema: () => Promise<void>;
|
|
41
|
+
declare const ensureMarketContextSchemas: (sources: Iterable<TimescaleMarketContextSource>) => Promise<void>;
|
|
26
42
|
declare function upsertDerivatives(rows: DerivativesRow[]): Promise<void>;
|
|
27
43
|
declare function getDerivativesRangeForSymbols(symbols: string[], interval: DerivativesInterval, startMs: number, endMs: number): Promise<any[]>;
|
|
28
44
|
declare function getDerivativesDataEdgesForSymbols(symbols: string[], interval: DerivativesInterval): Promise<Map<string, {
|
|
@@ -83,6 +99,8 @@ declare function getDerivativesWindow(params: {
|
|
|
83
99
|
intervals: DerivativesInterval[];
|
|
84
100
|
endMs: number;
|
|
85
101
|
lookbackMs: number;
|
|
102
|
+
signal?: AbortSignal;
|
|
103
|
+
timeoutMs?: number;
|
|
86
104
|
}): Promise<Partial<Record<DerivativesInterval, DerivativesRow[]>>>;
|
|
87
105
|
declare function getDerivativesSummary(hours?: number, limit?: number, symbols?: string[]): Promise<{
|
|
88
106
|
hours: number;
|
|
@@ -153,6 +171,8 @@ declare function getLatestMarketTradeFlow(params: {
|
|
|
153
171
|
interval: MarketFeatureInterval;
|
|
154
172
|
atMs: number;
|
|
155
173
|
maxAgeMs?: number;
|
|
174
|
+
signal?: AbortSignal;
|
|
175
|
+
timeoutMs?: number;
|
|
156
176
|
}): Promise<MarketFeatureAsOf<MarketTradeFlowRow> | null>;
|
|
157
177
|
type HyperliquidWhaleWalletCoverageStatus = 'complete' | 'truncated' | 'failed';
|
|
158
178
|
declare function getHyperliquidWhaleWalletCoverage(params: {
|
|
@@ -200,6 +220,8 @@ declare function getHyperliquidWhaleCoverageSeriesRows(params: {
|
|
|
200
220
|
toMs: number;
|
|
201
221
|
universeFingerprint: string;
|
|
202
222
|
whaleRegistryFingerprint: string;
|
|
223
|
+
signal?: AbortSignal;
|
|
224
|
+
timeoutMs?: number;
|
|
203
225
|
}): Promise<HyperliquidWhaleCoverageSeriesRow[]>;
|
|
204
226
|
type HyperliquidWhaleFlowSeriesRow = {
|
|
205
227
|
ts: Date;
|
|
@@ -224,6 +246,8 @@ declare function getHyperliquidWhaleFlowSeriesRows(params: {
|
|
|
224
246
|
toMs: number;
|
|
225
247
|
universeFingerprint: string;
|
|
226
248
|
whaleRegistryFingerprint: string;
|
|
249
|
+
signal?: AbortSignal;
|
|
250
|
+
timeoutMs?: number;
|
|
227
251
|
}): Promise<HyperliquidWhaleFlowSeriesRow[]>;
|
|
228
252
|
type HyperliquidWhaleFlowAggregate = {
|
|
229
253
|
symbol: string;
|
|
@@ -265,6 +289,8 @@ declare function getHyperliquidWhaleFlowAggregate(params: {
|
|
|
265
289
|
universeFingerprint: string;
|
|
266
290
|
whaleRegistryFingerprint: string;
|
|
267
291
|
maxAgeMs?: number;
|
|
292
|
+
signal?: AbortSignal;
|
|
293
|
+
timeoutMs?: number;
|
|
268
294
|
}): Promise<HyperliquidWhaleFlowAggregate | null>;
|
|
269
295
|
declare function hasHyperliquidWhaleBackfillCoverage(params: {
|
|
270
296
|
fromMs: number;
|
|
@@ -277,11 +303,15 @@ declare function getLatestMarketBreadth(params: {
|
|
|
277
303
|
interval: MarketFeatureInterval;
|
|
278
304
|
atMs: number;
|
|
279
305
|
maxAgeMs?: number;
|
|
306
|
+
signal?: AbortSignal;
|
|
307
|
+
timeoutMs?: number;
|
|
280
308
|
}): Promise<MarketFeatureAsOf<MarketBreadthRow> | null>;
|
|
281
309
|
declare function getLatestMarketGlobalContext(params: {
|
|
282
310
|
source?: MarketGlobalContextRow['source'];
|
|
283
311
|
atMs: number;
|
|
284
312
|
maxAgeMs?: number;
|
|
313
|
+
signal?: AbortSignal;
|
|
314
|
+
timeoutMs?: number;
|
|
285
315
|
}): Promise<(MarketFeatureAsOf<MarketGlobalContextRow> & {
|
|
286
316
|
btcDominanceChange24hPct: number | null;
|
|
287
317
|
ethDominanceChange24hPct: number | null;
|
|
@@ -314,12 +344,16 @@ declare function getLatestMarketReferenceAssetContexts(params: {
|
|
|
314
344
|
interval?: MarketReferenceAssetContextRow['interval'];
|
|
315
345
|
atMs: number;
|
|
316
346
|
maxAgeMs?: number;
|
|
347
|
+
signal?: AbortSignal;
|
|
348
|
+
timeoutMs?: number;
|
|
317
349
|
}): Promise<Map<string, MarketFeatureAsOf<MarketReferenceAssetContextRow>>>;
|
|
318
350
|
declare function getLatestMarketCmcExchangeLiquidityContext(params: {
|
|
319
351
|
source?: MarketCmcExchangeLiquidityContextRow['source'];
|
|
320
352
|
interval?: MarketCmcExchangeLiquidityContextRow['interval'];
|
|
321
353
|
atMs: number;
|
|
322
354
|
maxAgeMs?: number;
|
|
355
|
+
signal?: AbortSignal;
|
|
356
|
+
timeoutMs?: number;
|
|
323
357
|
}): Promise<(MarketFeatureAsOf<MarketCmcExchangeLiquidityContextRow> & {
|
|
324
358
|
totalVolumeChange24hPct: number | null;
|
|
325
359
|
}) | null>;
|
|
@@ -329,6 +363,8 @@ declare function getLatestMarketCmcIndexContexts(params: {
|
|
|
329
363
|
interval?: MarketCmcIndexContextRow['interval'];
|
|
330
364
|
atMs: number;
|
|
331
365
|
maxAgeMs?: number;
|
|
366
|
+
signal?: AbortSignal;
|
|
367
|
+
timeoutMs?: number;
|
|
332
368
|
}): Promise<Map<MarketCmcIndexContextRow['indexSlug'], MarketFeatureAsOf<MarketCmcIndexContextRow> & {
|
|
333
369
|
valueChange24hPct: number | null;
|
|
334
370
|
}>>;
|
|
@@ -337,6 +373,8 @@ declare function getLatestMarketCmcFearGreedContext(params: {
|
|
|
337
373
|
interval?: MarketCmcFearGreedContextRow['interval'];
|
|
338
374
|
atMs: number;
|
|
339
375
|
maxAgeMs?: number;
|
|
376
|
+
signal?: AbortSignal;
|
|
377
|
+
timeoutMs?: number;
|
|
340
378
|
}): Promise<(MarketFeatureAsOf<MarketCmcFearGreedContextRow> & {
|
|
341
379
|
valueChange24h: number | null;
|
|
342
380
|
valueChange7d: number | null;
|
|
@@ -426,4 +464,4 @@ declare function findContinuityGap(provider: string, symbol: string, interval: n
|
|
|
426
464
|
diffSeconds: number;
|
|
427
465
|
} | null>;
|
|
428
466
|
|
|
429
|
-
export { type CandleRow, type DeprecatedMarketContextCleanupItem, type DerivativesMetricCoverageMetric, type HyperliquidWhaleCoverageSeriesRow, type HyperliquidWhaleFlowAggregate, type HyperliquidWhaleFlowSeriesRow, type HyperliquidWhaleWalletCoverageStatus, type MarketFeatureAsOf, applyDerivativesMetricCoverage, cleanupDeprecatedMarketContext, closeTimescalePool, deleteCandles, findContinuityGap, getCandlesRange, getDataEdges, getDataEdgesForSymbols, getDerivativesBackfillCoverage, getDerivativesDataEdgesForSymbols, getDerivativesMetricCoverage, getDerivativesRangeForSymbols, getDerivativesSummary, getDerivativesWindow, getHyperliquidWhaleCoverageSeriesRows, getHyperliquidWhaleFlowAggregate, getHyperliquidWhaleFlowSeriesRows, getHyperliquidWhaleWalletCoverage, getLatestMarketBreadth, getLatestMarketCmcExchangeLiquidityContext, getLatestMarketCmcFearGreedContext, getLatestMarketCmcIndexContexts, getLatestMarketGlobalContext, getLatestMarketReferenceAssetContexts, getLatestMarketTradeFlow, getMarketBreadthCoverage, getMarketCmcExchangeLiquidityContextCoverage, getMarketCmcFearGreedContextCoverage, getMarketCmcIndexContextCoverage, getMarketContextBackfillCoverage, getMarketGlobalContextCoverage, getMarketReferenceAssetContextCoverage, getMarketTradeFlowCoverage, getSpreadRangeForSymbols, getSpreadSummary, hasHyperliquidWhaleBackfillCoverage, rebuildHyperliquidWhaleCoverageRows, rebuildHyperliquidWhaleFlowRows, toRows, upsertCandles, upsertDerivatives, upsertDerivativesBackfillCoverage, upsertHyperliquidWhaleCoverageRows, upsertHyperliquidWhaleFlowRows, upsertHyperliquidWhaleTradeEvents, upsertHyperliquidWhaleWalletCoverage, upsertMarketBreadthRows, upsertMarketCmcExchangeLiquidityContextRows, upsertMarketCmcFearGreedContextRows, upsertMarketCmcIndexContextRows, upsertMarketContextBackfillCoverage, upsertMarketGlobalContextRows, upsertMarketReferenceAssetContextRows, upsertMarketTradeFlowRows, upsertSpreadRows, waitForDbReady };
|
|
467
|
+
export { type CandleRow, type DeprecatedMarketContextCleanupItem, type DerivativesMetricCoverageMetric, type HyperliquidWhaleCoverageSeriesRow, type HyperliquidWhaleFlowAggregate, type HyperliquidWhaleFlowSeriesRow, type HyperliquidWhaleWalletCoverageStatus, type MarketFeatureAsOf, type TimescaleMarketContextQueryOptions, type TimescaleMarketContextSource, applyDerivativesMetricCoverage, cleanupDeprecatedMarketContext, closeTimescalePool, configureTimescaleMarketContextSchemaMode, deleteCandles, ensureBinanceMarketSchema, ensureCoinMarketCapContextSchema, ensureDerivativesSchema, ensureHyperliquidWhaleSchema, ensureMarketContextSchemas, findContinuityGap, getCandlesRange, getDataEdges, getDataEdgesForSymbols, getDerivativesBackfillCoverage, getDerivativesDataEdgesForSymbols, getDerivativesMetricCoverage, getDerivativesRangeForSymbols, getDerivativesSummary, getDerivativesWindow, getHyperliquidWhaleCoverageSeriesRows, getHyperliquidWhaleFlowAggregate, getHyperliquidWhaleFlowSeriesRows, getHyperliquidWhaleWalletCoverage, getLatestMarketBreadth, getLatestMarketCmcExchangeLiquidityContext, getLatestMarketCmcFearGreedContext, getLatestMarketCmcIndexContexts, getLatestMarketGlobalContext, getLatestMarketReferenceAssetContexts, getLatestMarketTradeFlow, getMarketBreadthCoverage, getMarketCmcExchangeLiquidityContextCoverage, getMarketCmcFearGreedContextCoverage, getMarketCmcIndexContextCoverage, getMarketContextBackfillCoverage, getMarketGlobalContextCoverage, getMarketReferenceAssetContextCoverage, getMarketTradeFlowCoverage, getSpreadRangeForSymbols, getSpreadSummary, hasHyperliquidWhaleBackfillCoverage, rebuildHyperliquidWhaleCoverageRows, rebuildHyperliquidWhaleFlowRows, toRows, upsertCandles, upsertDerivatives, upsertDerivativesBackfillCoverage, upsertHyperliquidWhaleCoverageRows, upsertHyperliquidWhaleFlowRows, upsertHyperliquidWhaleTradeEvents, upsertHyperliquidWhaleWalletCoverage, upsertMarketBreadthRows, upsertMarketCmcExchangeLiquidityContextRows, upsertMarketCmcFearGreedContextRows, upsertMarketCmcIndexContextRows, upsertMarketContextBackfillCoverage, upsertMarketGlobalContextRows, upsertMarketReferenceAssetContextRows, upsertMarketTradeFlowRows, upsertSpreadRows, waitForDbReady };
|
package/dist/timescale.js
CHANGED
|
@@ -23,7 +23,13 @@ __export(timescale_exports, {
|
|
|
23
23
|
applyDerivativesMetricCoverage: () => applyDerivativesMetricCoverage,
|
|
24
24
|
cleanupDeprecatedMarketContext: () => cleanupDeprecatedMarketContext,
|
|
25
25
|
closeTimescalePool: () => closeTimescalePool,
|
|
26
|
+
configureTimescaleMarketContextSchemaMode: () => configureTimescaleMarketContextSchemaMode,
|
|
26
27
|
deleteCandles: () => deleteCandles,
|
|
28
|
+
ensureBinanceMarketSchema: () => ensureBinanceMarketSchema,
|
|
29
|
+
ensureCoinMarketCapContextSchema: () => ensureCoinMarketCapContextSchema,
|
|
30
|
+
ensureDerivativesSchema: () => ensureDerivativesSchema,
|
|
31
|
+
ensureHyperliquidWhaleSchema: () => ensureHyperliquidWhaleSchema,
|
|
32
|
+
ensureMarketContextSchemas: () => ensureMarketContextSchemas,
|
|
27
33
|
findContinuityGap: () => findContinuityGap,
|
|
28
34
|
getCandlesRange: () => getCandlesRange,
|
|
29
35
|
getDataEdges: () => getDataEdges,
|
|
@@ -114,6 +120,12 @@ var derivativesSchemaReadyPromise = null;
|
|
|
114
120
|
var spreadSchemaReadyPromise = null;
|
|
115
121
|
var binanceMarketSchemaReadyPromise = null;
|
|
116
122
|
var hyperliquidWhaleSchemaReadyPromise = null;
|
|
123
|
+
var marketContextSchemaMode = "ensure";
|
|
124
|
+
var verifiedMarketContextSchemas = /* @__PURE__ */ new Set();
|
|
125
|
+
var configureTimescaleMarketContextSchemaMode = (mode) => {
|
|
126
|
+
marketContextSchemaMode = mode;
|
|
127
|
+
verifiedMarketContextSchemas.clear();
|
|
128
|
+
};
|
|
117
129
|
var closeTimescalePool = async () => {
|
|
118
130
|
const pool = global.__pgPool__;
|
|
119
131
|
if (!pool) {
|
|
@@ -130,6 +142,7 @@ var closeTimescalePool = async () => {
|
|
|
130
142
|
spreadSchemaReadyPromise = null;
|
|
131
143
|
binanceMarketSchemaReadyPromise = null;
|
|
132
144
|
hyperliquidWhaleSchemaReadyPromise = null;
|
|
145
|
+
verifiedMarketContextSchemas.clear();
|
|
133
146
|
await pool.end();
|
|
134
147
|
};
|
|
135
148
|
var CANDLES_SCHEMA_LOCK_KEY = 61e4;
|
|
@@ -138,6 +151,70 @@ var SPREAD_SCHEMA_LOCK_KEY = 610002;
|
|
|
138
151
|
var BINANCE_MARKET_SCHEMA_LOCK_KEY = 610003;
|
|
139
152
|
var HYPERLIQUID_WHALE_SCHEMA_LOCK_KEY = 610004;
|
|
140
153
|
var PG_SAFE_MAX_BIND_PARAMS = 3e4;
|
|
154
|
+
var resolveMarketContextQueryTimeoutMs = (override) => {
|
|
155
|
+
if (Number.isFinite(override) && Number(override) > 0) {
|
|
156
|
+
return Math.floor(Number(override));
|
|
157
|
+
}
|
|
158
|
+
const configured = Number(process.env.MARKET_CONTEXT_SQL_TIMEOUT_MS);
|
|
159
|
+
return Number.isFinite(configured) && configured > 0 ? Math.floor(configured) : 3e4;
|
|
160
|
+
};
|
|
161
|
+
var createMarketContextQueryError = (name, message) => {
|
|
162
|
+
const error = new Error(message);
|
|
163
|
+
error.name = name;
|
|
164
|
+
return error;
|
|
165
|
+
};
|
|
166
|
+
var queryMarketContext = async (text, values, options = {}) => {
|
|
167
|
+
const pool = getPool();
|
|
168
|
+
const client = await pool.connect();
|
|
169
|
+
const timeoutMs = resolveMarketContextQueryTimeoutMs(options.timeoutMs);
|
|
170
|
+
let released = false;
|
|
171
|
+
let rejectCancellation;
|
|
172
|
+
const release = (error) => {
|
|
173
|
+
if (released) return;
|
|
174
|
+
released = true;
|
|
175
|
+
client.release(error);
|
|
176
|
+
};
|
|
177
|
+
const cancellation = new Promise((_resolve, reject) => {
|
|
178
|
+
rejectCancellation = reject;
|
|
179
|
+
});
|
|
180
|
+
const cancel = (error) => {
|
|
181
|
+
release(error);
|
|
182
|
+
rejectCancellation?.(error);
|
|
183
|
+
};
|
|
184
|
+
const onAbort = () => cancel(
|
|
185
|
+
createMarketContextQueryError(
|
|
186
|
+
"AbortError",
|
|
187
|
+
"Timescale market-context query aborted"
|
|
188
|
+
)
|
|
189
|
+
);
|
|
190
|
+
const timer = setTimeout(
|
|
191
|
+
() => cancel(
|
|
192
|
+
createMarketContextQueryError(
|
|
193
|
+
"TimescaleQueryTimeoutError",
|
|
194
|
+
`Timescale market-context query exceeded ${timeoutMs}ms`
|
|
195
|
+
)
|
|
196
|
+
),
|
|
197
|
+
timeoutMs
|
|
198
|
+
);
|
|
199
|
+
timer.unref?.();
|
|
200
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
201
|
+
try {
|
|
202
|
+
if (options.signal?.aborted) {
|
|
203
|
+
const error = createMarketContextQueryError(
|
|
204
|
+
"AbortError",
|
|
205
|
+
"Timescale market-context query aborted"
|
|
206
|
+
);
|
|
207
|
+
release(error);
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
const query = client.query(text, values);
|
|
211
|
+
return await Promise.race([query, cancellation]);
|
|
212
|
+
} finally {
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
215
|
+
release();
|
|
216
|
+
}
|
|
217
|
+
};
|
|
141
218
|
var normalizeCandleProvider = (provider) => String(provider || "").trim().toLowerCase();
|
|
142
219
|
var normalizeCandleSymbol = (symbol) => String(symbol || "").trim().toUpperCase();
|
|
143
220
|
var getSafeBulkInsertRows = (columnsCount) => Math.max(1, Math.floor(PG_SAFE_MAX_BIND_PARAMS / columnsCount));
|
|
@@ -942,6 +1019,58 @@ var ensureHyperliquidWhaleSchema = async () => {
|
|
|
942
1019
|
});
|
|
943
1020
|
await hyperliquidWhaleSchemaReadyPromise;
|
|
944
1021
|
};
|
|
1022
|
+
var ensureCoinMarketCapContextSchema = async () => ensureBinanceMarketSchema();
|
|
1023
|
+
var ensureMarketContextSchema = async (source) => {
|
|
1024
|
+
switch (source) {
|
|
1025
|
+
case "binance":
|
|
1026
|
+
return ensureBinanceMarketSchema();
|
|
1027
|
+
case "coinmarketcap":
|
|
1028
|
+
return ensureCoinMarketCapContextSchema();
|
|
1029
|
+
case "derivatives":
|
|
1030
|
+
return ensureDerivativesSchema();
|
|
1031
|
+
case "hyperliquidWhales":
|
|
1032
|
+
return ensureHyperliquidWhaleSchema();
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
var MARKET_CONTEXT_SCHEMA_TABLES = {
|
|
1036
|
+
binance: ["market_trade_flow", "market_breadth"],
|
|
1037
|
+
coinmarketcap: [
|
|
1038
|
+
"market_global_context",
|
|
1039
|
+
"market_reference_asset_context",
|
|
1040
|
+
"market_cmc_exchange_liquidity_context",
|
|
1041
|
+
"market_cmc_fear_greed_context",
|
|
1042
|
+
"market_cmc_index_context"
|
|
1043
|
+
],
|
|
1044
|
+
derivatives: ["derivatives_market"],
|
|
1045
|
+
hyperliquidWhales: [
|
|
1046
|
+
"hyperliquid_whale_flow",
|
|
1047
|
+
"hyperliquid_whale_coverage_1m"
|
|
1048
|
+
]
|
|
1049
|
+
};
|
|
1050
|
+
var verifyMarketContextSchema = async (source) => {
|
|
1051
|
+
if (verifiedMarketContextSchemas.has(source)) return;
|
|
1052
|
+
const tables = MARKET_CONTEXT_SCHEMA_TABLES[source];
|
|
1053
|
+
const result = await queryMarketContext(
|
|
1054
|
+
`
|
|
1055
|
+
SELECT table_name AS "tableName"
|
|
1056
|
+
FROM unnest($1::text[]) AS requested(table_name)
|
|
1057
|
+
WHERE to_regclass(requested.table_name) IS NULL
|
|
1058
|
+
`,
|
|
1059
|
+
[tables]
|
|
1060
|
+
);
|
|
1061
|
+
if (result.rows.length) {
|
|
1062
|
+
throw new Error(
|
|
1063
|
+
`Timescale ${source} schema is not prepared; missing: ${result.rows.map((row) => row.tableName).filter(Boolean).join(", ")}`
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
verifiedMarketContextSchemas.add(source);
|
|
1067
|
+
};
|
|
1068
|
+
var prepareMarketContextSchemaForRead = async (source) => marketContextSchemaMode === "verify" ? verifyMarketContextSchema(source) : ensureMarketContextSchema(source);
|
|
1069
|
+
var ensureMarketContextSchemas = async (sources) => {
|
|
1070
|
+
for (const source of new Set(sources)) {
|
|
1071
|
+
await ensureMarketContextSchema(source);
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
945
1074
|
async function upsertDerivatives(rows) {
|
|
946
1075
|
if (!rows.length) return;
|
|
947
1076
|
await ensureDerivativesSchema();
|
|
@@ -1269,9 +1398,8 @@ async function getDerivativesWindow(params) {
|
|
|
1269
1398
|
if (!normalizedSymbol || !normalizedIntervals.length) {
|
|
1270
1399
|
return {};
|
|
1271
1400
|
}
|
|
1272
|
-
await
|
|
1401
|
+
await prepareMarketContextSchemaForRead("derivatives");
|
|
1273
1402
|
const startMs = endMs - Math.max(0, lookbackMs);
|
|
1274
|
-
const pool = getPool();
|
|
1275
1403
|
const sql = `
|
|
1276
1404
|
SELECT symbol, interval, ts, open_interest, funding_rate, liq_long, liq_short, liq_total, source
|
|
1277
1405
|
FROM derivatives_market
|
|
@@ -1281,12 +1409,11 @@ async function getDerivativesWindow(params) {
|
|
|
1281
1409
|
AND ts <= to_timestamp($4/1000.0)
|
|
1282
1410
|
ORDER BY interval ASC, ts ASC
|
|
1283
1411
|
`;
|
|
1284
|
-
const res = await
|
|
1285
|
-
|
|
1286
|
-
normalizedIntervals,
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
]);
|
|
1412
|
+
const res = await queryMarketContext(
|
|
1413
|
+
sql,
|
|
1414
|
+
[normalizedSymbol, normalizedIntervals, startMs, endMs],
|
|
1415
|
+
params
|
|
1416
|
+
);
|
|
1290
1417
|
const rowsByInterval = {};
|
|
1291
1418
|
for (const row of res.rows) {
|
|
1292
1419
|
const interval = row.interval;
|
|
@@ -2493,9 +2620,8 @@ var toMarketFeatureAge = (rowTs, atMs) => {
|
|
|
2493
2620
|
return Number.isFinite(ageMs) ? ageMs : null;
|
|
2494
2621
|
};
|
|
2495
2622
|
async function getLatestMarketTradeFlow(params) {
|
|
2496
|
-
await
|
|
2497
|
-
const
|
|
2498
|
-
const res = await pool.query(
|
|
2623
|
+
await prepareMarketContextSchemaForRead("binance");
|
|
2624
|
+
const res = await queryMarketContext(
|
|
2499
2625
|
`
|
|
2500
2626
|
SELECT
|
|
2501
2627
|
symbol,
|
|
@@ -2517,7 +2643,8 @@ async function getLatestMarketTradeFlow(params) {
|
|
|
2517
2643
|
ORDER BY ts DESC
|
|
2518
2644
|
LIMIT 1
|
|
2519
2645
|
`,
|
|
2520
|
-
[params.symbol.toUpperCase(), params.interval, params.atMs]
|
|
2646
|
+
[params.symbol.toUpperCase(), params.interval, params.atMs],
|
|
2647
|
+
params
|
|
2521
2648
|
);
|
|
2522
2649
|
const row = res.rows[0];
|
|
2523
2650
|
if (!row) return null;
|
|
@@ -2768,8 +2895,8 @@ async function upsertHyperliquidWhaleCoverageRows(rows) {
|
|
|
2768
2895
|
);
|
|
2769
2896
|
}
|
|
2770
2897
|
async function getHyperliquidWhaleCoverageSeriesRows(params) {
|
|
2771
|
-
await
|
|
2772
|
-
const result = await
|
|
2898
|
+
await prepareMarketContextSchemaForRead("hyperliquidWhales");
|
|
2899
|
+
const result = await queryMarketContext(
|
|
2773
2900
|
`
|
|
2774
2901
|
SELECT
|
|
2775
2902
|
ts,
|
|
@@ -2790,7 +2917,8 @@ async function getHyperliquidWhaleCoverageSeriesRows(params) {
|
|
|
2790
2917
|
import_types.HYPERLIQUID_WHALE_DATA_MODEL_VERSION,
|
|
2791
2918
|
params.fromMs,
|
|
2792
2919
|
params.toMs
|
|
2793
|
-
]
|
|
2920
|
+
],
|
|
2921
|
+
params
|
|
2794
2922
|
);
|
|
2795
2923
|
return result.rows.map((row) => ({
|
|
2796
2924
|
ts: new Date(row.ts),
|
|
@@ -2800,8 +2928,8 @@ async function getHyperliquidWhaleCoverageSeriesRows(params) {
|
|
|
2800
2928
|
}));
|
|
2801
2929
|
}
|
|
2802
2930
|
async function getHyperliquidWhaleFlowSeriesRows(params) {
|
|
2803
|
-
await
|
|
2804
|
-
const result = await
|
|
2931
|
+
await prepareMarketContextSchemaForRead("hyperliquidWhales");
|
|
2932
|
+
const result = await queryMarketContext(
|
|
2805
2933
|
`
|
|
2806
2934
|
SELECT
|
|
2807
2935
|
ts,
|
|
@@ -2834,7 +2962,8 @@ async function getHyperliquidWhaleFlowSeriesRows(params) {
|
|
|
2834
2962
|
params.whaleRegistryFingerprint,
|
|
2835
2963
|
params.fromMs,
|
|
2836
2964
|
params.toMs
|
|
2837
|
-
]
|
|
2965
|
+
],
|
|
2966
|
+
params
|
|
2838
2967
|
);
|
|
2839
2968
|
return result.rows.map((row) => ({
|
|
2840
2969
|
ts: new Date(row.ts),
|
|
@@ -2855,10 +2984,10 @@ async function getHyperliquidWhaleFlowSeriesRows(params) {
|
|
|
2855
2984
|
}));
|
|
2856
2985
|
}
|
|
2857
2986
|
async function getHyperliquidWhaleFlowAggregate(params) {
|
|
2858
|
-
await
|
|
2987
|
+
await prepareMarketContextSchemaForRead("hyperliquidWhales");
|
|
2859
2988
|
const intervalMs = HYPERLIQUID_CONTEXT_INTERVAL_MS[params.interval];
|
|
2860
2989
|
const expectedBuckets = Math.ceil(intervalMs / 6e4);
|
|
2861
|
-
const res = await
|
|
2990
|
+
const res = await queryMarketContext(
|
|
2862
2991
|
`
|
|
2863
2992
|
WITH coverage_rows AS (
|
|
2864
2993
|
SELECT *
|
|
@@ -2973,7 +3102,8 @@ async function getHyperliquidWhaleFlowAggregate(params) {
|
|
|
2973
3102
|
params.decisionTimeMs,
|
|
2974
3103
|
intervalMs,
|
|
2975
3104
|
import_types.HYPERLIQUID_WHALE_DATA_MODEL_VERSION
|
|
2976
|
-
]
|
|
3105
|
+
],
|
|
3106
|
+
params
|
|
2977
3107
|
);
|
|
2978
3108
|
const row = res.rows[0];
|
|
2979
3109
|
if (!row?.as_of_ts || Number(row.coverage_buckets) !== expectedBuckets || Number(row.covered_whales) <= 0) {
|
|
@@ -3046,9 +3176,8 @@ async function hasHyperliquidWhaleBackfillCoverage(params) {
|
|
|
3046
3176
|
return Number(result.rows[0]?.buckets) === expectedBuckets && Number(result.rows[0]?.complete_buckets) === expectedBuckets;
|
|
3047
3177
|
}
|
|
3048
3178
|
async function getLatestMarketBreadth(params) {
|
|
3049
|
-
await
|
|
3050
|
-
const
|
|
3051
|
-
const res = await pool.query(
|
|
3179
|
+
await prepareMarketContextSchemaForRead("binance");
|
|
3180
|
+
const res = await queryMarketContext(
|
|
3052
3181
|
`
|
|
3053
3182
|
SELECT
|
|
3054
3183
|
universe,
|
|
@@ -3087,7 +3216,8 @@ async function getLatestMarketBreadth(params) {
|
|
|
3087
3216
|
ORDER BY ts DESC
|
|
3088
3217
|
LIMIT 1
|
|
3089
3218
|
`,
|
|
3090
|
-
[params.universe, params.interval, params.atMs]
|
|
3219
|
+
[params.universe, params.interval, params.atMs],
|
|
3220
|
+
params
|
|
3091
3221
|
);
|
|
3092
3222
|
const row = res.rows[0];
|
|
3093
3223
|
if (!row) return null;
|
|
@@ -3099,10 +3229,9 @@ async function getLatestMarketBreadth(params) {
|
|
|
3099
3229
|
};
|
|
3100
3230
|
}
|
|
3101
3231
|
async function getLatestMarketGlobalContext(params) {
|
|
3102
|
-
await
|
|
3103
|
-
const pool = getPool();
|
|
3232
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3104
3233
|
const source = params.source ?? "coinmarketcap_global";
|
|
3105
|
-
const res = await
|
|
3234
|
+
const res = await queryMarketContext(
|
|
3106
3235
|
`
|
|
3107
3236
|
SELECT
|
|
3108
3237
|
source,
|
|
@@ -3131,11 +3260,12 @@ async function getLatestMarketGlobalContext(params) {
|
|
|
3131
3260
|
ORDER BY ts DESC
|
|
3132
3261
|
LIMIT 1
|
|
3133
3262
|
`,
|
|
3134
|
-
[source, params.atMs]
|
|
3263
|
+
[source, params.atMs],
|
|
3264
|
+
params
|
|
3135
3265
|
);
|
|
3136
3266
|
const row = res.rows[0];
|
|
3137
3267
|
if (!row) return null;
|
|
3138
|
-
const previousRes = await
|
|
3268
|
+
const previousRes = await queryMarketContext(
|
|
3139
3269
|
`
|
|
3140
3270
|
SELECT
|
|
3141
3271
|
btc_dominance_pct AS "btcDominancePct",
|
|
@@ -3148,7 +3278,8 @@ async function getLatestMarketGlobalContext(params) {
|
|
|
3148
3278
|
ORDER BY ts DESC
|
|
3149
3279
|
LIMIT 1
|
|
3150
3280
|
`,
|
|
3151
|
-
[source, row.ts]
|
|
3281
|
+
[source, row.ts],
|
|
3282
|
+
params
|
|
3152
3283
|
);
|
|
3153
3284
|
const previousDominance = previousRes.rows[0]?.btcDominancePct == null ? null : Number(previousRes.rows[0].btcDominancePct);
|
|
3154
3285
|
const previousEthDominance = previousRes.rows[0]?.ethDominancePct == null ? null : Number(previousRes.rows[0].ethDominancePct);
|
|
@@ -3241,9 +3372,8 @@ async function getLatestMarketReferenceAssetContexts(params) {
|
|
|
3241
3372
|
];
|
|
3242
3373
|
const rows = /* @__PURE__ */ new Map();
|
|
3243
3374
|
if (!symbols.length) return rows;
|
|
3244
|
-
await
|
|
3245
|
-
const
|
|
3246
|
-
const res = await pool.query(
|
|
3375
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3376
|
+
const res = await queryMarketContext(
|
|
3247
3377
|
`
|
|
3248
3378
|
SELECT DISTINCT ON (symbol)
|
|
3249
3379
|
source,
|
|
@@ -3268,7 +3398,8 @@ async function getLatestMarketReferenceAssetContexts(params) {
|
|
|
3268
3398
|
END <= to_timestamp($4/1000.0)
|
|
3269
3399
|
ORDER BY symbol ASC, ts DESC
|
|
3270
3400
|
`,
|
|
3271
|
-
[source, symbols, interval, params.atMs]
|
|
3401
|
+
[source, symbols, interval, params.atMs],
|
|
3402
|
+
params
|
|
3272
3403
|
);
|
|
3273
3404
|
for (const row of res.rows) {
|
|
3274
3405
|
const ageMs = toMarketFeatureAge(row.ts, params.atMs);
|
|
@@ -3281,11 +3412,10 @@ async function getLatestMarketReferenceAssetContexts(params) {
|
|
|
3281
3412
|
return rows;
|
|
3282
3413
|
}
|
|
3283
3414
|
async function getLatestMarketCmcExchangeLiquidityContext(params) {
|
|
3284
|
-
await
|
|
3285
|
-
const pool = getPool();
|
|
3415
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3286
3416
|
const source = params.source ?? "coinmarketcap_exchange_liquidity";
|
|
3287
3417
|
const interval = params.interval ?? "1d";
|
|
3288
|
-
const res = await
|
|
3418
|
+
const res = await queryMarketContext(
|
|
3289
3419
|
`
|
|
3290
3420
|
SELECT
|
|
3291
3421
|
source,
|
|
@@ -3308,11 +3438,12 @@ async function getLatestMarketCmcExchangeLiquidityContext(params) {
|
|
|
3308
3438
|
ORDER BY ts DESC
|
|
3309
3439
|
LIMIT 1
|
|
3310
3440
|
`,
|
|
3311
|
-
[source, interval, params.atMs]
|
|
3441
|
+
[source, interval, params.atMs],
|
|
3442
|
+
params
|
|
3312
3443
|
);
|
|
3313
3444
|
const row = res.rows[0];
|
|
3314
3445
|
if (!row) return null;
|
|
3315
|
-
const previousRes = await
|
|
3446
|
+
const previousRes = await queryMarketContext(
|
|
3316
3447
|
`
|
|
3317
3448
|
SELECT total_volume_usd AS "totalVolumeUsd"
|
|
3318
3449
|
FROM market_cmc_exchange_liquidity_context
|
|
@@ -3322,7 +3453,8 @@ async function getLatestMarketCmcExchangeLiquidityContext(params) {
|
|
|
3322
3453
|
ORDER BY ts DESC
|
|
3323
3454
|
LIMIT 1
|
|
3324
3455
|
`,
|
|
3325
|
-
[source, interval, row.ts]
|
|
3456
|
+
[source, interval, row.ts],
|
|
3457
|
+
params
|
|
3326
3458
|
);
|
|
3327
3459
|
const currentTotal = row.totalVolumeUsd == null ? null : Number(row.totalVolumeUsd);
|
|
3328
3460
|
const previousTotal = previousRes.rows[0]?.totalVolumeUsd == null ? null : Number(previousRes.rows[0].totalVolumeUsd);
|
|
@@ -3346,9 +3478,8 @@ async function getLatestMarketCmcIndexContexts(params) {
|
|
|
3346
3478
|
];
|
|
3347
3479
|
const rows = /* @__PURE__ */ new Map();
|
|
3348
3480
|
if (!indexSlugs.length) return rows;
|
|
3349
|
-
await
|
|
3350
|
-
const
|
|
3351
|
-
const res = await pool.query(
|
|
3481
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3482
|
+
const res = await queryMarketContext(
|
|
3352
3483
|
`
|
|
3353
3484
|
SELECT DISTINCT ON (index_slug)
|
|
3354
3485
|
source,
|
|
@@ -3371,10 +3502,11 @@ async function getLatestMarketCmcIndexContexts(params) {
|
|
|
3371
3502
|
END <= to_timestamp($4/1000.0)
|
|
3372
3503
|
ORDER BY index_slug ASC, ts DESC
|
|
3373
3504
|
`,
|
|
3374
|
-
[source, indexSlugs, interval, params.atMs]
|
|
3505
|
+
[source, indexSlugs, interval, params.atMs],
|
|
3506
|
+
params
|
|
3375
3507
|
);
|
|
3376
3508
|
for (const row of res.rows) {
|
|
3377
|
-
const previousRes = await
|
|
3509
|
+
const previousRes = await queryMarketContext(
|
|
3378
3510
|
`
|
|
3379
3511
|
SELECT value
|
|
3380
3512
|
FROM market_cmc_index_context
|
|
@@ -3385,7 +3517,8 @@ async function getLatestMarketCmcIndexContexts(params) {
|
|
|
3385
3517
|
ORDER BY ts DESC
|
|
3386
3518
|
LIMIT 1
|
|
3387
3519
|
`,
|
|
3388
|
-
[source, row.indexSlug, interval, row.ts]
|
|
3520
|
+
[source, row.indexSlug, interval, row.ts],
|
|
3521
|
+
params
|
|
3389
3522
|
);
|
|
3390
3523
|
const currentValue = row.value == null ? null : Number(row.value);
|
|
3391
3524
|
const previousValue = previousRes.rows[0]?.value == null ? null : Number(previousRes.rows[0].value);
|
|
@@ -3400,11 +3533,10 @@ async function getLatestMarketCmcIndexContexts(params) {
|
|
|
3400
3533
|
return rows;
|
|
3401
3534
|
}
|
|
3402
3535
|
async function getLatestMarketCmcFearGreedContext(params) {
|
|
3403
|
-
await
|
|
3404
|
-
const pool = getPool();
|
|
3536
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3405
3537
|
const source = params.source ?? "coinmarketcap_fear_greed";
|
|
3406
3538
|
const interval = params.interval ?? "1d";
|
|
3407
|
-
const res = await
|
|
3539
|
+
const res = await queryMarketContext(
|
|
3408
3540
|
`
|
|
3409
3541
|
SELECT
|
|
3410
3542
|
source,
|
|
@@ -3424,11 +3556,12 @@ async function getLatestMarketCmcFearGreedContext(params) {
|
|
|
3424
3556
|
ORDER BY ts DESC
|
|
3425
3557
|
LIMIT 1
|
|
3426
3558
|
`,
|
|
3427
|
-
[source, interval, params.atMs]
|
|
3559
|
+
[source, interval, params.atMs],
|
|
3560
|
+
params
|
|
3428
3561
|
);
|
|
3429
3562
|
const row = res.rows[0];
|
|
3430
3563
|
if (!row) return null;
|
|
3431
|
-
const previousRes = await
|
|
3564
|
+
const previousRes = await queryMarketContext(
|
|
3432
3565
|
`
|
|
3433
3566
|
SELECT
|
|
3434
3567
|
value::int AS value,
|
|
@@ -3440,9 +3573,10 @@ async function getLatestMarketCmcFearGreedContext(params) {
|
|
|
3440
3573
|
ORDER BY ts DESC
|
|
3441
3574
|
LIMIT 1
|
|
3442
3575
|
`,
|
|
3443
|
-
[source, interval, row.ts]
|
|
3576
|
+
[source, interval, row.ts],
|
|
3577
|
+
params
|
|
3444
3578
|
);
|
|
3445
|
-
const previous7dRes = await
|
|
3579
|
+
const previous7dRes = await queryMarketContext(
|
|
3446
3580
|
`
|
|
3447
3581
|
SELECT value::int AS value
|
|
3448
3582
|
FROM market_cmc_fear_greed_context
|
|
@@ -3452,7 +3586,8 @@ async function getLatestMarketCmcFearGreedContext(params) {
|
|
|
3452
3586
|
ORDER BY ts DESC
|
|
3453
3587
|
LIMIT 1
|
|
3454
3588
|
`,
|
|
3455
|
-
[source, interval, row.ts]
|
|
3589
|
+
[source, interval, row.ts],
|
|
3590
|
+
params
|
|
3456
3591
|
);
|
|
3457
3592
|
const previousValue = previousRes.rows[0]?.value == null ? null : Number(previousRes.rows[0].value);
|
|
3458
3593
|
const previous7dValue = previous7dRes.rows[0]?.value == null ? null : Number(previous7dRes.rows[0].value);
|
|
@@ -3939,7 +4074,13 @@ async function findContinuityGap(provider, symbol, interval) {
|
|
|
3939
4074
|
applyDerivativesMetricCoverage,
|
|
3940
4075
|
cleanupDeprecatedMarketContext,
|
|
3941
4076
|
closeTimescalePool,
|
|
4077
|
+
configureTimescaleMarketContextSchemaMode,
|
|
3942
4078
|
deleteCandles,
|
|
4079
|
+
ensureBinanceMarketSchema,
|
|
4080
|
+
ensureCoinMarketCapContextSchema,
|
|
4081
|
+
ensureDerivativesSchema,
|
|
4082
|
+
ensureHyperliquidWhaleSchema,
|
|
4083
|
+
ensureMarketContextSchemas,
|
|
3943
4084
|
findContinuityGap,
|
|
3944
4085
|
getCandlesRange,
|
|
3945
4086
|
getDataEdges,
|
package/dist/timescale.mjs
CHANGED
|
@@ -37,6 +37,12 @@ var derivativesSchemaReadyPromise = null;
|
|
|
37
37
|
var spreadSchemaReadyPromise = null;
|
|
38
38
|
var binanceMarketSchemaReadyPromise = null;
|
|
39
39
|
var hyperliquidWhaleSchemaReadyPromise = null;
|
|
40
|
+
var marketContextSchemaMode = "ensure";
|
|
41
|
+
var verifiedMarketContextSchemas = /* @__PURE__ */ new Set();
|
|
42
|
+
var configureTimescaleMarketContextSchemaMode = (mode) => {
|
|
43
|
+
marketContextSchemaMode = mode;
|
|
44
|
+
verifiedMarketContextSchemas.clear();
|
|
45
|
+
};
|
|
40
46
|
var closeTimescalePool = async () => {
|
|
41
47
|
const pool = global.__pgPool__;
|
|
42
48
|
if (!pool) {
|
|
@@ -53,6 +59,7 @@ var closeTimescalePool = async () => {
|
|
|
53
59
|
spreadSchemaReadyPromise = null;
|
|
54
60
|
binanceMarketSchemaReadyPromise = null;
|
|
55
61
|
hyperliquidWhaleSchemaReadyPromise = null;
|
|
62
|
+
verifiedMarketContextSchemas.clear();
|
|
56
63
|
await pool.end();
|
|
57
64
|
};
|
|
58
65
|
var CANDLES_SCHEMA_LOCK_KEY = 61e4;
|
|
@@ -61,6 +68,70 @@ var SPREAD_SCHEMA_LOCK_KEY = 610002;
|
|
|
61
68
|
var BINANCE_MARKET_SCHEMA_LOCK_KEY = 610003;
|
|
62
69
|
var HYPERLIQUID_WHALE_SCHEMA_LOCK_KEY = 610004;
|
|
63
70
|
var PG_SAFE_MAX_BIND_PARAMS = 3e4;
|
|
71
|
+
var resolveMarketContextQueryTimeoutMs = (override) => {
|
|
72
|
+
if (Number.isFinite(override) && Number(override) > 0) {
|
|
73
|
+
return Math.floor(Number(override));
|
|
74
|
+
}
|
|
75
|
+
const configured = Number(process.env.MARKET_CONTEXT_SQL_TIMEOUT_MS);
|
|
76
|
+
return Number.isFinite(configured) && configured > 0 ? Math.floor(configured) : 3e4;
|
|
77
|
+
};
|
|
78
|
+
var createMarketContextQueryError = (name, message) => {
|
|
79
|
+
const error = new Error(message);
|
|
80
|
+
error.name = name;
|
|
81
|
+
return error;
|
|
82
|
+
};
|
|
83
|
+
var queryMarketContext = async (text, values, options = {}) => {
|
|
84
|
+
const pool = getPool();
|
|
85
|
+
const client = await pool.connect();
|
|
86
|
+
const timeoutMs = resolveMarketContextQueryTimeoutMs(options.timeoutMs);
|
|
87
|
+
let released = false;
|
|
88
|
+
let rejectCancellation;
|
|
89
|
+
const release = (error) => {
|
|
90
|
+
if (released) return;
|
|
91
|
+
released = true;
|
|
92
|
+
client.release(error);
|
|
93
|
+
};
|
|
94
|
+
const cancellation = new Promise((_resolve, reject) => {
|
|
95
|
+
rejectCancellation = reject;
|
|
96
|
+
});
|
|
97
|
+
const cancel = (error) => {
|
|
98
|
+
release(error);
|
|
99
|
+
rejectCancellation?.(error);
|
|
100
|
+
};
|
|
101
|
+
const onAbort = () => cancel(
|
|
102
|
+
createMarketContextQueryError(
|
|
103
|
+
"AbortError",
|
|
104
|
+
"Timescale market-context query aborted"
|
|
105
|
+
)
|
|
106
|
+
);
|
|
107
|
+
const timer = setTimeout(
|
|
108
|
+
() => cancel(
|
|
109
|
+
createMarketContextQueryError(
|
|
110
|
+
"TimescaleQueryTimeoutError",
|
|
111
|
+
`Timescale market-context query exceeded ${timeoutMs}ms`
|
|
112
|
+
)
|
|
113
|
+
),
|
|
114
|
+
timeoutMs
|
|
115
|
+
);
|
|
116
|
+
timer.unref?.();
|
|
117
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
118
|
+
try {
|
|
119
|
+
if (options.signal?.aborted) {
|
|
120
|
+
const error = createMarketContextQueryError(
|
|
121
|
+
"AbortError",
|
|
122
|
+
"Timescale market-context query aborted"
|
|
123
|
+
);
|
|
124
|
+
release(error);
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
const query = client.query(text, values);
|
|
128
|
+
return await Promise.race([query, cancellation]);
|
|
129
|
+
} finally {
|
|
130
|
+
clearTimeout(timer);
|
|
131
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
132
|
+
release();
|
|
133
|
+
}
|
|
134
|
+
};
|
|
64
135
|
var normalizeCandleProvider = (provider) => String(provider || "").trim().toLowerCase();
|
|
65
136
|
var normalizeCandleSymbol = (symbol) => String(symbol || "").trim().toUpperCase();
|
|
66
137
|
var getSafeBulkInsertRows = (columnsCount) => Math.max(1, Math.floor(PG_SAFE_MAX_BIND_PARAMS / columnsCount));
|
|
@@ -865,6 +936,58 @@ var ensureHyperliquidWhaleSchema = async () => {
|
|
|
865
936
|
});
|
|
866
937
|
await hyperliquidWhaleSchemaReadyPromise;
|
|
867
938
|
};
|
|
939
|
+
var ensureCoinMarketCapContextSchema = async () => ensureBinanceMarketSchema();
|
|
940
|
+
var ensureMarketContextSchema = async (source) => {
|
|
941
|
+
switch (source) {
|
|
942
|
+
case "binance":
|
|
943
|
+
return ensureBinanceMarketSchema();
|
|
944
|
+
case "coinmarketcap":
|
|
945
|
+
return ensureCoinMarketCapContextSchema();
|
|
946
|
+
case "derivatives":
|
|
947
|
+
return ensureDerivativesSchema();
|
|
948
|
+
case "hyperliquidWhales":
|
|
949
|
+
return ensureHyperliquidWhaleSchema();
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
var MARKET_CONTEXT_SCHEMA_TABLES = {
|
|
953
|
+
binance: ["market_trade_flow", "market_breadth"],
|
|
954
|
+
coinmarketcap: [
|
|
955
|
+
"market_global_context",
|
|
956
|
+
"market_reference_asset_context",
|
|
957
|
+
"market_cmc_exchange_liquidity_context",
|
|
958
|
+
"market_cmc_fear_greed_context",
|
|
959
|
+
"market_cmc_index_context"
|
|
960
|
+
],
|
|
961
|
+
derivatives: ["derivatives_market"],
|
|
962
|
+
hyperliquidWhales: [
|
|
963
|
+
"hyperliquid_whale_flow",
|
|
964
|
+
"hyperliquid_whale_coverage_1m"
|
|
965
|
+
]
|
|
966
|
+
};
|
|
967
|
+
var verifyMarketContextSchema = async (source) => {
|
|
968
|
+
if (verifiedMarketContextSchemas.has(source)) return;
|
|
969
|
+
const tables = MARKET_CONTEXT_SCHEMA_TABLES[source];
|
|
970
|
+
const result = await queryMarketContext(
|
|
971
|
+
`
|
|
972
|
+
SELECT table_name AS "tableName"
|
|
973
|
+
FROM unnest($1::text[]) AS requested(table_name)
|
|
974
|
+
WHERE to_regclass(requested.table_name) IS NULL
|
|
975
|
+
`,
|
|
976
|
+
[tables]
|
|
977
|
+
);
|
|
978
|
+
if (result.rows.length) {
|
|
979
|
+
throw new Error(
|
|
980
|
+
`Timescale ${source} schema is not prepared; missing: ${result.rows.map((row) => row.tableName).filter(Boolean).join(", ")}`
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
|
+
verifiedMarketContextSchemas.add(source);
|
|
984
|
+
};
|
|
985
|
+
var prepareMarketContextSchemaForRead = async (source) => marketContextSchemaMode === "verify" ? verifyMarketContextSchema(source) : ensureMarketContextSchema(source);
|
|
986
|
+
var ensureMarketContextSchemas = async (sources) => {
|
|
987
|
+
for (const source of new Set(sources)) {
|
|
988
|
+
await ensureMarketContextSchema(source);
|
|
989
|
+
}
|
|
990
|
+
};
|
|
868
991
|
async function upsertDerivatives(rows) {
|
|
869
992
|
if (!rows.length) return;
|
|
870
993
|
await ensureDerivativesSchema();
|
|
@@ -1192,9 +1315,8 @@ async function getDerivativesWindow(params) {
|
|
|
1192
1315
|
if (!normalizedSymbol || !normalizedIntervals.length) {
|
|
1193
1316
|
return {};
|
|
1194
1317
|
}
|
|
1195
|
-
await
|
|
1318
|
+
await prepareMarketContextSchemaForRead("derivatives");
|
|
1196
1319
|
const startMs = endMs - Math.max(0, lookbackMs);
|
|
1197
|
-
const pool = getPool();
|
|
1198
1320
|
const sql = `
|
|
1199
1321
|
SELECT symbol, interval, ts, open_interest, funding_rate, liq_long, liq_short, liq_total, source
|
|
1200
1322
|
FROM derivatives_market
|
|
@@ -1204,12 +1326,11 @@ async function getDerivativesWindow(params) {
|
|
|
1204
1326
|
AND ts <= to_timestamp($4/1000.0)
|
|
1205
1327
|
ORDER BY interval ASC, ts ASC
|
|
1206
1328
|
`;
|
|
1207
|
-
const res = await
|
|
1208
|
-
|
|
1209
|
-
normalizedIntervals,
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
]);
|
|
1329
|
+
const res = await queryMarketContext(
|
|
1330
|
+
sql,
|
|
1331
|
+
[normalizedSymbol, normalizedIntervals, startMs, endMs],
|
|
1332
|
+
params
|
|
1333
|
+
);
|
|
1213
1334
|
const rowsByInterval = {};
|
|
1214
1335
|
for (const row of res.rows) {
|
|
1215
1336
|
const interval = row.interval;
|
|
@@ -2416,9 +2537,8 @@ var toMarketFeatureAge = (rowTs, atMs) => {
|
|
|
2416
2537
|
return Number.isFinite(ageMs) ? ageMs : null;
|
|
2417
2538
|
};
|
|
2418
2539
|
async function getLatestMarketTradeFlow(params) {
|
|
2419
|
-
await
|
|
2420
|
-
const
|
|
2421
|
-
const res = await pool.query(
|
|
2540
|
+
await prepareMarketContextSchemaForRead("binance");
|
|
2541
|
+
const res = await queryMarketContext(
|
|
2422
2542
|
`
|
|
2423
2543
|
SELECT
|
|
2424
2544
|
symbol,
|
|
@@ -2440,7 +2560,8 @@ async function getLatestMarketTradeFlow(params) {
|
|
|
2440
2560
|
ORDER BY ts DESC
|
|
2441
2561
|
LIMIT 1
|
|
2442
2562
|
`,
|
|
2443
|
-
[params.symbol.toUpperCase(), params.interval, params.atMs]
|
|
2563
|
+
[params.symbol.toUpperCase(), params.interval, params.atMs],
|
|
2564
|
+
params
|
|
2444
2565
|
);
|
|
2445
2566
|
const row = res.rows[0];
|
|
2446
2567
|
if (!row) return null;
|
|
@@ -2691,8 +2812,8 @@ async function upsertHyperliquidWhaleCoverageRows(rows) {
|
|
|
2691
2812
|
);
|
|
2692
2813
|
}
|
|
2693
2814
|
async function getHyperliquidWhaleCoverageSeriesRows(params) {
|
|
2694
|
-
await
|
|
2695
|
-
const result = await
|
|
2815
|
+
await prepareMarketContextSchemaForRead("hyperliquidWhales");
|
|
2816
|
+
const result = await queryMarketContext(
|
|
2696
2817
|
`
|
|
2697
2818
|
SELECT
|
|
2698
2819
|
ts,
|
|
@@ -2713,7 +2834,8 @@ async function getHyperliquidWhaleCoverageSeriesRows(params) {
|
|
|
2713
2834
|
HYPERLIQUID_WHALE_DATA_MODEL_VERSION,
|
|
2714
2835
|
params.fromMs,
|
|
2715
2836
|
params.toMs
|
|
2716
|
-
]
|
|
2837
|
+
],
|
|
2838
|
+
params
|
|
2717
2839
|
);
|
|
2718
2840
|
return result.rows.map((row) => ({
|
|
2719
2841
|
ts: new Date(row.ts),
|
|
@@ -2723,8 +2845,8 @@ async function getHyperliquidWhaleCoverageSeriesRows(params) {
|
|
|
2723
2845
|
}));
|
|
2724
2846
|
}
|
|
2725
2847
|
async function getHyperliquidWhaleFlowSeriesRows(params) {
|
|
2726
|
-
await
|
|
2727
|
-
const result = await
|
|
2848
|
+
await prepareMarketContextSchemaForRead("hyperliquidWhales");
|
|
2849
|
+
const result = await queryMarketContext(
|
|
2728
2850
|
`
|
|
2729
2851
|
SELECT
|
|
2730
2852
|
ts,
|
|
@@ -2757,7 +2879,8 @@ async function getHyperliquidWhaleFlowSeriesRows(params) {
|
|
|
2757
2879
|
params.whaleRegistryFingerprint,
|
|
2758
2880
|
params.fromMs,
|
|
2759
2881
|
params.toMs
|
|
2760
|
-
]
|
|
2882
|
+
],
|
|
2883
|
+
params
|
|
2761
2884
|
);
|
|
2762
2885
|
return result.rows.map((row) => ({
|
|
2763
2886
|
ts: new Date(row.ts),
|
|
@@ -2778,10 +2901,10 @@ async function getHyperliquidWhaleFlowSeriesRows(params) {
|
|
|
2778
2901
|
}));
|
|
2779
2902
|
}
|
|
2780
2903
|
async function getHyperliquidWhaleFlowAggregate(params) {
|
|
2781
|
-
await
|
|
2904
|
+
await prepareMarketContextSchemaForRead("hyperliquidWhales");
|
|
2782
2905
|
const intervalMs = HYPERLIQUID_CONTEXT_INTERVAL_MS[params.interval];
|
|
2783
2906
|
const expectedBuckets = Math.ceil(intervalMs / 6e4);
|
|
2784
|
-
const res = await
|
|
2907
|
+
const res = await queryMarketContext(
|
|
2785
2908
|
`
|
|
2786
2909
|
WITH coverage_rows AS (
|
|
2787
2910
|
SELECT *
|
|
@@ -2896,7 +3019,8 @@ async function getHyperliquidWhaleFlowAggregate(params) {
|
|
|
2896
3019
|
params.decisionTimeMs,
|
|
2897
3020
|
intervalMs,
|
|
2898
3021
|
HYPERLIQUID_WHALE_DATA_MODEL_VERSION
|
|
2899
|
-
]
|
|
3022
|
+
],
|
|
3023
|
+
params
|
|
2900
3024
|
);
|
|
2901
3025
|
const row = res.rows[0];
|
|
2902
3026
|
if (!row?.as_of_ts || Number(row.coverage_buckets) !== expectedBuckets || Number(row.covered_whales) <= 0) {
|
|
@@ -2969,9 +3093,8 @@ async function hasHyperliquidWhaleBackfillCoverage(params) {
|
|
|
2969
3093
|
return Number(result.rows[0]?.buckets) === expectedBuckets && Number(result.rows[0]?.complete_buckets) === expectedBuckets;
|
|
2970
3094
|
}
|
|
2971
3095
|
async function getLatestMarketBreadth(params) {
|
|
2972
|
-
await
|
|
2973
|
-
const
|
|
2974
|
-
const res = await pool.query(
|
|
3096
|
+
await prepareMarketContextSchemaForRead("binance");
|
|
3097
|
+
const res = await queryMarketContext(
|
|
2975
3098
|
`
|
|
2976
3099
|
SELECT
|
|
2977
3100
|
universe,
|
|
@@ -3010,7 +3133,8 @@ async function getLatestMarketBreadth(params) {
|
|
|
3010
3133
|
ORDER BY ts DESC
|
|
3011
3134
|
LIMIT 1
|
|
3012
3135
|
`,
|
|
3013
|
-
[params.universe, params.interval, params.atMs]
|
|
3136
|
+
[params.universe, params.interval, params.atMs],
|
|
3137
|
+
params
|
|
3014
3138
|
);
|
|
3015
3139
|
const row = res.rows[0];
|
|
3016
3140
|
if (!row) return null;
|
|
@@ -3022,10 +3146,9 @@ async function getLatestMarketBreadth(params) {
|
|
|
3022
3146
|
};
|
|
3023
3147
|
}
|
|
3024
3148
|
async function getLatestMarketGlobalContext(params) {
|
|
3025
|
-
await
|
|
3026
|
-
const pool = getPool();
|
|
3149
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3027
3150
|
const source = params.source ?? "coinmarketcap_global";
|
|
3028
|
-
const res = await
|
|
3151
|
+
const res = await queryMarketContext(
|
|
3029
3152
|
`
|
|
3030
3153
|
SELECT
|
|
3031
3154
|
source,
|
|
@@ -3054,11 +3177,12 @@ async function getLatestMarketGlobalContext(params) {
|
|
|
3054
3177
|
ORDER BY ts DESC
|
|
3055
3178
|
LIMIT 1
|
|
3056
3179
|
`,
|
|
3057
|
-
[source, params.atMs]
|
|
3180
|
+
[source, params.atMs],
|
|
3181
|
+
params
|
|
3058
3182
|
);
|
|
3059
3183
|
const row = res.rows[0];
|
|
3060
3184
|
if (!row) return null;
|
|
3061
|
-
const previousRes = await
|
|
3185
|
+
const previousRes = await queryMarketContext(
|
|
3062
3186
|
`
|
|
3063
3187
|
SELECT
|
|
3064
3188
|
btc_dominance_pct AS "btcDominancePct",
|
|
@@ -3071,7 +3195,8 @@ async function getLatestMarketGlobalContext(params) {
|
|
|
3071
3195
|
ORDER BY ts DESC
|
|
3072
3196
|
LIMIT 1
|
|
3073
3197
|
`,
|
|
3074
|
-
[source, row.ts]
|
|
3198
|
+
[source, row.ts],
|
|
3199
|
+
params
|
|
3075
3200
|
);
|
|
3076
3201
|
const previousDominance = previousRes.rows[0]?.btcDominancePct == null ? null : Number(previousRes.rows[0].btcDominancePct);
|
|
3077
3202
|
const previousEthDominance = previousRes.rows[0]?.ethDominancePct == null ? null : Number(previousRes.rows[0].ethDominancePct);
|
|
@@ -3164,9 +3289,8 @@ async function getLatestMarketReferenceAssetContexts(params) {
|
|
|
3164
3289
|
];
|
|
3165
3290
|
const rows = /* @__PURE__ */ new Map();
|
|
3166
3291
|
if (!symbols.length) return rows;
|
|
3167
|
-
await
|
|
3168
|
-
const
|
|
3169
|
-
const res = await pool.query(
|
|
3292
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3293
|
+
const res = await queryMarketContext(
|
|
3170
3294
|
`
|
|
3171
3295
|
SELECT DISTINCT ON (symbol)
|
|
3172
3296
|
source,
|
|
@@ -3191,7 +3315,8 @@ async function getLatestMarketReferenceAssetContexts(params) {
|
|
|
3191
3315
|
END <= to_timestamp($4/1000.0)
|
|
3192
3316
|
ORDER BY symbol ASC, ts DESC
|
|
3193
3317
|
`,
|
|
3194
|
-
[source, symbols, interval, params.atMs]
|
|
3318
|
+
[source, symbols, interval, params.atMs],
|
|
3319
|
+
params
|
|
3195
3320
|
);
|
|
3196
3321
|
for (const row of res.rows) {
|
|
3197
3322
|
const ageMs = toMarketFeatureAge(row.ts, params.atMs);
|
|
@@ -3204,11 +3329,10 @@ async function getLatestMarketReferenceAssetContexts(params) {
|
|
|
3204
3329
|
return rows;
|
|
3205
3330
|
}
|
|
3206
3331
|
async function getLatestMarketCmcExchangeLiquidityContext(params) {
|
|
3207
|
-
await
|
|
3208
|
-
const pool = getPool();
|
|
3332
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3209
3333
|
const source = params.source ?? "coinmarketcap_exchange_liquidity";
|
|
3210
3334
|
const interval = params.interval ?? "1d";
|
|
3211
|
-
const res = await
|
|
3335
|
+
const res = await queryMarketContext(
|
|
3212
3336
|
`
|
|
3213
3337
|
SELECT
|
|
3214
3338
|
source,
|
|
@@ -3231,11 +3355,12 @@ async function getLatestMarketCmcExchangeLiquidityContext(params) {
|
|
|
3231
3355
|
ORDER BY ts DESC
|
|
3232
3356
|
LIMIT 1
|
|
3233
3357
|
`,
|
|
3234
|
-
[source, interval, params.atMs]
|
|
3358
|
+
[source, interval, params.atMs],
|
|
3359
|
+
params
|
|
3235
3360
|
);
|
|
3236
3361
|
const row = res.rows[0];
|
|
3237
3362
|
if (!row) return null;
|
|
3238
|
-
const previousRes = await
|
|
3363
|
+
const previousRes = await queryMarketContext(
|
|
3239
3364
|
`
|
|
3240
3365
|
SELECT total_volume_usd AS "totalVolumeUsd"
|
|
3241
3366
|
FROM market_cmc_exchange_liquidity_context
|
|
@@ -3245,7 +3370,8 @@ async function getLatestMarketCmcExchangeLiquidityContext(params) {
|
|
|
3245
3370
|
ORDER BY ts DESC
|
|
3246
3371
|
LIMIT 1
|
|
3247
3372
|
`,
|
|
3248
|
-
[source, interval, row.ts]
|
|
3373
|
+
[source, interval, row.ts],
|
|
3374
|
+
params
|
|
3249
3375
|
);
|
|
3250
3376
|
const currentTotal = row.totalVolumeUsd == null ? null : Number(row.totalVolumeUsd);
|
|
3251
3377
|
const previousTotal = previousRes.rows[0]?.totalVolumeUsd == null ? null : Number(previousRes.rows[0].totalVolumeUsd);
|
|
@@ -3269,9 +3395,8 @@ async function getLatestMarketCmcIndexContexts(params) {
|
|
|
3269
3395
|
];
|
|
3270
3396
|
const rows = /* @__PURE__ */ new Map();
|
|
3271
3397
|
if (!indexSlugs.length) return rows;
|
|
3272
|
-
await
|
|
3273
|
-
const
|
|
3274
|
-
const res = await pool.query(
|
|
3398
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3399
|
+
const res = await queryMarketContext(
|
|
3275
3400
|
`
|
|
3276
3401
|
SELECT DISTINCT ON (index_slug)
|
|
3277
3402
|
source,
|
|
@@ -3294,10 +3419,11 @@ async function getLatestMarketCmcIndexContexts(params) {
|
|
|
3294
3419
|
END <= to_timestamp($4/1000.0)
|
|
3295
3420
|
ORDER BY index_slug ASC, ts DESC
|
|
3296
3421
|
`,
|
|
3297
|
-
[source, indexSlugs, interval, params.atMs]
|
|
3422
|
+
[source, indexSlugs, interval, params.atMs],
|
|
3423
|
+
params
|
|
3298
3424
|
);
|
|
3299
3425
|
for (const row of res.rows) {
|
|
3300
|
-
const previousRes = await
|
|
3426
|
+
const previousRes = await queryMarketContext(
|
|
3301
3427
|
`
|
|
3302
3428
|
SELECT value
|
|
3303
3429
|
FROM market_cmc_index_context
|
|
@@ -3308,7 +3434,8 @@ async function getLatestMarketCmcIndexContexts(params) {
|
|
|
3308
3434
|
ORDER BY ts DESC
|
|
3309
3435
|
LIMIT 1
|
|
3310
3436
|
`,
|
|
3311
|
-
[source, row.indexSlug, interval, row.ts]
|
|
3437
|
+
[source, row.indexSlug, interval, row.ts],
|
|
3438
|
+
params
|
|
3312
3439
|
);
|
|
3313
3440
|
const currentValue = row.value == null ? null : Number(row.value);
|
|
3314
3441
|
const previousValue = previousRes.rows[0]?.value == null ? null : Number(previousRes.rows[0].value);
|
|
@@ -3323,11 +3450,10 @@ async function getLatestMarketCmcIndexContexts(params) {
|
|
|
3323
3450
|
return rows;
|
|
3324
3451
|
}
|
|
3325
3452
|
async function getLatestMarketCmcFearGreedContext(params) {
|
|
3326
|
-
await
|
|
3327
|
-
const pool = getPool();
|
|
3453
|
+
await prepareMarketContextSchemaForRead("coinmarketcap");
|
|
3328
3454
|
const source = params.source ?? "coinmarketcap_fear_greed";
|
|
3329
3455
|
const interval = params.interval ?? "1d";
|
|
3330
|
-
const res = await
|
|
3456
|
+
const res = await queryMarketContext(
|
|
3331
3457
|
`
|
|
3332
3458
|
SELECT
|
|
3333
3459
|
source,
|
|
@@ -3347,11 +3473,12 @@ async function getLatestMarketCmcFearGreedContext(params) {
|
|
|
3347
3473
|
ORDER BY ts DESC
|
|
3348
3474
|
LIMIT 1
|
|
3349
3475
|
`,
|
|
3350
|
-
[source, interval, params.atMs]
|
|
3476
|
+
[source, interval, params.atMs],
|
|
3477
|
+
params
|
|
3351
3478
|
);
|
|
3352
3479
|
const row = res.rows[0];
|
|
3353
3480
|
if (!row) return null;
|
|
3354
|
-
const previousRes = await
|
|
3481
|
+
const previousRes = await queryMarketContext(
|
|
3355
3482
|
`
|
|
3356
3483
|
SELECT
|
|
3357
3484
|
value::int AS value,
|
|
@@ -3363,9 +3490,10 @@ async function getLatestMarketCmcFearGreedContext(params) {
|
|
|
3363
3490
|
ORDER BY ts DESC
|
|
3364
3491
|
LIMIT 1
|
|
3365
3492
|
`,
|
|
3366
|
-
[source, interval, row.ts]
|
|
3493
|
+
[source, interval, row.ts],
|
|
3494
|
+
params
|
|
3367
3495
|
);
|
|
3368
|
-
const previous7dRes = await
|
|
3496
|
+
const previous7dRes = await queryMarketContext(
|
|
3369
3497
|
`
|
|
3370
3498
|
SELECT value::int AS value
|
|
3371
3499
|
FROM market_cmc_fear_greed_context
|
|
@@ -3375,7 +3503,8 @@ async function getLatestMarketCmcFearGreedContext(params) {
|
|
|
3375
3503
|
ORDER BY ts DESC
|
|
3376
3504
|
LIMIT 1
|
|
3377
3505
|
`,
|
|
3378
|
-
[source, interval, row.ts]
|
|
3506
|
+
[source, interval, row.ts],
|
|
3507
|
+
params
|
|
3379
3508
|
);
|
|
3380
3509
|
const previousValue = previousRes.rows[0]?.value == null ? null : Number(previousRes.rows[0].value);
|
|
3381
3510
|
const previous7dValue = previous7dRes.rows[0]?.value == null ? null : Number(previous7dRes.rows[0].value);
|
|
@@ -3861,7 +3990,13 @@ export {
|
|
|
3861
3990
|
applyDerivativesMetricCoverage,
|
|
3862
3991
|
cleanupDeprecatedMarketContext,
|
|
3863
3992
|
closeTimescalePool,
|
|
3993
|
+
configureTimescaleMarketContextSchemaMode,
|
|
3864
3994
|
deleteCandles,
|
|
3995
|
+
ensureBinanceMarketSchema,
|
|
3996
|
+
ensureCoinMarketCapContextSchema,
|
|
3997
|
+
ensureDerivativesSchema,
|
|
3998
|
+
ensureHyperliquidWhaleSchema,
|
|
3999
|
+
ensureMarketContextSchemas,
|
|
3865
4000
|
findContinuityGap,
|
|
3866
4001
|
getCandlesRange,
|
|
3867
4002
|
getDataEdges,
|
package/dist/tradingAccounts.js
CHANGED
|
@@ -351,6 +351,8 @@ var redisKeys = {
|
|
|
351
351
|
runtimeTrade: (userName, orderId) => `users:${userName}:runtime:trade-records:${orderId}`,
|
|
352
352
|
runtimeTradeBuckets: (userName) => `users:${userName}:runtime:trade-records:days:`,
|
|
353
353
|
runtimeTradeBucket: (userName, dayKey) => `users:${userName}:runtime:trade-records:days:${dayKey}`,
|
|
354
|
+
runtimeClosedTradeBuckets: (userName) => `users:${userName}:runtime:closed-trade-records:days:`,
|
|
355
|
+
runtimeClosedTradeBucket: (userName, dayKey) => `users:${userName}:runtime:closed-trade-records:days:${dayKey}`,
|
|
354
356
|
runtimeActiveTrades: (userName) => `users:${userName}:runtime:active-trades:`,
|
|
355
357
|
runtimeActiveTrade: (userName, symbol, scopeId) => scopeId ? `users:${userName}:runtime:active-trades:${scopeId}:${symbol}` : `users:${userName}:runtime:active-trades:${symbol}`,
|
|
356
358
|
aiChatHistory: (userName, symbolKey) => `users:${userName}:ai:chats:${symbolKey}`,
|
package/dist/tradingAccounts.mjs
CHANGED
package/dist/userSettings.js
CHANGED
|
@@ -583,6 +583,8 @@ var redisKeys = {
|
|
|
583
583
|
runtimeTrade: (userName, orderId) => `users:${userName}:runtime:trade-records:${orderId}`,
|
|
584
584
|
runtimeTradeBuckets: (userName) => `users:${userName}:runtime:trade-records:days:`,
|
|
585
585
|
runtimeTradeBucket: (userName, dayKey) => `users:${userName}:runtime:trade-records:days:${dayKey}`,
|
|
586
|
+
runtimeClosedTradeBuckets: (userName) => `users:${userName}:runtime:closed-trade-records:days:`,
|
|
587
|
+
runtimeClosedTradeBucket: (userName, dayKey) => `users:${userName}:runtime:closed-trade-records:days:${dayKey}`,
|
|
586
588
|
runtimeActiveTrades: (userName) => `users:${userName}:runtime:active-trades:`,
|
|
587
589
|
runtimeActiveTrade: (userName, symbol, scopeId) => scopeId ? `users:${userName}:runtime:active-trades:${scopeId}:${symbol}` : `users:${userName}:runtime:active-trades:${symbol}`,
|
|
588
590
|
aiChatHistory: (userName, symbolKey) => `users:${userName}:ai:chats:${symbolKey}`,
|
package/dist/userSettings.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/infra",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.16",
|
|
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.14.4",
|
|
95
95
|
"@grpc/proto-loader": "^0.8.1",
|
|
96
|
-
"@tradejs/types": "^2.0.
|
|
96
|
+
"@tradejs/types": "^2.0.16",
|
|
97
97
|
"chalk": "4.1.2",
|
|
98
98
|
"ioredis": "5.11.1",
|
|
99
99
|
"pg": "8.22.0",
|