@deeptick/client 0.1.1 → 0.2.0

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/README.md CHANGED
@@ -1,225 +1,19 @@
1
1
  # DeepTick TypeScript SDK
2
2
 
3
- > `npm install @deeptick/client`
3
+ ```ts
4
+ import { CachedClient } from "@deeptick/client";
4
5
 
5
- The TypeScript SDK provides three layers of access to DeepTick market data:
6
-
7
- 1. **CachedClient** — Download daily Parquet/CSV archives with local disk caching
8
- 2. **DeepTickStream** — Real-time WebSocket streaming with typed callbacks
9
- 3. **DeepTickFeed** — Unified live/replay feed (backtest code = production code)
10
- 4. **Types & Derive** — Full type definitions and client-side derived computations
11
-
12
- ## Quick Start
13
-
14
- ```typescript
15
- import { CachedClient } from '@deeptick/client/cache';
16
-
17
- const client = new CachedClient("https://api.deeptick.com");
18
-
19
- // Load BTC trades for a date range (cached after first download)
20
- const batches = await client.loadTrades(
21
- "binance_futures",
22
- "BTCUSDT",
23
- "2026-05-01",
24
- "2026-05-02"
25
- );
26
- console.log(`Loaded ${batches.length} daily files.`);
27
- console.log(client.getStats());
28
- ```
29
-
30
- ## Streaming (Real-Time)
31
-
32
- ```typescript
33
- import { DeepTickStream } from '@deeptick/client/streaming';
34
-
35
- const stream = new DeepTickStream({
36
- url: "wss://api.deeptick.com/v1/stream?api_key=dtk_your_key"
37
- });
38
-
39
- // Typed callbacks for each data type
40
- stream.onTrade((exchange, symbol, trade) => {
41
- console.log(`[${exchange}] ${symbol}: ${trade.price} x ${trade.amount}`);
42
- });
43
-
44
- stream.onBookTicker((exchange, symbol, ticker) => {
45
- console.log(`[${exchange}] ${symbol}: ${ticker.bid_price}/${ticker.ask_price}`);
46
- });
47
-
48
- stream.onDerivativeTicker((exchange, symbol, data) => {
49
- console.log(`[${exchange}] ${symbol} funding: ${data.funding_rate}`);
50
- });
51
-
52
- // Connect and subscribe
53
- await stream.connect();
54
- await stream.subscribe([
55
- "binance_futures.trades.BTCUSDT",
56
- "*.book_ticker.*",
57
- "*.derivative_ticker.*",
58
- ]);
59
-
60
- // Measure latency
61
- const latency = await stream.ping();
62
- console.log(`Round-trip: ${latency}ms`);
63
- ```
64
-
65
- ### Global Callback
66
-
67
- ```typescript
68
- stream.onData((exchange, symbol, data) => {
69
- // Receives ALL data types
70
- console.log(exchange, symbol, data);
71
- });
72
- ```
73
-
74
- ## Replay (Historical Tick-by-Tick)
75
-
76
- ```typescript
77
- import { DeepTickFeed } from '@deeptick/client/feed';
78
-
79
- const feed = DeepTickFeed.replay(
80
- "wss://api.deeptick.com/v1/replay/ws",
81
- {
82
- apiKey: "dtk_your_key",
83
- sources: [
84
- "binance_futures:trades:BTCUSDT",
85
- "binance_futures:book_l2_delta:BTCUSDT",
86
- ],
87
- from: "2026-05-01",
88
- to: "2026-05-02",
89
- speed: 0, // max speed
90
- }
91
- );
92
-
93
- feed.onData((topic, data) => console.log(topic, data));
94
- feed.onReplayEnd((stats) => {
95
- console.log(`Replay complete: ${stats.totalEvents} events in ${stats.durationS}s`);
96
- });
97
-
98
- await feed.connect();
6
+ const client = new CachedClient("dtk_your_key", "https://deeptick.dev");
7
+ const trades = await client.loadTrades("lighter", "BTC-USD", "2026-07-08", "2026-07-08");
99
8
  ```
100
9
 
101
- ### Auto Mode (Replay Live)
10
+ `loadTrades` returns daily Parquet payloads as `Uint8Array` values. Use an Arrow
11
+ or Parquet reader of your choice to decode them.
102
12
 
103
- ```typescript
104
- const feed = DeepTickFeed.auto(
105
- "wss://api.deeptick.com",
106
- {
107
- apiKey: "dtk_your_key",
108
- sources: ["hyperliquid:trades:BTC"],
109
- from: "2026-05-01", // replay from here, then switch to live
110
- }
111
- );
13
+ Surface:
112
14
 
113
- feed.onData((topic, data) => process(data)); // same handler!
114
- feed.onModeChange((from, to) => {
115
- console.log(`Switched from ${from} to ${to}`);
116
- });
117
-
118
- await feed.connect();
119
- ```
120
-
121
- ## Derived Data (Computed On-the-Fly)
122
-
123
- ```typescript
124
- import { CachedClient } from '@deeptick/client/cache';
125
- import { derive, unpackLevels } from '@deeptick/client/types';
126
- import type {
127
- TradeRecord,
128
- BookDeltaRecord,
129
- BBORecord,
130
- CandleRecord,
131
- BookSnapshot,
132
- ImbalanceRecord,
133
- VolumeProfileBucket,
134
- } from '@deeptick/client/types';
135
-
136
- const client = new CachedClient("https://api.deeptick.com");
137
-
138
- // ── BBO from L2 deltas ──────────────────────────────────────────────
139
- const deltas = await client.loadBookDeltas("binance_futures", "BTCUSDT", "2026-05-01");
140
- const bbo: BBORecord[] = derive.bbo(deltas);
141
- console.log(`BBO rows: ${bbo.length}`);
142
-
143
- // ── Candles at any interval ─────────────────────────────────────────
144
- const trades = await client.loadTrades("binance_futures", "BTCUSDT", "2026-05-01");
145
- const candles1m: CandleRecord[] = derive.candles(trades, { intervalMs: 60_000 });
146
- const candles5m: CandleRecord[] = derive.candles(trades, { intervalMs: 300_000 });
147
-
148
- // ── Book snapshots (20 levels every 1 min) ──────────────────────────
149
- const snapshots: BookSnapshot[] = derive.bookSnapshots(deltas, {
150
- depth: 20,
151
- intervalMs: 60_000,
152
- });
153
-
154
- // ── Volume profile ──────────────────────────────────────────────────
155
- const profile: VolumeProfileBucket[] = derive.volumeProfile(trades, {
156
- numBuckets: 100,
157
- });
158
-
159
- // ── Order book imbalance ────────────────────────────────────────────
160
- const imbalance: ImbalanceRecord[] = derive.bookImbalance(deltas, {
161
- depth: 5,
162
- intervalMs: 1000,
163
- });
164
-
165
- // ── Cross-exchange funding spread ───────────────────────────────────
166
- const hlFunding = await client.loadFunding("hyperliquid", "BTC", "2026-05-01");
167
- const bnFunding = await client.loadFunding("binance_futures", "BTCUSDT", "2026-05-01");
168
- const fundingCross = derive.fundingCross(
169
- { hyperliquid: hlFunding, binance_futures: bnFunding },
170
- { intervalMs: 3_600_000 }
171
- );
172
-
173
- // ── Cross-exchange basis ────────────────────────────────────────────
174
- const hlTrades = await client.loadTrades("hyperliquid", "BTC", "2026-05-01");
175
- const bnTrades = await client.loadTrades("binance_futures", "BTCUSDT", "2026-05-01");
176
- const basis = derive.crossExchangeBasis(
177
- { hyperliquid: hlTrades, binance_futures: bnTrades },
178
- { intervalMs: 1000 }
179
- );
180
-
181
- // ── Unpack binary book levels ───────────────────────────────────────
182
- const packed = new Uint8Array(/* from parquet column */);
183
- const levels: [number, number][] = unpackLevels(packed);
184
- // levels = [[price1, size1], [price2, size2], ...]
185
- ```
186
-
187
- ## Type Definitions
188
-
189
- ```typescript
190
- // Wire protocol types for streaming
191
- interface StreamTrade {
192
- exchange: string; symbol: string;
193
- timestamp: number; local_timestamp: number;
194
- trade_id: string; price: number; amount: number;
195
- side: 'buy' | 'sell';
196
- }
197
-
198
- interface StreamBookTicker {
199
- exchange: string; symbol: string;
200
- timestamp: number; local_timestamp: number;
201
- bid_price: number; bid_amount: number;
202
- ask_price: number; ask_amount: number;
203
- }
204
-
205
- interface StreamDerivativeTicker {
206
- exchange: string; symbol: string;
207
- timestamp: number; local_timestamp: number;
208
- funding_rate: number | null;
209
- predicted_funding_rate: number | null;
210
- open_interest: number | null;
211
- last_price: number | null;
212
- mark_price: number | null;
213
- index_price: number | null;
214
- }
215
- ```
216
-
217
- ## Architecture
218
-
219
- ```
220
- client-ts/src/
221
- ├── types.ts # Type definitions + derive namespace (BBO, candles, snapshots)
222
- ├── cache.ts # CachedClient — HTTP download + disk cache
223
- ├── streaming.ts # DeepTickStream — real-time WebSocket (Node + Browser)
224
- └── feed.ts # DeepTickFeed — unified live/replay feed
225
- ```
15
+ - `new DeepTickClient(apiKey, baseUrl)`
16
+ - `loadTrades(exchange, symbol, start, end)` and `load_trades(...)`
17
+ - `download(exchange, dataType, symbol, date, dest?)`
18
+ - `entitlements()` and `catalog(exchange?)`
19
+ - `CachedClient` adds local Parquet payload caching under `~/.deeptick/cache`
package/dist/index.d.ts CHANGED
@@ -1,24 +1,59 @@
1
- /**
2
- * @deeptick/client TypeScript SDK for DeepTick market data
3
- *
4
- * Three layers:
5
- * 1. CachedClient — Download + cache daily archives
6
- * 2. DeepTickStream — Real-time WebSocket streaming
7
- * 3. DeepTickFeed — Unified live/replay feed
8
- * 4. derive — Client-side derived computations
9
- *
10
- * Usage:
11
- * import { DeepTickStream } from '@deeptick/client';
12
- * import { CachedClient } from '@deeptick/client/cache';
13
- * import { DeepTickFeed } from '@deeptick/client/feed';
14
- * import { derive } from '@deeptick/client/types';
15
- */
16
- export { DeepTickStream } from './streaming.js';
17
- export type { StreamFrame, StreamTrade, StreamBookTicker, StreamBookDelta, StreamDerivativeTicker, DataCallback, DeepTickStreamOptions, } from './streaming.js';
18
- export { DeepTickFeed, FeedMode } from './feed.js';
19
- export type { FeedOptions, FeedStats } from './feed.js';
20
- export { CachedClient } from './cache.js';
21
- export type { CacheStats } from './cache.js';
22
- export { derive, unpackLevels } from './types.js';
23
- export type { TradeRecord, BookDeltaRecord, BBORecord, CandleRecord, BookSnapshot, VolumeProfileBucket, ImbalanceRecord, FundingCrossRecord, } from './types.js';
1
+ export declare const DEFAULT_BASE_URL = "https://deeptick.dev";
2
+ export type DataFormat = "parquet" | "csv";
3
+ export type JsonObject = Record<string, unknown>;
4
+ export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
5
+ export interface ClientOptions {
6
+ fetch?: FetchLike;
7
+ timeoutMs?: number;
8
+ }
9
+ export interface DownloadOptions {
10
+ columns?: string[];
11
+ format?: DataFormat;
12
+ }
13
+ export interface CacheStats {
14
+ cacheDir: string;
15
+ cacheHits: number;
16
+ cacheMisses: number;
17
+ hitRatePct: number;
18
+ bytesDownloaded: number;
19
+ bytesFromCache: number;
20
+ }
21
+ export interface CachedClientOptions extends ClientOptions {
22
+ cacheDir?: string;
23
+ maxConcurrency?: number;
24
+ }
25
+ export declare class DeepTickError extends Error {
26
+ readonly status: number;
27
+ constructor(status: number, message: string);
28
+ }
29
+ export declare class DeepTickClient {
30
+ readonly apiKey: string;
31
+ readonly baseUrl: string;
32
+ protected readonly fetchImpl: FetchLike;
33
+ protected readonly timeoutMs: number;
34
+ constructor(apiKey?: string, baseUrl?: string, options?: ClientOptions);
35
+ entitlements(): Promise<JsonObject>;
36
+ catalog(exchange?: string): Promise<JsonObject>;
37
+ download(exchange: string, dataType: string, symbol: string, date: string | Date, dest?: string, options?: DownloadOptions): Promise<Uint8Array>;
38
+ loadTrades(exchange: string, symbol: string, start: string | Date, end?: string | Date, options?: DownloadOptions): Promise<Uint8Array[]>;
39
+ load_trades(exchange: string, symbol: string, start: string | Date, end?: string | Date, options?: DownloadOptions): Promise<Uint8Array[]>;
40
+ load(dataType: string, exchange: string, symbol: string, start: string | Date, end?: string | Date, options?: DownloadOptions): Promise<Uint8Array[]>;
41
+ protected json(path: string, params?: Record<string, string>): Promise<JsonObject>;
42
+ protected bytes(path: string, params?: Record<string, string>): Promise<Uint8Array>;
43
+ protected request(path: string, params?: Record<string, string>): Promise<Response>;
44
+ protected headers(): HeadersInit;
45
+ }
46
+ export declare class CachedClient extends DeepTickClient {
47
+ readonly cacheDir: string;
48
+ readonly maxConcurrency: number;
49
+ cacheHits: number;
50
+ cacheMisses: number;
51
+ bytesDownloaded: number;
52
+ bytesFromCache: number;
53
+ constructor(apiKey?: string, baseUrl?: string, options?: CachedClientOptions);
54
+ load(dataType: string, exchange: string, symbol: string, start: string | Date, end?: string | Date, options?: DownloadOptions): Promise<Uint8Array[]>;
55
+ getStats(): CacheStats;
56
+ clearCache(): Promise<void>;
57
+ private downloadCached;
58
+ }
24
59
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EACV,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,YAAY,EACZ,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EACV,WAAW,EACX,eAAe,EACf,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gBAAgB,yBAAyB,CAAC;AAGvD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,KAAK,CAAC;AAC3C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACjD,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjF,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK5C;AAED,qBAAa,cAAc;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IACxC,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAGnC,MAAM,GAAE,MAA2C,EACnD,OAAO,GAAE,MAAyB,EAClC,OAAO,GAAE,aAAkB;IAQvB,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC;IAInC,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAK/C,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,UAAU,CAAC;IAYhB,UAAU,CACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,UAAU,EAAE,CAAC;IAIlB,WAAW,CACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,UAAU,EAAE,CAAC;IAIlB,IAAI,CACR,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,UAAU,EAAE,CAAC;cAeR,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;cAYxE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;cAQzE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;IAazF,SAAS,CAAC,OAAO,IAAI,WAAW;CAOjC;AAED,qBAAa,YAAa,SAAQ,cAAc;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC,SAAS,SAAK;IACd,WAAW,SAAK;IAChB,eAAe,SAAK;IACpB,cAAc,SAAK;gBAGjB,MAAM,GAAE,MAA2C,EACnD,OAAO,GAAE,MAAyB,EAClC,OAAO,GAAE,mBAAwB;IAWpB,IAAI,CACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,UAAU,EAAE,CAAC;IA0BxB,QAAQ,IAAI,UAAU;IAYhB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAKnB,cAAc;CAuB7B"}
package/dist/index.js CHANGED
@@ -1,21 +1,251 @@
1
- /**
2
- * @deeptick/client TypeScript SDK for DeepTick market data
3
- *
4
- * Three layers:
5
- * 1. CachedClient — Download + cache daily archives
6
- * 2. DeepTickStream — Real-time WebSocket streaming
7
- * 3. DeepTickFeed — Unified live/replay feed
8
- * 4. derive — Client-side derived computations
9
- *
10
- * Usage:
11
- * import { DeepTickStream } from '@deeptick/client';
12
- * import { CachedClient } from '@deeptick/client/cache';
13
- * import { DeepTickFeed } from '@deeptick/client/feed';
14
- * import { derive } from '@deeptick/client/types';
15
- */
16
- // Re-export everything
17
- export { DeepTickStream } from './streaming.js';
18
- export { DeepTickFeed, FeedMode } from './feed.js';
19
- export { CachedClient } from './cache.js';
20
- export { derive, unpackLevels } from './types.js';
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ export const DEFAULT_BASE_URL = "https://deeptick.dev";
6
+ const USER_AGENT = "deeptick-typescript/0.1.0";
7
+ export class DeepTickError extends Error {
8
+ constructor(status, message) {
9
+ super(`DeepTick API returned HTTP ${status}: ${message}`);
10
+ this.name = "DeepTickError";
11
+ this.status = status;
12
+ }
13
+ }
14
+ export class DeepTickClient {
15
+ constructor(apiKey = process.env.DEEPTICK_API_KEY ?? "", baseUrl = DEFAULT_BASE_URL, options = {}) {
16
+ this.apiKey = apiKey;
17
+ this.baseUrl = normalizeBaseUrl(baseUrl);
18
+ this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);
19
+ this.timeoutMs = options.timeoutMs ?? 120_000;
20
+ }
21
+ async entitlements() {
22
+ return this.json("/v1/entitlements");
23
+ }
24
+ async catalog(exchange) {
25
+ const params = exchange ? { exchange } : undefined;
26
+ return this.json("/v1/catalog", params);
27
+ }
28
+ async download(exchange, dataType, symbol, date, dest, options = {}) {
29
+ const body = await this.bytes(dataPath(exchange, dataType, symbol, date), dataParams(options));
30
+ if (dest) {
31
+ await mkdir(dirname(dest), { recursive: true });
32
+ await writeFile(dest, body);
33
+ }
34
+ return body;
35
+ }
36
+ async loadTrades(exchange, symbol, start, end, options = {}) {
37
+ return this.load("trades", exchange, symbol, start, end, options);
38
+ }
39
+ async load_trades(exchange, symbol, start, end, options = {}) {
40
+ return this.loadTrades(exchange, symbol, start, end, options);
41
+ }
42
+ async load(dataType, exchange, symbol, start, end, options = {}) {
43
+ const out = [];
44
+ for (const day of dateRange(start, end)) {
45
+ try {
46
+ out.push(await this.download(exchange, dataType, symbol, day, undefined, options));
47
+ }
48
+ catch (error) {
49
+ if (error instanceof DeepTickError && error.status === 404) {
50
+ continue;
51
+ }
52
+ throw error;
53
+ }
54
+ }
55
+ return out;
56
+ }
57
+ async json(path, params) {
58
+ const response = await this.request(path, params);
59
+ if (!response.ok) {
60
+ throw await toDeepTickError(response);
61
+ }
62
+ const value = (await response.json());
63
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
64
+ throw new Error(`Expected object response from ${path}`);
65
+ }
66
+ return value;
67
+ }
68
+ async bytes(path, params) {
69
+ const response = await this.request(path, params);
70
+ if (!response.ok) {
71
+ throw await toDeepTickError(response);
72
+ }
73
+ return Buffer.from(await response.arrayBuffer());
74
+ }
75
+ async request(path, params) {
76
+ const controller = new AbortController();
77
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
78
+ try {
79
+ return await this.fetchImpl(urlWithParams(`${this.baseUrl}${path}`, params), {
80
+ headers: this.headers(),
81
+ signal: controller.signal,
82
+ });
83
+ }
84
+ finally {
85
+ clearTimeout(timeout);
86
+ }
87
+ }
88
+ headers() {
89
+ const headers = { "User-Agent": USER_AGENT };
90
+ if (this.apiKey) {
91
+ headers["X-API-Key"] = this.apiKey;
92
+ }
93
+ return headers;
94
+ }
95
+ }
96
+ export class CachedClient extends DeepTickClient {
97
+ constructor(apiKey = process.env.DEEPTICK_API_KEY ?? "", baseUrl = DEFAULT_BASE_URL, options = {}) {
98
+ super(resolveCachedClientArgs(apiKey, baseUrl).apiKey, resolveCachedClientArgs(apiKey, baseUrl).baseUrl, options);
99
+ this.cacheHits = 0;
100
+ this.cacheMisses = 0;
101
+ this.bytesDownloaded = 0;
102
+ this.bytesFromCache = 0;
103
+ this.cacheDir = options.cacheDir ?? join(homedir(), ".deeptick", "cache");
104
+ this.maxConcurrency = options.maxConcurrency ?? 8;
105
+ }
106
+ async load(dataType, exchange, symbol, start, end, options = {}) {
107
+ const days = dateRange(start, end);
108
+ const results = [];
109
+ for (let offset = 0; offset < days.length; offset += this.maxConcurrency) {
110
+ const batch = days.slice(offset, offset + this.maxConcurrency);
111
+ const downloaded = await Promise.all(batch.map(async (day) => {
112
+ try {
113
+ return await this.downloadCached(exchange, dataType, symbol, day, options);
114
+ }
115
+ catch (error) {
116
+ if (error instanceof DeepTickError && error.status === 404) {
117
+ return undefined;
118
+ }
119
+ throw error;
120
+ }
121
+ }));
122
+ for (const item of downloaded) {
123
+ if (item) {
124
+ results.push(item);
125
+ }
126
+ }
127
+ }
128
+ return results;
129
+ }
130
+ getStats() {
131
+ const requests = this.cacheHits + this.cacheMisses;
132
+ return {
133
+ cacheDir: this.cacheDir,
134
+ cacheHits: this.cacheHits,
135
+ cacheMisses: this.cacheMisses,
136
+ hitRatePct: requests === 0 ? 0 : Math.round((this.cacheHits / requests) * 1000) / 10,
137
+ bytesDownloaded: this.bytesDownloaded,
138
+ bytesFromCache: this.bytesFromCache,
139
+ };
140
+ }
141
+ async clearCache() {
142
+ await rm(this.cacheDir, { recursive: true, force: true });
143
+ await mkdir(this.cacheDir, { recursive: true });
144
+ }
145
+ async downloadCached(exchange, dataType, symbol, date, options) {
146
+ const cacheFile = cachePath(this.cacheDir, exchange, dataType, symbol, date, options.columns);
147
+ try {
148
+ const cached = await readFile(cacheFile);
149
+ this.cacheHits += 1;
150
+ this.bytesFromCache += (await stat(cacheFile)).size;
151
+ return cached;
152
+ }
153
+ catch {
154
+ this.cacheMisses += 1;
155
+ }
156
+ const body = await this.download(exchange, dataType, symbol, date, undefined, options);
157
+ await mkdir(dirname(cacheFile), { recursive: true });
158
+ await writeFile(cacheFile, body);
159
+ this.bytesDownloaded += body.byteLength;
160
+ return body;
161
+ }
162
+ }
163
+ function normalizeBaseUrl(baseUrl) {
164
+ let value = (baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
165
+ if (value.endsWith("/v1")) {
166
+ value = value.slice(0, -3);
167
+ }
168
+ return value.replace(/\/+$/, "");
169
+ }
170
+ function looksLikeUrl(value) {
171
+ return value.startsWith("http://") || value.startsWith("https://");
172
+ }
173
+ function resolveCachedClientArgs(apiKey, baseUrl) {
174
+ if (looksLikeUrl(apiKey)) {
175
+ if (baseUrl === DEFAULT_BASE_URL) {
176
+ return { apiKey: process.env.DEEPTICK_API_KEY ?? "", baseUrl: apiKey };
177
+ }
178
+ return { apiKey: baseUrl, baseUrl: apiKey };
179
+ }
180
+ return { apiKey, baseUrl };
181
+ }
182
+ function dataPath(exchange, dataType, symbol, date) {
183
+ return [
184
+ "/v1/data",
185
+ encodeURIComponent(exchange),
186
+ encodeURIComponent(dataType),
187
+ encodeURIComponent(symbol),
188
+ encodeURIComponent(toDateString(date)),
189
+ ].join("/");
190
+ }
191
+ function dataParams(options) {
192
+ const params = { format: options.format ?? "parquet" };
193
+ if (options.columns && options.columns.length > 0) {
194
+ params.columns = options.columns.join(",");
195
+ }
196
+ return params;
197
+ }
198
+ function cachePath(cacheDir, exchange, dataType, symbol, date, columns) {
199
+ const safeSymbol = symbol.replace(/[/:]/g, "-");
200
+ const suffix = columns && columns.length > 0
201
+ ? `_${createHash("md5").update([...columns].sort().join(",")).digest("hex").slice(0, 8)}`
202
+ : "";
203
+ return join(cacheDir, exchange, dataType, safeSymbol, `${date}${suffix}.parquet`);
204
+ }
205
+ function dateRange(start, end) {
206
+ const first = asUtcDate(start);
207
+ const last = asUtcDate(end ?? start);
208
+ if (last.getTime() < first.getTime()) {
209
+ throw new Error("end date must be on or after start date");
210
+ }
211
+ const days = [];
212
+ const current = new Date(first);
213
+ while (current.getTime() <= last.getTime()) {
214
+ days.push(current.toISOString().slice(0, 10));
215
+ current.setUTCDate(current.getUTCDate() + 1);
216
+ }
217
+ return days;
218
+ }
219
+ function asUtcDate(value) {
220
+ if (value instanceof Date) {
221
+ return new Date(Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate()));
222
+ }
223
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
224
+ throw new Error(`expected date as YYYY-MM-DD, got ${value}`);
225
+ }
226
+ return new Date(`${value}T00:00:00.000Z`);
227
+ }
228
+ function toDateString(value) {
229
+ return asUtcDate(value).toISOString().slice(0, 10);
230
+ }
231
+ function urlWithParams(url, params) {
232
+ const out = new URL(url);
233
+ for (const [key, value] of Object.entries(params ?? {})) {
234
+ out.searchParams.set(key, value);
235
+ }
236
+ return out.toString();
237
+ }
238
+ async function toDeepTickError(response) {
239
+ let message = response.statusText;
240
+ try {
241
+ const text = await response.text();
242
+ if (text) {
243
+ message = text.slice(0, 500);
244
+ }
245
+ }
246
+ catch {
247
+ // Keep the status text if the body has already been consumed.
248
+ }
249
+ return new DeepTickError(response.status, message);
250
+ }
21
251
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,uBAAuB;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAWhD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGnD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}