oxarchive 0.4.1__tar.gz → 0.5.2__tar.gz
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.
- {oxarchive-0.4.1 → oxarchive-0.5.2}/PKG-INFO +199 -10
- {oxarchive-0.4.1 → oxarchive-0.5.2}/README.md +198 -9
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/__init__.py +9 -1
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/exchanges.py +16 -2
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/resources/__init__.py +6 -1
- oxarchive-0.5.2/oxarchive/resources/candles.py +121 -0
- oxarchive-0.5.2/oxarchive/resources/instruments.py +110 -0
- oxarchive-0.5.2/oxarchive/resources/liquidations.py +198 -0
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/resources/orderbook.py +18 -1
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/types.py +167 -3
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/websocket.py +42 -3
- {oxarchive-0.4.1 → oxarchive-0.5.2}/pyproject.toml +1 -1
- oxarchive-0.4.1/oxarchive/resources/instruments.py +0 -56
- {oxarchive-0.4.1 → oxarchive-0.5.2}/.gitignore +0 -0
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/client.py +0 -0
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/http.py +0 -0
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/resources/funding.py +0 -0
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/resources/openinterest.py +0 -0
- {oxarchive-0.4.1 → oxarchive-0.5.2}/oxarchive/resources/trades.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oxarchive
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Official Python SDK for 0xarchive - Hyperliquid Historical Data API
|
|
5
5
|
Project-URL: Homepage, https://0xarchive.io
|
|
6
6
|
Project-URL: Documentation, https://0xarchive.io/docs/sdks
|
|
@@ -153,6 +153,59 @@ orderbook = await client.hyperliquid.orderbook.aget("BTC")
|
|
|
153
153
|
history = await client.hyperliquid.orderbook.ahistory("BTC", start=..., end=...)
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
+
#### Orderbook Depth Limits
|
|
157
|
+
|
|
158
|
+
The `depth` parameter controls how many price levels are returned per side. Tier-based limits apply:
|
|
159
|
+
|
|
160
|
+
| Tier | Max Depth |
|
|
161
|
+
|------|-----------|
|
|
162
|
+
| Free | 20 |
|
|
163
|
+
| Build | 50 |
|
|
164
|
+
| Pro | 100 |
|
|
165
|
+
| Enterprise | Full Depth |
|
|
166
|
+
|
|
167
|
+
**Note:** Hyperliquid source data only contains 20 levels. Higher limits apply to Lighter.xyz data.
|
|
168
|
+
|
|
169
|
+
#### Lighter Orderbook Granularity
|
|
170
|
+
|
|
171
|
+
Lighter.xyz orderbook history supports a `granularity` parameter for different data resolutions. Tier restrictions apply.
|
|
172
|
+
|
|
173
|
+
| Granularity | Interval | Tier Required | Credit Multiplier |
|
|
174
|
+
|-------------|----------|---------------|-------------------|
|
|
175
|
+
| `checkpoint` | ~60s | Free+ | 1x |
|
|
176
|
+
| `30s` | 30s | Build+ | 2x |
|
|
177
|
+
| `10s` | 10s | Build+ | 3x |
|
|
178
|
+
| `1s` | 1s | Pro+ | 10x |
|
|
179
|
+
| `tick` | tick-level | Enterprise | 20x |
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
# Get Lighter orderbook history with 10s resolution (Build+ tier)
|
|
183
|
+
history = client.lighter.orderbook.history(
|
|
184
|
+
"BTC",
|
|
185
|
+
start="2024-01-01",
|
|
186
|
+
end="2024-01-02",
|
|
187
|
+
granularity="10s"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Get 1-second resolution (Pro+ tier)
|
|
191
|
+
history = client.lighter.orderbook.history(
|
|
192
|
+
"BTC",
|
|
193
|
+
start="2024-01-01",
|
|
194
|
+
end="2024-01-02",
|
|
195
|
+
granularity="1s"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# Tick-level data (Enterprise tier) - returns checkpoint + raw deltas
|
|
199
|
+
history = client.lighter.orderbook.history(
|
|
200
|
+
"BTC",
|
|
201
|
+
start="2024-01-01",
|
|
202
|
+
end="2024-01-02",
|
|
203
|
+
granularity="tick"
|
|
204
|
+
)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Note:** The `granularity` parameter is ignored for Hyperliquid orderbook history.
|
|
208
|
+
|
|
156
209
|
### Trades
|
|
157
210
|
|
|
158
211
|
The trades API uses cursor-based pagination for efficient retrieval of large datasets.
|
|
@@ -187,17 +240,47 @@ result = await client.hyperliquid.trades.alist("ETH", start=..., end=...)
|
|
|
187
240
|
### Instruments
|
|
188
241
|
|
|
189
242
|
```python
|
|
190
|
-
# List all trading instruments
|
|
243
|
+
# List all trading instruments (Hyperliquid)
|
|
191
244
|
instruments = client.hyperliquid.instruments.list()
|
|
192
245
|
|
|
193
246
|
# Get specific instrument details
|
|
194
247
|
btc = client.hyperliquid.instruments.get("BTC")
|
|
248
|
+
print(f"BTC size decimals: {btc.sz_decimals}")
|
|
195
249
|
|
|
196
250
|
# Async versions
|
|
197
251
|
instruments = await client.hyperliquid.instruments.alist()
|
|
198
252
|
btc = await client.hyperliquid.instruments.aget("BTC")
|
|
199
253
|
```
|
|
200
254
|
|
|
255
|
+
#### Lighter.xyz Instruments
|
|
256
|
+
|
|
257
|
+
Lighter instruments have a different schema with additional fields for fees, market IDs, and minimum order amounts:
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
# List Lighter instruments (returns LighterInstrument, not Instrument)
|
|
261
|
+
lighter_instruments = client.lighter.instruments.list()
|
|
262
|
+
|
|
263
|
+
# Get specific Lighter instrument
|
|
264
|
+
eth = client.lighter.instruments.get("ETH")
|
|
265
|
+
print(f"ETH taker fee: {eth.taker_fee}")
|
|
266
|
+
print(f"ETH maker fee: {eth.maker_fee}")
|
|
267
|
+
print(f"ETH market ID: {eth.market_id}")
|
|
268
|
+
print(f"ETH min base amount: {eth.min_base_amount}")
|
|
269
|
+
|
|
270
|
+
# Async versions
|
|
271
|
+
lighter_instruments = await client.lighter.instruments.alist()
|
|
272
|
+
eth = await client.lighter.instruments.aget("ETH")
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Key differences:**
|
|
276
|
+
| Field | Hyperliquid (`Instrument`) | Lighter (`LighterInstrument`) |
|
|
277
|
+
|-------|---------------------------|------------------------------|
|
|
278
|
+
| Symbol | `name` | `symbol` |
|
|
279
|
+
| Size decimals | `sz_decimals` | `size_decimals` |
|
|
280
|
+
| Fee info | Not available | `taker_fee`, `maker_fee`, `liquidation_fee` |
|
|
281
|
+
| Market ID | Not available | `market_id` |
|
|
282
|
+
| Min amounts | Not available | `min_base_amount`, `min_quote_amount` |
|
|
283
|
+
|
|
201
284
|
### Funding Rates
|
|
202
285
|
|
|
203
286
|
```python
|
|
@@ -234,6 +317,57 @@ current = await client.hyperliquid.open_interest.acurrent("BTC")
|
|
|
234
317
|
history = await client.hyperliquid.open_interest.ahistory("ETH", start=..., end=...)
|
|
235
318
|
```
|
|
236
319
|
|
|
320
|
+
### Candles (OHLCV)
|
|
321
|
+
|
|
322
|
+
Get historical OHLCV candle data aggregated from trades.
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
# Get candle history (start is required)
|
|
326
|
+
candles = client.hyperliquid.candles.history(
|
|
327
|
+
"BTC",
|
|
328
|
+
start="2024-01-01",
|
|
329
|
+
end="2024-01-02",
|
|
330
|
+
interval="1h", # 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w
|
|
331
|
+
limit=100
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
# Iterate through candles
|
|
335
|
+
for candle in candles.data:
|
|
336
|
+
print(f"{candle.timestamp}: O={candle.open} H={candle.high} L={candle.low} C={candle.close} V={candle.volume}")
|
|
337
|
+
|
|
338
|
+
# Cursor-based pagination for large datasets
|
|
339
|
+
result = client.hyperliquid.candles.history("BTC", start=..., end=..., interval="1m", limit=1000)
|
|
340
|
+
while result.next_cursor:
|
|
341
|
+
result = client.hyperliquid.candles.history(
|
|
342
|
+
"BTC", start=..., end=..., interval="1m",
|
|
343
|
+
cursor=result.next_cursor, limit=1000
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Lighter.xyz candles
|
|
347
|
+
lighter_candles = client.lighter.candles.history(
|
|
348
|
+
"BTC",
|
|
349
|
+
start="2024-01-01",
|
|
350
|
+
end="2024-01-02",
|
|
351
|
+
interval="15m"
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
# Async versions
|
|
355
|
+
candles = await client.hyperliquid.candles.ahistory("BTC", start=..., end=..., interval="1h")
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
#### Available Intervals
|
|
359
|
+
|
|
360
|
+
| Interval | Description |
|
|
361
|
+
|----------|-------------|
|
|
362
|
+
| `1m` | 1 minute |
|
|
363
|
+
| `5m` | 5 minutes |
|
|
364
|
+
| `15m` | 15 minutes |
|
|
365
|
+
| `30m` | 30 minutes |
|
|
366
|
+
| `1h` | 1 hour (default) |
|
|
367
|
+
| `4h` | 4 hours |
|
|
368
|
+
| `1d` | 1 day |
|
|
369
|
+
| `1w` | 1 week |
|
|
370
|
+
|
|
237
371
|
### Legacy API (Deprecated)
|
|
238
372
|
|
|
239
373
|
The following legacy methods are deprecated and will be removed in v2.0. They default to Hyperliquid data:
|
|
@@ -335,6 +469,19 @@ async def main():
|
|
|
335
469
|
speed=10 # Optional, defaults to 1x
|
|
336
470
|
)
|
|
337
471
|
|
|
472
|
+
# Lighter.xyz replay with granularity (tier restrictions apply)
|
|
473
|
+
await ws.replay(
|
|
474
|
+
"orderbook", "BTC",
|
|
475
|
+
start=int(time.time() * 1000) - 86400000,
|
|
476
|
+
speed=10,
|
|
477
|
+
granularity="10s" # Options: 'checkpoint', '30s', '10s', '1s', 'tick'
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
# Handle tick-level data (granularity='tick', Enterprise tier)
|
|
481
|
+
ws.on_historical_tick_data(lambda coin, checkpoint, deltas:
|
|
482
|
+
print(f"Checkpoint: {len(checkpoint['bids'])} bids, Deltas: {len(deltas)}")
|
|
483
|
+
)
|
|
484
|
+
|
|
338
485
|
# Control playback
|
|
339
486
|
await ws.replay_pause()
|
|
340
487
|
await ws.replay_resume()
|
|
@@ -380,6 +527,14 @@ async def main():
|
|
|
380
527
|
batch_size=1000 # Optional, defaults to 1000
|
|
381
528
|
)
|
|
382
529
|
|
|
530
|
+
# Lighter.xyz stream with granularity (tier restrictions apply)
|
|
531
|
+
await ws.stream(
|
|
532
|
+
"orderbook", "BTC",
|
|
533
|
+
start=int(time.time() * 1000) - 3600000,
|
|
534
|
+
end=int(time.time() * 1000),
|
|
535
|
+
granularity="10s" # Options: 'checkpoint', '30s', '10s', '1s', 'tick'
|
|
536
|
+
)
|
|
537
|
+
|
|
383
538
|
# Stop if needed
|
|
384
539
|
await ws.stream_stop()
|
|
385
540
|
|
|
@@ -401,12 +556,43 @@ ws = OxArchiveWs(WsOptions(
|
|
|
401
556
|
|
|
402
557
|
### Available Channels
|
|
403
558
|
|
|
404
|
-
| Channel | Description | Requires Coin |
|
|
405
|
-
|
|
406
|
-
| `orderbook` | L2 order book updates | Yes |
|
|
407
|
-
| `trades` | Trade/fill updates | Yes |
|
|
408
|
-
| `
|
|
409
|
-
| `
|
|
559
|
+
| Channel | Description | Requires Coin | Historical Support |
|
|
560
|
+
|---------|-------------|---------------|-------------------|
|
|
561
|
+
| `orderbook` | L2 order book updates | Yes | Yes |
|
|
562
|
+
| `trades` | Trade/fill updates | Yes | Yes |
|
|
563
|
+
| `candles` | OHLCV candle data | Yes | Yes (replay/stream only) |
|
|
564
|
+
| `ticker` | Price and 24h volume | Yes | Real-time only |
|
|
565
|
+
| `all_tickers` | All market tickers | No | Real-time only |
|
|
566
|
+
|
|
567
|
+
#### Candle Replay/Stream
|
|
568
|
+
|
|
569
|
+
```python
|
|
570
|
+
# Replay candles at 10x speed
|
|
571
|
+
await ws.replay(
|
|
572
|
+
"candles", "BTC",
|
|
573
|
+
start=int(time.time() * 1000) - 86400000,
|
|
574
|
+
end=int(time.time() * 1000),
|
|
575
|
+
speed=10,
|
|
576
|
+
interval="15m" # 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
# Bulk stream candles
|
|
580
|
+
await ws.stream(
|
|
581
|
+
"candles", "ETH",
|
|
582
|
+
start=int(time.time() * 1000) - 3600000,
|
|
583
|
+
end=int(time.time() * 1000),
|
|
584
|
+
batch_size=1000,
|
|
585
|
+
interval="1h"
|
|
586
|
+
)
|
|
587
|
+
|
|
588
|
+
# Lighter.xyz candles
|
|
589
|
+
await ws.replay(
|
|
590
|
+
"lighter_candles", "BTC",
|
|
591
|
+
start=...,
|
|
592
|
+
speed=10,
|
|
593
|
+
interval="5m"
|
|
594
|
+
)
|
|
595
|
+
```
|
|
410
596
|
|
|
411
597
|
## Timestamp Formats
|
|
412
598
|
|
|
@@ -449,8 +635,8 @@ except OxArchiveError as e:
|
|
|
449
635
|
Full type hint support with Pydantic models:
|
|
450
636
|
|
|
451
637
|
```python
|
|
452
|
-
from oxarchive import Client
|
|
453
|
-
from oxarchive.types import OrderBook, Trade, Instrument, FundingRate, OpenInterest
|
|
638
|
+
from oxarchive import Client, LighterGranularity
|
|
639
|
+
from oxarchive.types import OrderBook, Trade, Instrument, LighterInstrument, FundingRate, OpenInterest
|
|
454
640
|
from oxarchive.resources.trades import CursorResponse
|
|
455
641
|
|
|
456
642
|
client = Client(api_key="ox_your_api_key")
|
|
@@ -458,6 +644,9 @@ client = Client(api_key="ox_your_api_key")
|
|
|
458
644
|
orderbook: OrderBook = client.orderbook.get("BTC")
|
|
459
645
|
trades: list[Trade] = client.trades.recent("BTC")
|
|
460
646
|
result: CursorResponse = client.trades.list("BTC", start=..., end=...)
|
|
647
|
+
|
|
648
|
+
# Lighter granularity type hint
|
|
649
|
+
granularity: LighterGranularity = "10s"
|
|
461
650
|
```
|
|
462
651
|
|
|
463
652
|
## Requirements
|
|
@@ -116,6 +116,59 @@ orderbook = await client.hyperliquid.orderbook.aget("BTC")
|
|
|
116
116
|
history = await client.hyperliquid.orderbook.ahistory("BTC", start=..., end=...)
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
#### Orderbook Depth Limits
|
|
120
|
+
|
|
121
|
+
The `depth` parameter controls how many price levels are returned per side. Tier-based limits apply:
|
|
122
|
+
|
|
123
|
+
| Tier | Max Depth |
|
|
124
|
+
|------|-----------|
|
|
125
|
+
| Free | 20 |
|
|
126
|
+
| Build | 50 |
|
|
127
|
+
| Pro | 100 |
|
|
128
|
+
| Enterprise | Full Depth |
|
|
129
|
+
|
|
130
|
+
**Note:** Hyperliquid source data only contains 20 levels. Higher limits apply to Lighter.xyz data.
|
|
131
|
+
|
|
132
|
+
#### Lighter Orderbook Granularity
|
|
133
|
+
|
|
134
|
+
Lighter.xyz orderbook history supports a `granularity` parameter for different data resolutions. Tier restrictions apply.
|
|
135
|
+
|
|
136
|
+
| Granularity | Interval | Tier Required | Credit Multiplier |
|
|
137
|
+
|-------------|----------|---------------|-------------------|
|
|
138
|
+
| `checkpoint` | ~60s | Free+ | 1x |
|
|
139
|
+
| `30s` | 30s | Build+ | 2x |
|
|
140
|
+
| `10s` | 10s | Build+ | 3x |
|
|
141
|
+
| `1s` | 1s | Pro+ | 10x |
|
|
142
|
+
| `tick` | tick-level | Enterprise | 20x |
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# Get Lighter orderbook history with 10s resolution (Build+ tier)
|
|
146
|
+
history = client.lighter.orderbook.history(
|
|
147
|
+
"BTC",
|
|
148
|
+
start="2024-01-01",
|
|
149
|
+
end="2024-01-02",
|
|
150
|
+
granularity="10s"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# Get 1-second resolution (Pro+ tier)
|
|
154
|
+
history = client.lighter.orderbook.history(
|
|
155
|
+
"BTC",
|
|
156
|
+
start="2024-01-01",
|
|
157
|
+
end="2024-01-02",
|
|
158
|
+
granularity="1s"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Tick-level data (Enterprise tier) - returns checkpoint + raw deltas
|
|
162
|
+
history = client.lighter.orderbook.history(
|
|
163
|
+
"BTC",
|
|
164
|
+
start="2024-01-01",
|
|
165
|
+
end="2024-01-02",
|
|
166
|
+
granularity="tick"
|
|
167
|
+
)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Note:** The `granularity` parameter is ignored for Hyperliquid orderbook history.
|
|
171
|
+
|
|
119
172
|
### Trades
|
|
120
173
|
|
|
121
174
|
The trades API uses cursor-based pagination for efficient retrieval of large datasets.
|
|
@@ -150,17 +203,47 @@ result = await client.hyperliquid.trades.alist("ETH", start=..., end=...)
|
|
|
150
203
|
### Instruments
|
|
151
204
|
|
|
152
205
|
```python
|
|
153
|
-
# List all trading instruments
|
|
206
|
+
# List all trading instruments (Hyperliquid)
|
|
154
207
|
instruments = client.hyperliquid.instruments.list()
|
|
155
208
|
|
|
156
209
|
# Get specific instrument details
|
|
157
210
|
btc = client.hyperliquid.instruments.get("BTC")
|
|
211
|
+
print(f"BTC size decimals: {btc.sz_decimals}")
|
|
158
212
|
|
|
159
213
|
# Async versions
|
|
160
214
|
instruments = await client.hyperliquid.instruments.alist()
|
|
161
215
|
btc = await client.hyperliquid.instruments.aget("BTC")
|
|
162
216
|
```
|
|
163
217
|
|
|
218
|
+
#### Lighter.xyz Instruments
|
|
219
|
+
|
|
220
|
+
Lighter instruments have a different schema with additional fields for fees, market IDs, and minimum order amounts:
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
# List Lighter instruments (returns LighterInstrument, not Instrument)
|
|
224
|
+
lighter_instruments = client.lighter.instruments.list()
|
|
225
|
+
|
|
226
|
+
# Get specific Lighter instrument
|
|
227
|
+
eth = client.lighter.instruments.get("ETH")
|
|
228
|
+
print(f"ETH taker fee: {eth.taker_fee}")
|
|
229
|
+
print(f"ETH maker fee: {eth.maker_fee}")
|
|
230
|
+
print(f"ETH market ID: {eth.market_id}")
|
|
231
|
+
print(f"ETH min base amount: {eth.min_base_amount}")
|
|
232
|
+
|
|
233
|
+
# Async versions
|
|
234
|
+
lighter_instruments = await client.lighter.instruments.alist()
|
|
235
|
+
eth = await client.lighter.instruments.aget("ETH")
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Key differences:**
|
|
239
|
+
| Field | Hyperliquid (`Instrument`) | Lighter (`LighterInstrument`) |
|
|
240
|
+
|-------|---------------------------|------------------------------|
|
|
241
|
+
| Symbol | `name` | `symbol` |
|
|
242
|
+
| Size decimals | `sz_decimals` | `size_decimals` |
|
|
243
|
+
| Fee info | Not available | `taker_fee`, `maker_fee`, `liquidation_fee` |
|
|
244
|
+
| Market ID | Not available | `market_id` |
|
|
245
|
+
| Min amounts | Not available | `min_base_amount`, `min_quote_amount` |
|
|
246
|
+
|
|
164
247
|
### Funding Rates
|
|
165
248
|
|
|
166
249
|
```python
|
|
@@ -197,6 +280,57 @@ current = await client.hyperliquid.open_interest.acurrent("BTC")
|
|
|
197
280
|
history = await client.hyperliquid.open_interest.ahistory("ETH", start=..., end=...)
|
|
198
281
|
```
|
|
199
282
|
|
|
283
|
+
### Candles (OHLCV)
|
|
284
|
+
|
|
285
|
+
Get historical OHLCV candle data aggregated from trades.
|
|
286
|
+
|
|
287
|
+
```python
|
|
288
|
+
# Get candle history (start is required)
|
|
289
|
+
candles = client.hyperliquid.candles.history(
|
|
290
|
+
"BTC",
|
|
291
|
+
start="2024-01-01",
|
|
292
|
+
end="2024-01-02",
|
|
293
|
+
interval="1h", # 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w
|
|
294
|
+
limit=100
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
# Iterate through candles
|
|
298
|
+
for candle in candles.data:
|
|
299
|
+
print(f"{candle.timestamp}: O={candle.open} H={candle.high} L={candle.low} C={candle.close} V={candle.volume}")
|
|
300
|
+
|
|
301
|
+
# Cursor-based pagination for large datasets
|
|
302
|
+
result = client.hyperliquid.candles.history("BTC", start=..., end=..., interval="1m", limit=1000)
|
|
303
|
+
while result.next_cursor:
|
|
304
|
+
result = client.hyperliquid.candles.history(
|
|
305
|
+
"BTC", start=..., end=..., interval="1m",
|
|
306
|
+
cursor=result.next_cursor, limit=1000
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
# Lighter.xyz candles
|
|
310
|
+
lighter_candles = client.lighter.candles.history(
|
|
311
|
+
"BTC",
|
|
312
|
+
start="2024-01-01",
|
|
313
|
+
end="2024-01-02",
|
|
314
|
+
interval="15m"
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
# Async versions
|
|
318
|
+
candles = await client.hyperliquid.candles.ahistory("BTC", start=..., end=..., interval="1h")
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
#### Available Intervals
|
|
322
|
+
|
|
323
|
+
| Interval | Description |
|
|
324
|
+
|----------|-------------|
|
|
325
|
+
| `1m` | 1 minute |
|
|
326
|
+
| `5m` | 5 minutes |
|
|
327
|
+
| `15m` | 15 minutes |
|
|
328
|
+
| `30m` | 30 minutes |
|
|
329
|
+
| `1h` | 1 hour (default) |
|
|
330
|
+
| `4h` | 4 hours |
|
|
331
|
+
| `1d` | 1 day |
|
|
332
|
+
| `1w` | 1 week |
|
|
333
|
+
|
|
200
334
|
### Legacy API (Deprecated)
|
|
201
335
|
|
|
202
336
|
The following legacy methods are deprecated and will be removed in v2.0. They default to Hyperliquid data:
|
|
@@ -298,6 +432,19 @@ async def main():
|
|
|
298
432
|
speed=10 # Optional, defaults to 1x
|
|
299
433
|
)
|
|
300
434
|
|
|
435
|
+
# Lighter.xyz replay with granularity (tier restrictions apply)
|
|
436
|
+
await ws.replay(
|
|
437
|
+
"orderbook", "BTC",
|
|
438
|
+
start=int(time.time() * 1000) - 86400000,
|
|
439
|
+
speed=10,
|
|
440
|
+
granularity="10s" # Options: 'checkpoint', '30s', '10s', '1s', 'tick'
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
# Handle tick-level data (granularity='tick', Enterprise tier)
|
|
444
|
+
ws.on_historical_tick_data(lambda coin, checkpoint, deltas:
|
|
445
|
+
print(f"Checkpoint: {len(checkpoint['bids'])} bids, Deltas: {len(deltas)}")
|
|
446
|
+
)
|
|
447
|
+
|
|
301
448
|
# Control playback
|
|
302
449
|
await ws.replay_pause()
|
|
303
450
|
await ws.replay_resume()
|
|
@@ -343,6 +490,14 @@ async def main():
|
|
|
343
490
|
batch_size=1000 # Optional, defaults to 1000
|
|
344
491
|
)
|
|
345
492
|
|
|
493
|
+
# Lighter.xyz stream with granularity (tier restrictions apply)
|
|
494
|
+
await ws.stream(
|
|
495
|
+
"orderbook", "BTC",
|
|
496
|
+
start=int(time.time() * 1000) - 3600000,
|
|
497
|
+
end=int(time.time() * 1000),
|
|
498
|
+
granularity="10s" # Options: 'checkpoint', '30s', '10s', '1s', 'tick'
|
|
499
|
+
)
|
|
500
|
+
|
|
346
501
|
# Stop if needed
|
|
347
502
|
await ws.stream_stop()
|
|
348
503
|
|
|
@@ -364,12 +519,43 @@ ws = OxArchiveWs(WsOptions(
|
|
|
364
519
|
|
|
365
520
|
### Available Channels
|
|
366
521
|
|
|
367
|
-
| Channel | Description | Requires Coin |
|
|
368
|
-
|
|
369
|
-
| `orderbook` | L2 order book updates | Yes |
|
|
370
|
-
| `trades` | Trade/fill updates | Yes |
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
522
|
+
| Channel | Description | Requires Coin | Historical Support |
|
|
523
|
+
|---------|-------------|---------------|-------------------|
|
|
524
|
+
| `orderbook` | L2 order book updates | Yes | Yes |
|
|
525
|
+
| `trades` | Trade/fill updates | Yes | Yes |
|
|
526
|
+
| `candles` | OHLCV candle data | Yes | Yes (replay/stream only) |
|
|
527
|
+
| `ticker` | Price and 24h volume | Yes | Real-time only |
|
|
528
|
+
| `all_tickers` | All market tickers | No | Real-time only |
|
|
529
|
+
|
|
530
|
+
#### Candle Replay/Stream
|
|
531
|
+
|
|
532
|
+
```python
|
|
533
|
+
# Replay candles at 10x speed
|
|
534
|
+
await ws.replay(
|
|
535
|
+
"candles", "BTC",
|
|
536
|
+
start=int(time.time() * 1000) - 86400000,
|
|
537
|
+
end=int(time.time() * 1000),
|
|
538
|
+
speed=10,
|
|
539
|
+
interval="15m" # 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
# Bulk stream candles
|
|
543
|
+
await ws.stream(
|
|
544
|
+
"candles", "ETH",
|
|
545
|
+
start=int(time.time() * 1000) - 3600000,
|
|
546
|
+
end=int(time.time() * 1000),
|
|
547
|
+
batch_size=1000,
|
|
548
|
+
interval="1h"
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
# Lighter.xyz candles
|
|
552
|
+
await ws.replay(
|
|
553
|
+
"lighter_candles", "BTC",
|
|
554
|
+
start=...,
|
|
555
|
+
speed=10,
|
|
556
|
+
interval="5m"
|
|
557
|
+
)
|
|
558
|
+
```
|
|
373
559
|
|
|
374
560
|
## Timestamp Formats
|
|
375
561
|
|
|
@@ -412,8 +598,8 @@ except OxArchiveError as e:
|
|
|
412
598
|
Full type hint support with Pydantic models:
|
|
413
599
|
|
|
414
600
|
```python
|
|
415
|
-
from oxarchive import Client
|
|
416
|
-
from oxarchive.types import OrderBook, Trade, Instrument, FundingRate, OpenInterest
|
|
601
|
+
from oxarchive import Client, LighterGranularity
|
|
602
|
+
from oxarchive.types import OrderBook, Trade, Instrument, LighterInstrument, FundingRate, OpenInterest
|
|
417
603
|
from oxarchive.resources.trades import CursorResponse
|
|
418
604
|
|
|
419
605
|
client = Client(api_key="ox_your_api_key")
|
|
@@ -421,6 +607,9 @@ client = Client(api_key="ox_your_api_key")
|
|
|
421
607
|
orderbook: OrderBook = client.orderbook.get("BTC")
|
|
422
608
|
trades: list[Trade] = client.trades.recent("BTC")
|
|
423
609
|
result: CursorResponse = client.trades.list("BTC", start=..., end=...)
|
|
610
|
+
|
|
611
|
+
# Lighter granularity type hint
|
|
612
|
+
granularity: LighterGranularity = "10s"
|
|
424
613
|
```
|
|
425
614
|
|
|
426
615
|
## Requirements
|
|
@@ -23,12 +23,16 @@ Example:
|
|
|
23
23
|
|
|
24
24
|
from .client import Client
|
|
25
25
|
from .exchanges import HyperliquidClient, LighterClient
|
|
26
|
+
from .resources.orderbook import LighterGranularity
|
|
26
27
|
from .types import (
|
|
27
28
|
OrderBook,
|
|
28
29
|
Trade,
|
|
29
30
|
Instrument,
|
|
31
|
+
LighterInstrument,
|
|
30
32
|
FundingRate,
|
|
31
33
|
OpenInterest,
|
|
34
|
+
Candle,
|
|
35
|
+
CandleInterval,
|
|
32
36
|
OxArchiveError,
|
|
33
37
|
# WebSocket types
|
|
34
38
|
WsChannel,
|
|
@@ -63,7 +67,7 @@ except ImportError:
|
|
|
63
67
|
OxArchiveWs = None # type: ignore
|
|
64
68
|
WsOptions = None # type: ignore
|
|
65
69
|
|
|
66
|
-
__version__ = "0.
|
|
70
|
+
__version__ = "0.5.2"
|
|
67
71
|
|
|
68
72
|
__all__ = [
|
|
69
73
|
# Client
|
|
@@ -78,8 +82,12 @@ __all__ = [
|
|
|
78
82
|
"OrderBook",
|
|
79
83
|
"Trade",
|
|
80
84
|
"Instrument",
|
|
85
|
+
"LighterInstrument",
|
|
86
|
+
"LighterGranularity",
|
|
81
87
|
"FundingRate",
|
|
82
88
|
"OpenInterest",
|
|
89
|
+
"Candle",
|
|
90
|
+
"CandleInterval",
|
|
83
91
|
"OxArchiveError",
|
|
84
92
|
# WebSocket Types
|
|
85
93
|
"WsChannel",
|
|
@@ -7,8 +7,11 @@ from .resources import (
|
|
|
7
7
|
OrderBookResource,
|
|
8
8
|
TradesResource,
|
|
9
9
|
InstrumentsResource,
|
|
10
|
+
LighterInstrumentsResource,
|
|
10
11
|
FundingResource,
|
|
11
12
|
OpenInterestResource,
|
|
13
|
+
CandlesResource,
|
|
14
|
+
LiquidationsResource,
|
|
12
15
|
)
|
|
13
16
|
|
|
14
17
|
|
|
@@ -43,6 +46,12 @@ class HyperliquidClient:
|
|
|
43
46
|
self.open_interest = OpenInterestResource(http, base_path)
|
|
44
47
|
"""Open interest"""
|
|
45
48
|
|
|
49
|
+
self.candles = CandlesResource(http, base_path)
|
|
50
|
+
"""OHLCV candle data"""
|
|
51
|
+
|
|
52
|
+
self.liquidations = LiquidationsResource(http, base_path)
|
|
53
|
+
"""Liquidation events (May 2025+)"""
|
|
54
|
+
|
|
46
55
|
|
|
47
56
|
class LighterClient:
|
|
48
57
|
"""
|
|
@@ -54,6 +63,8 @@ class LighterClient:
|
|
|
54
63
|
>>> client = oxarchive.Client(api_key="...")
|
|
55
64
|
>>> orderbook = client.lighter.orderbook.get("BTC")
|
|
56
65
|
>>> trades = client.lighter.trades.list("ETH", start=..., end=...)
|
|
66
|
+
>>> instruments = client.lighter.instruments.list()
|
|
67
|
+
>>> print(f"ETH taker fee: {instruments[0].taker_fee}")
|
|
57
68
|
"""
|
|
58
69
|
|
|
59
70
|
def __init__(self, http: HttpClient):
|
|
@@ -66,11 +77,14 @@ class LighterClient:
|
|
|
66
77
|
self.trades = TradesResource(http, base_path)
|
|
67
78
|
"""Trade/fill history"""
|
|
68
79
|
|
|
69
|
-
self.instruments =
|
|
70
|
-
"""Trading instruments metadata"""
|
|
80
|
+
self.instruments = LighterInstrumentsResource(http, base_path)
|
|
81
|
+
"""Trading instruments metadata (returns LighterInstrument with fees, min amounts, etc.)"""
|
|
71
82
|
|
|
72
83
|
self.funding = FundingResource(http, base_path)
|
|
73
84
|
"""Funding rates"""
|
|
74
85
|
|
|
75
86
|
self.open_interest = OpenInterestResource(http, base_path)
|
|
76
87
|
"""Open interest"""
|
|
88
|
+
|
|
89
|
+
self.candles = CandlesResource(http, base_path)
|
|
90
|
+
"""OHLCV candle data"""
|
|
@@ -2,14 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
from .orderbook import OrderBookResource
|
|
4
4
|
from .trades import TradesResource
|
|
5
|
-
from .instruments import InstrumentsResource
|
|
5
|
+
from .instruments import InstrumentsResource, LighterInstrumentsResource
|
|
6
6
|
from .funding import FundingResource
|
|
7
7
|
from .openinterest import OpenInterestResource
|
|
8
|
+
from .candles import CandlesResource
|
|
9
|
+
from .liquidations import LiquidationsResource
|
|
8
10
|
|
|
9
11
|
__all__ = [
|
|
10
12
|
"OrderBookResource",
|
|
11
13
|
"TradesResource",
|
|
12
14
|
"InstrumentsResource",
|
|
15
|
+
"LighterInstrumentsResource",
|
|
13
16
|
"FundingResource",
|
|
14
17
|
"OpenInterestResource",
|
|
18
|
+
"CandlesResource",
|
|
19
|
+
"LiquidationsResource",
|
|
15
20
|
]
|