oxarchive 0.3.3__tar.gz → 0.3.4__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.3.3 → oxarchive-0.3.4}/PKG-INFO +112 -57
- {oxarchive-0.3.3 → oxarchive-0.3.4}/README.md +111 -56
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/__init__.py +1 -1
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/types.py +2 -2
- {oxarchive-0.3.3 → oxarchive-0.3.4}/pyproject.toml +1 -1
- {oxarchive-0.3.3 → oxarchive-0.3.4}/.gitignore +0 -0
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/client.py +0 -0
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/http.py +0 -0
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/resources/__init__.py +0 -0
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/resources/funding.py +0 -0
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/resources/instruments.py +0 -0
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/resources/openinterest.py +0 -0
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/resources/orderbook.py +0 -0
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/resources/trades.py +0 -0
- {oxarchive-0.3.3 → oxarchive-0.3.4}/oxarchive/websocket.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oxarchive
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
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
|
|
@@ -45,6 +45,12 @@ Official Python SDK for [0xarchive](https://0xarchive.io) - Hyperliquid Historic
|
|
|
45
45
|
pip install oxarchive
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
For WebSocket support:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install oxarchive[websocket]
|
|
52
|
+
```
|
|
53
|
+
|
|
48
54
|
## Quick Start
|
|
49
55
|
|
|
50
56
|
```python
|
|
@@ -97,13 +103,13 @@ async with Client(api_key="ox_your_api_key") as client:
|
|
|
97
103
|
|
|
98
104
|
```python
|
|
99
105
|
client = Client(
|
|
100
|
-
api_key="ox_your_api_key",
|
|
101
|
-
base_url="https://api.0xarchive.io",
|
|
102
|
-
timeout=30.0,
|
|
106
|
+
api_key="ox_your_api_key", # Required
|
|
107
|
+
base_url="https://api.0xarchive.io", # Optional
|
|
108
|
+
timeout=30.0, # Optional, request timeout in seconds (default: 30.0)
|
|
103
109
|
)
|
|
104
110
|
```
|
|
105
111
|
|
|
106
|
-
## API Reference
|
|
112
|
+
## REST API Reference
|
|
107
113
|
|
|
108
114
|
### Order Book
|
|
109
115
|
|
|
@@ -117,38 +123,63 @@ historical = client.orderbook.get("BTC", timestamp=1704067200000)
|
|
|
117
123
|
# Get with limited depth
|
|
118
124
|
shallow = client.orderbook.get("BTC", depth=10)
|
|
119
125
|
|
|
120
|
-
# Get historical snapshots
|
|
126
|
+
# Get historical snapshots (start and end are required)
|
|
121
127
|
history = client.orderbook.history(
|
|
122
128
|
"BTC",
|
|
123
129
|
start="2024-01-01",
|
|
124
130
|
end="2024-01-02",
|
|
125
|
-
limit=1000
|
|
131
|
+
limit=1000,
|
|
132
|
+
depth=20 # Price levels per side
|
|
126
133
|
)
|
|
134
|
+
|
|
135
|
+
# Async versions
|
|
136
|
+
orderbook = await client.orderbook.aget("BTC")
|
|
137
|
+
history = await client.orderbook.ahistory("BTC", start=..., end=...)
|
|
127
138
|
```
|
|
128
139
|
|
|
129
140
|
### Trades
|
|
130
141
|
|
|
142
|
+
The trades API uses cursor-based pagination for efficient retrieval of large datasets.
|
|
143
|
+
|
|
131
144
|
```python
|
|
132
145
|
# Get recent trades
|
|
133
146
|
recent = client.trades.recent("BTC", limit=100)
|
|
134
147
|
|
|
135
|
-
# Get trade history
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
148
|
+
# Get trade history with cursor-based pagination
|
|
149
|
+
result = client.trades.list("ETH", start="2024-01-01", end="2024-01-02", limit=1000)
|
|
150
|
+
trades = result.data
|
|
151
|
+
|
|
152
|
+
# Paginate through all results
|
|
153
|
+
while result.next_cursor:
|
|
154
|
+
result = client.trades.list(
|
|
155
|
+
"ETH",
|
|
156
|
+
start="2024-01-01",
|
|
157
|
+
end="2024-01-02",
|
|
158
|
+
cursor=result.next_cursor,
|
|
159
|
+
limit=1000
|
|
160
|
+
)
|
|
161
|
+
trades.extend(result.data)
|
|
162
|
+
|
|
163
|
+
# Filter by side
|
|
164
|
+
buys = client.trades.list("BTC", start=..., end=..., side="buy")
|
|
165
|
+
|
|
166
|
+
# Async versions
|
|
167
|
+
recent = await client.trades.arecent("BTC")
|
|
168
|
+
result = await client.trades.alist("ETH", start=..., end=...)
|
|
142
169
|
```
|
|
143
170
|
|
|
144
171
|
### Instruments
|
|
145
172
|
|
|
146
173
|
```python
|
|
147
|
-
# List all instruments
|
|
174
|
+
# List all trading instruments
|
|
148
175
|
instruments = client.instruments.list()
|
|
149
176
|
|
|
150
|
-
# Get specific instrument
|
|
177
|
+
# Get specific instrument details
|
|
151
178
|
btc = client.instruments.get("BTC")
|
|
179
|
+
|
|
180
|
+
# Async versions
|
|
181
|
+
instruments = await client.instruments.alist()
|
|
182
|
+
btc = await client.instruments.aget("BTC")
|
|
152
183
|
```
|
|
153
184
|
|
|
154
185
|
### Funding Rates
|
|
@@ -157,12 +188,16 @@ btc = client.instruments.get("BTC")
|
|
|
157
188
|
# Get current funding rate
|
|
158
189
|
current = client.funding.current("BTC")
|
|
159
190
|
|
|
160
|
-
# Get funding rate history
|
|
191
|
+
# Get funding rate history (start is required)
|
|
161
192
|
history = client.funding.history(
|
|
162
193
|
"ETH",
|
|
163
194
|
start="2024-01-01",
|
|
164
195
|
end="2024-01-07"
|
|
165
196
|
)
|
|
197
|
+
|
|
198
|
+
# Async versions
|
|
199
|
+
current = await client.funding.acurrent("BTC")
|
|
200
|
+
history = await client.funding.ahistory("ETH", start=..., end=...)
|
|
166
201
|
```
|
|
167
202
|
|
|
168
203
|
### Open Interest
|
|
@@ -171,40 +206,32 @@ history = client.funding.history(
|
|
|
171
206
|
# Get current open interest
|
|
172
207
|
current = client.open_interest.current("BTC")
|
|
173
208
|
|
|
174
|
-
# Get open interest history
|
|
209
|
+
# Get open interest history (start is required)
|
|
175
210
|
history = client.open_interest.history(
|
|
176
211
|
"ETH",
|
|
177
212
|
start="2024-01-01",
|
|
178
213
|
end="2024-01-07"
|
|
179
214
|
)
|
|
215
|
+
|
|
216
|
+
# Async versions
|
|
217
|
+
current = await client.open_interest.acurrent("BTC")
|
|
218
|
+
history = await client.open_interest.ahistory("ETH", start=..., end=...)
|
|
180
219
|
```
|
|
181
220
|
|
|
182
|
-
##
|
|
221
|
+
## WebSocket Client
|
|
183
222
|
|
|
184
|
-
The
|
|
223
|
+
The WebSocket client supports three modes: real-time streaming, historical replay, and bulk streaming.
|
|
185
224
|
|
|
186
225
|
```python
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
# Unix milliseconds
|
|
190
|
-
client.orderbook.get("BTC", timestamp=1704067200000)
|
|
191
|
-
|
|
192
|
-
# ISO string
|
|
193
|
-
client.orderbook.history("BTC", start="2024-01-01", end="2024-01-02")
|
|
226
|
+
import asyncio
|
|
227
|
+
from oxarchive import OxArchiveWs, WsOptions
|
|
194
228
|
|
|
195
|
-
|
|
196
|
-
client.orderbook.history("BTC", start=datetime(2024, 1, 1), end=datetime(2024, 1, 2))
|
|
229
|
+
ws = OxArchiveWs(WsOptions(api_key="ox_your_api_key"))
|
|
197
230
|
```
|
|
198
231
|
|
|
199
|
-
|
|
232
|
+
### Real-time Streaming
|
|
200
233
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
```bash
|
|
204
|
-
pip install oxarchive[websocket]
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### Basic Usage
|
|
234
|
+
Subscribe to live market data from Hyperliquid.
|
|
208
235
|
|
|
209
236
|
```python
|
|
210
237
|
import asyncio
|
|
@@ -227,24 +254,26 @@ async def main():
|
|
|
227
254
|
ws.subscribe_trades("BTC")
|
|
228
255
|
ws.subscribe_all_tickers()
|
|
229
256
|
|
|
230
|
-
# Handle
|
|
257
|
+
# Handle real-time data
|
|
231
258
|
ws.on_orderbook(lambda coin, data: print(f"{coin}: {data.mid_price}"))
|
|
232
|
-
|
|
233
|
-
# Handle trade updates
|
|
234
259
|
ws.on_trades(lambda coin, trades: print(f"{coin}: {len(trades)} trades"))
|
|
235
260
|
|
|
236
261
|
# Keep running
|
|
237
262
|
await asyncio.sleep(60)
|
|
238
263
|
|
|
239
|
-
#
|
|
264
|
+
# Unsubscribe and disconnect
|
|
265
|
+
ws.unsubscribe_orderbook("ETH")
|
|
240
266
|
await ws.disconnect()
|
|
241
267
|
|
|
242
268
|
asyncio.run(main())
|
|
243
269
|
```
|
|
244
270
|
|
|
245
|
-
### Historical Replay
|
|
271
|
+
### Historical Replay
|
|
246
272
|
|
|
247
|
-
Replay historical data with timing preserved
|
|
273
|
+
Replay historical data with timing preserved. Perfect for backtesting.
|
|
274
|
+
|
|
275
|
+
> **Important:** Replay data is delivered via `on_historical_data()`, NOT `on_trades()` or `on_orderbook()`.
|
|
276
|
+
> The real-time callbacks only receive live market data from subscriptions.
|
|
248
277
|
|
|
249
278
|
```python
|
|
250
279
|
import asyncio
|
|
@@ -254,13 +283,14 @@ from oxarchive import OxArchiveWs, WsOptions
|
|
|
254
283
|
async def main():
|
|
255
284
|
ws = OxArchiveWs(WsOptions(api_key="ox_..."))
|
|
256
285
|
|
|
257
|
-
# Handle replay data
|
|
286
|
+
# Handle replay data - this is where historical records arrive
|
|
258
287
|
ws.on_historical_data(lambda coin, ts, data:
|
|
259
288
|
print(f"{ts}: {data['mid_price']}")
|
|
260
289
|
)
|
|
261
290
|
|
|
291
|
+
# Replay lifecycle events
|
|
262
292
|
ws.on_replay_start(lambda ch, coin, start, end, speed:
|
|
263
|
-
print(f"Starting replay
|
|
293
|
+
print(f"Starting replay: {ch}/{coin} at {speed}x")
|
|
264
294
|
)
|
|
265
295
|
|
|
266
296
|
ws.on_replay_complete(lambda ch, coin, sent:
|
|
@@ -273,7 +303,8 @@ async def main():
|
|
|
273
303
|
await ws.replay(
|
|
274
304
|
"orderbook", "BTC",
|
|
275
305
|
start=int(time.time() * 1000) - 86400000, # 24 hours ago
|
|
276
|
-
|
|
306
|
+
end=int(time.time() * 1000), # Optional
|
|
307
|
+
speed=10 # Optional, defaults to 1x
|
|
277
308
|
)
|
|
278
309
|
|
|
279
310
|
# Control playback
|
|
@@ -285,9 +316,9 @@ async def main():
|
|
|
285
316
|
asyncio.run(main())
|
|
286
317
|
```
|
|
287
318
|
|
|
288
|
-
### Bulk Streaming
|
|
319
|
+
### Bulk Streaming
|
|
289
320
|
|
|
290
|
-
Fast bulk download for data pipelines
|
|
321
|
+
Fast bulk download for data pipelines. Data arrives in batches without timing delays.
|
|
291
322
|
|
|
292
323
|
```python
|
|
293
324
|
import asyncio
|
|
@@ -304,7 +335,7 @@ async def main():
|
|
|
304
335
|
)
|
|
305
336
|
|
|
306
337
|
ws.on_stream_progress(lambda snapshots_sent:
|
|
307
|
-
print(f"
|
|
338
|
+
print(f"Progress: {snapshots_sent} snapshots")
|
|
308
339
|
)
|
|
309
340
|
|
|
310
341
|
ws.on_stream_complete(lambda ch, coin, sent:
|
|
@@ -318,25 +349,25 @@ async def main():
|
|
|
318
349
|
"orderbook", "ETH",
|
|
319
350
|
start=int(time.time() * 1000) - 3600000, # 1 hour ago
|
|
320
351
|
end=int(time.time() * 1000),
|
|
321
|
-
batch_size=1000
|
|
352
|
+
batch_size=1000 # Optional, defaults to 1000
|
|
322
353
|
)
|
|
323
354
|
|
|
324
|
-
# Stop
|
|
355
|
+
# Stop if needed
|
|
325
356
|
await ws.stream_stop()
|
|
326
357
|
|
|
327
358
|
asyncio.run(main())
|
|
328
359
|
```
|
|
329
360
|
|
|
330
|
-
### Configuration
|
|
361
|
+
### WebSocket Configuration
|
|
331
362
|
|
|
332
363
|
```python
|
|
333
364
|
ws = OxArchiveWs(WsOptions(
|
|
334
365
|
api_key="ox_your_api_key",
|
|
335
366
|
ws_url="wss://api.0xarchive.io/ws", # Optional
|
|
336
|
-
auto_reconnect=True,
|
|
337
|
-
reconnect_delay=1.0,
|
|
338
|
-
max_reconnect_attempts=10,
|
|
339
|
-
ping_interval=30.0,
|
|
367
|
+
auto_reconnect=True, # Auto-reconnect on disconnect (default: True)
|
|
368
|
+
reconnect_delay=1.0, # Initial reconnect delay in seconds (default: 1.0)
|
|
369
|
+
max_reconnect_attempts=10, # Max reconnect attempts (default: 10)
|
|
370
|
+
ping_interval=30.0, # Keep-alive ping interval in seconds (default: 30.0)
|
|
340
371
|
))
|
|
341
372
|
```
|
|
342
373
|
|
|
@@ -349,6 +380,27 @@ ws = OxArchiveWs(WsOptions(
|
|
|
349
380
|
| `ticker` | Price and 24h volume | Yes |
|
|
350
381
|
| `all_tickers` | All market tickers | No |
|
|
351
382
|
|
|
383
|
+
## Timestamp Formats
|
|
384
|
+
|
|
385
|
+
The SDK accepts timestamps in multiple formats:
|
|
386
|
+
|
|
387
|
+
```python
|
|
388
|
+
from datetime import datetime
|
|
389
|
+
|
|
390
|
+
# Unix milliseconds (int)
|
|
391
|
+
client.orderbook.get("BTC", timestamp=1704067200000)
|
|
392
|
+
|
|
393
|
+
# ISO string
|
|
394
|
+
client.orderbook.history("BTC", start="2024-01-01", end="2024-01-02")
|
|
395
|
+
|
|
396
|
+
# datetime object
|
|
397
|
+
client.orderbook.history(
|
|
398
|
+
"BTC",
|
|
399
|
+
start=datetime(2024, 1, 1),
|
|
400
|
+
end=datetime(2024, 1, 2)
|
|
401
|
+
)
|
|
402
|
+
```
|
|
403
|
+
|
|
352
404
|
## Error Handling
|
|
353
405
|
|
|
354
406
|
```python
|
|
@@ -369,12 +421,15 @@ except OxArchiveError as e:
|
|
|
369
421
|
Full type hint support with Pydantic models:
|
|
370
422
|
|
|
371
423
|
```python
|
|
372
|
-
from oxarchive import Client
|
|
424
|
+
from oxarchive import Client
|
|
425
|
+
from oxarchive.types import OrderBook, Trade, Instrument, FundingRate, OpenInterest
|
|
426
|
+
from oxarchive.resources.trades import CursorResponse
|
|
373
427
|
|
|
374
428
|
client = Client(api_key="ox_your_api_key")
|
|
375
429
|
|
|
376
430
|
orderbook: OrderBook = client.orderbook.get("BTC")
|
|
377
431
|
trades: list[Trade] = client.trades.recent("BTC")
|
|
432
|
+
result: CursorResponse = client.trades.list("BTC", start=..., end=...)
|
|
378
433
|
```
|
|
379
434
|
|
|
380
435
|
## Requirements
|
|
@@ -8,6 +8,12 @@ Official Python SDK for [0xarchive](https://0xarchive.io) - Hyperliquid Historic
|
|
|
8
8
|
pip install oxarchive
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
For WebSocket support:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install oxarchive[websocket]
|
|
15
|
+
```
|
|
16
|
+
|
|
11
17
|
## Quick Start
|
|
12
18
|
|
|
13
19
|
```python
|
|
@@ -60,13 +66,13 @@ async with Client(api_key="ox_your_api_key") as client:
|
|
|
60
66
|
|
|
61
67
|
```python
|
|
62
68
|
client = Client(
|
|
63
|
-
api_key="ox_your_api_key",
|
|
64
|
-
base_url="https://api.0xarchive.io",
|
|
65
|
-
timeout=30.0,
|
|
69
|
+
api_key="ox_your_api_key", # Required
|
|
70
|
+
base_url="https://api.0xarchive.io", # Optional
|
|
71
|
+
timeout=30.0, # Optional, request timeout in seconds (default: 30.0)
|
|
66
72
|
)
|
|
67
73
|
```
|
|
68
74
|
|
|
69
|
-
## API Reference
|
|
75
|
+
## REST API Reference
|
|
70
76
|
|
|
71
77
|
### Order Book
|
|
72
78
|
|
|
@@ -80,38 +86,63 @@ historical = client.orderbook.get("BTC", timestamp=1704067200000)
|
|
|
80
86
|
# Get with limited depth
|
|
81
87
|
shallow = client.orderbook.get("BTC", depth=10)
|
|
82
88
|
|
|
83
|
-
# Get historical snapshots
|
|
89
|
+
# Get historical snapshots (start and end are required)
|
|
84
90
|
history = client.orderbook.history(
|
|
85
91
|
"BTC",
|
|
86
92
|
start="2024-01-01",
|
|
87
93
|
end="2024-01-02",
|
|
88
|
-
limit=1000
|
|
94
|
+
limit=1000,
|
|
95
|
+
depth=20 # Price levels per side
|
|
89
96
|
)
|
|
97
|
+
|
|
98
|
+
# Async versions
|
|
99
|
+
orderbook = await client.orderbook.aget("BTC")
|
|
100
|
+
history = await client.orderbook.ahistory("BTC", start=..., end=...)
|
|
90
101
|
```
|
|
91
102
|
|
|
92
103
|
### Trades
|
|
93
104
|
|
|
105
|
+
The trades API uses cursor-based pagination for efficient retrieval of large datasets.
|
|
106
|
+
|
|
94
107
|
```python
|
|
95
108
|
# Get recent trades
|
|
96
109
|
recent = client.trades.recent("BTC", limit=100)
|
|
97
110
|
|
|
98
|
-
# Get trade history
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
111
|
+
# Get trade history with cursor-based pagination
|
|
112
|
+
result = client.trades.list("ETH", start="2024-01-01", end="2024-01-02", limit=1000)
|
|
113
|
+
trades = result.data
|
|
114
|
+
|
|
115
|
+
# Paginate through all results
|
|
116
|
+
while result.next_cursor:
|
|
117
|
+
result = client.trades.list(
|
|
118
|
+
"ETH",
|
|
119
|
+
start="2024-01-01",
|
|
120
|
+
end="2024-01-02",
|
|
121
|
+
cursor=result.next_cursor,
|
|
122
|
+
limit=1000
|
|
123
|
+
)
|
|
124
|
+
trades.extend(result.data)
|
|
125
|
+
|
|
126
|
+
# Filter by side
|
|
127
|
+
buys = client.trades.list("BTC", start=..., end=..., side="buy")
|
|
128
|
+
|
|
129
|
+
# Async versions
|
|
130
|
+
recent = await client.trades.arecent("BTC")
|
|
131
|
+
result = await client.trades.alist("ETH", start=..., end=...)
|
|
105
132
|
```
|
|
106
133
|
|
|
107
134
|
### Instruments
|
|
108
135
|
|
|
109
136
|
```python
|
|
110
|
-
# List all instruments
|
|
137
|
+
# List all trading instruments
|
|
111
138
|
instruments = client.instruments.list()
|
|
112
139
|
|
|
113
|
-
# Get specific instrument
|
|
140
|
+
# Get specific instrument details
|
|
114
141
|
btc = client.instruments.get("BTC")
|
|
142
|
+
|
|
143
|
+
# Async versions
|
|
144
|
+
instruments = await client.instruments.alist()
|
|
145
|
+
btc = await client.instruments.aget("BTC")
|
|
115
146
|
```
|
|
116
147
|
|
|
117
148
|
### Funding Rates
|
|
@@ -120,12 +151,16 @@ btc = client.instruments.get("BTC")
|
|
|
120
151
|
# Get current funding rate
|
|
121
152
|
current = client.funding.current("BTC")
|
|
122
153
|
|
|
123
|
-
# Get funding rate history
|
|
154
|
+
# Get funding rate history (start is required)
|
|
124
155
|
history = client.funding.history(
|
|
125
156
|
"ETH",
|
|
126
157
|
start="2024-01-01",
|
|
127
158
|
end="2024-01-07"
|
|
128
159
|
)
|
|
160
|
+
|
|
161
|
+
# Async versions
|
|
162
|
+
current = await client.funding.acurrent("BTC")
|
|
163
|
+
history = await client.funding.ahistory("ETH", start=..., end=...)
|
|
129
164
|
```
|
|
130
165
|
|
|
131
166
|
### Open Interest
|
|
@@ -134,40 +169,32 @@ history = client.funding.history(
|
|
|
134
169
|
# Get current open interest
|
|
135
170
|
current = client.open_interest.current("BTC")
|
|
136
171
|
|
|
137
|
-
# Get open interest history
|
|
172
|
+
# Get open interest history (start is required)
|
|
138
173
|
history = client.open_interest.history(
|
|
139
174
|
"ETH",
|
|
140
175
|
start="2024-01-01",
|
|
141
176
|
end="2024-01-07"
|
|
142
177
|
)
|
|
178
|
+
|
|
179
|
+
# Async versions
|
|
180
|
+
current = await client.open_interest.acurrent("BTC")
|
|
181
|
+
history = await client.open_interest.ahistory("ETH", start=..., end=...)
|
|
143
182
|
```
|
|
144
183
|
|
|
145
|
-
##
|
|
184
|
+
## WebSocket Client
|
|
146
185
|
|
|
147
|
-
The
|
|
186
|
+
The WebSocket client supports three modes: real-time streaming, historical replay, and bulk streaming.
|
|
148
187
|
|
|
149
188
|
```python
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
# Unix milliseconds
|
|
153
|
-
client.orderbook.get("BTC", timestamp=1704067200000)
|
|
154
|
-
|
|
155
|
-
# ISO string
|
|
156
|
-
client.orderbook.history("BTC", start="2024-01-01", end="2024-01-02")
|
|
189
|
+
import asyncio
|
|
190
|
+
from oxarchive import OxArchiveWs, WsOptions
|
|
157
191
|
|
|
158
|
-
|
|
159
|
-
client.orderbook.history("BTC", start=datetime(2024, 1, 1), end=datetime(2024, 1, 2))
|
|
192
|
+
ws = OxArchiveWs(WsOptions(api_key="ox_your_api_key"))
|
|
160
193
|
```
|
|
161
194
|
|
|
162
|
-
|
|
195
|
+
### Real-time Streaming
|
|
163
196
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
```bash
|
|
167
|
-
pip install oxarchive[websocket]
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### Basic Usage
|
|
197
|
+
Subscribe to live market data from Hyperliquid.
|
|
171
198
|
|
|
172
199
|
```python
|
|
173
200
|
import asyncio
|
|
@@ -190,24 +217,26 @@ async def main():
|
|
|
190
217
|
ws.subscribe_trades("BTC")
|
|
191
218
|
ws.subscribe_all_tickers()
|
|
192
219
|
|
|
193
|
-
# Handle
|
|
220
|
+
# Handle real-time data
|
|
194
221
|
ws.on_orderbook(lambda coin, data: print(f"{coin}: {data.mid_price}"))
|
|
195
|
-
|
|
196
|
-
# Handle trade updates
|
|
197
222
|
ws.on_trades(lambda coin, trades: print(f"{coin}: {len(trades)} trades"))
|
|
198
223
|
|
|
199
224
|
# Keep running
|
|
200
225
|
await asyncio.sleep(60)
|
|
201
226
|
|
|
202
|
-
#
|
|
227
|
+
# Unsubscribe and disconnect
|
|
228
|
+
ws.unsubscribe_orderbook("ETH")
|
|
203
229
|
await ws.disconnect()
|
|
204
230
|
|
|
205
231
|
asyncio.run(main())
|
|
206
232
|
```
|
|
207
233
|
|
|
208
|
-
### Historical Replay
|
|
234
|
+
### Historical Replay
|
|
209
235
|
|
|
210
|
-
Replay historical data with timing preserved
|
|
236
|
+
Replay historical data with timing preserved. Perfect for backtesting.
|
|
237
|
+
|
|
238
|
+
> **Important:** Replay data is delivered via `on_historical_data()`, NOT `on_trades()` or `on_orderbook()`.
|
|
239
|
+
> The real-time callbacks only receive live market data from subscriptions.
|
|
211
240
|
|
|
212
241
|
```python
|
|
213
242
|
import asyncio
|
|
@@ -217,13 +246,14 @@ from oxarchive import OxArchiveWs, WsOptions
|
|
|
217
246
|
async def main():
|
|
218
247
|
ws = OxArchiveWs(WsOptions(api_key="ox_..."))
|
|
219
248
|
|
|
220
|
-
# Handle replay data
|
|
249
|
+
# Handle replay data - this is where historical records arrive
|
|
221
250
|
ws.on_historical_data(lambda coin, ts, data:
|
|
222
251
|
print(f"{ts}: {data['mid_price']}")
|
|
223
252
|
)
|
|
224
253
|
|
|
254
|
+
# Replay lifecycle events
|
|
225
255
|
ws.on_replay_start(lambda ch, coin, start, end, speed:
|
|
226
|
-
print(f"Starting replay
|
|
256
|
+
print(f"Starting replay: {ch}/{coin} at {speed}x")
|
|
227
257
|
)
|
|
228
258
|
|
|
229
259
|
ws.on_replay_complete(lambda ch, coin, sent:
|
|
@@ -236,7 +266,8 @@ async def main():
|
|
|
236
266
|
await ws.replay(
|
|
237
267
|
"orderbook", "BTC",
|
|
238
268
|
start=int(time.time() * 1000) - 86400000, # 24 hours ago
|
|
239
|
-
|
|
269
|
+
end=int(time.time() * 1000), # Optional
|
|
270
|
+
speed=10 # Optional, defaults to 1x
|
|
240
271
|
)
|
|
241
272
|
|
|
242
273
|
# Control playback
|
|
@@ -248,9 +279,9 @@ async def main():
|
|
|
248
279
|
asyncio.run(main())
|
|
249
280
|
```
|
|
250
281
|
|
|
251
|
-
### Bulk Streaming
|
|
282
|
+
### Bulk Streaming
|
|
252
283
|
|
|
253
|
-
Fast bulk download for data pipelines
|
|
284
|
+
Fast bulk download for data pipelines. Data arrives in batches without timing delays.
|
|
254
285
|
|
|
255
286
|
```python
|
|
256
287
|
import asyncio
|
|
@@ -267,7 +298,7 @@ async def main():
|
|
|
267
298
|
)
|
|
268
299
|
|
|
269
300
|
ws.on_stream_progress(lambda snapshots_sent:
|
|
270
|
-
print(f"
|
|
301
|
+
print(f"Progress: {snapshots_sent} snapshots")
|
|
271
302
|
)
|
|
272
303
|
|
|
273
304
|
ws.on_stream_complete(lambda ch, coin, sent:
|
|
@@ -281,25 +312,25 @@ async def main():
|
|
|
281
312
|
"orderbook", "ETH",
|
|
282
313
|
start=int(time.time() * 1000) - 3600000, # 1 hour ago
|
|
283
314
|
end=int(time.time() * 1000),
|
|
284
|
-
batch_size=1000
|
|
315
|
+
batch_size=1000 # Optional, defaults to 1000
|
|
285
316
|
)
|
|
286
317
|
|
|
287
|
-
# Stop
|
|
318
|
+
# Stop if needed
|
|
288
319
|
await ws.stream_stop()
|
|
289
320
|
|
|
290
321
|
asyncio.run(main())
|
|
291
322
|
```
|
|
292
323
|
|
|
293
|
-
### Configuration
|
|
324
|
+
### WebSocket Configuration
|
|
294
325
|
|
|
295
326
|
```python
|
|
296
327
|
ws = OxArchiveWs(WsOptions(
|
|
297
328
|
api_key="ox_your_api_key",
|
|
298
329
|
ws_url="wss://api.0xarchive.io/ws", # Optional
|
|
299
|
-
auto_reconnect=True,
|
|
300
|
-
reconnect_delay=1.0,
|
|
301
|
-
max_reconnect_attempts=10,
|
|
302
|
-
ping_interval=30.0,
|
|
330
|
+
auto_reconnect=True, # Auto-reconnect on disconnect (default: True)
|
|
331
|
+
reconnect_delay=1.0, # Initial reconnect delay in seconds (default: 1.0)
|
|
332
|
+
max_reconnect_attempts=10, # Max reconnect attempts (default: 10)
|
|
333
|
+
ping_interval=30.0, # Keep-alive ping interval in seconds (default: 30.0)
|
|
303
334
|
))
|
|
304
335
|
```
|
|
305
336
|
|
|
@@ -312,6 +343,27 @@ ws = OxArchiveWs(WsOptions(
|
|
|
312
343
|
| `ticker` | Price and 24h volume | Yes |
|
|
313
344
|
| `all_tickers` | All market tickers | No |
|
|
314
345
|
|
|
346
|
+
## Timestamp Formats
|
|
347
|
+
|
|
348
|
+
The SDK accepts timestamps in multiple formats:
|
|
349
|
+
|
|
350
|
+
```python
|
|
351
|
+
from datetime import datetime
|
|
352
|
+
|
|
353
|
+
# Unix milliseconds (int)
|
|
354
|
+
client.orderbook.get("BTC", timestamp=1704067200000)
|
|
355
|
+
|
|
356
|
+
# ISO string
|
|
357
|
+
client.orderbook.history("BTC", start="2024-01-01", end="2024-01-02")
|
|
358
|
+
|
|
359
|
+
# datetime object
|
|
360
|
+
client.orderbook.history(
|
|
361
|
+
"BTC",
|
|
362
|
+
start=datetime(2024, 1, 1),
|
|
363
|
+
end=datetime(2024, 1, 2)
|
|
364
|
+
)
|
|
365
|
+
```
|
|
366
|
+
|
|
315
367
|
## Error Handling
|
|
316
368
|
|
|
317
369
|
```python
|
|
@@ -332,12 +384,15 @@ except OxArchiveError as e:
|
|
|
332
384
|
Full type hint support with Pydantic models:
|
|
333
385
|
|
|
334
386
|
```python
|
|
335
|
-
from oxarchive import Client
|
|
387
|
+
from oxarchive import Client
|
|
388
|
+
from oxarchive.types import OrderBook, Trade, Instrument, FundingRate, OpenInterest
|
|
389
|
+
from oxarchive.resources.trades import CursorResponse
|
|
336
390
|
|
|
337
391
|
client = Client(api_key="ox_your_api_key")
|
|
338
392
|
|
|
339
393
|
orderbook: OrderBook = client.orderbook.get("BTC")
|
|
340
394
|
trades: list[Trade] = client.trades.recent("BTC")
|
|
395
|
+
result: CursorResponse = client.trades.list("BTC", start=..., end=...)
|
|
341
396
|
```
|
|
342
397
|
|
|
343
398
|
## Requirements
|
|
@@ -118,8 +118,8 @@ class Trade(BaseModel):
|
|
|
118
118
|
closed_pnl: Optional[str] = None
|
|
119
119
|
"""Realized PnL if closing a position."""
|
|
120
120
|
|
|
121
|
-
direction: Optional[
|
|
122
|
-
"""Position direction."""
|
|
121
|
+
direction: Optional[str] = None
|
|
122
|
+
"""Position direction (e.g., 'Open Long', 'Close Short', 'Long > Short')."""
|
|
123
123
|
|
|
124
124
|
start_position: Optional[str] = None
|
|
125
125
|
"""Position size before this trade."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|