oxarchive 0.1.1__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.1.1/PKG-INFO +401 -0
- oxarchive-0.1.1/README.md +365 -0
- oxarchive-0.1.1/oxarchive/__init__.py +101 -0
- oxarchive-0.1.1/oxarchive/client.py +114 -0
- oxarchive-0.1.1/oxarchive/http.py +108 -0
- oxarchive-0.1.1/oxarchive/resources/__init__.py +17 -0
- oxarchive-0.1.1/oxarchive/resources/candles.py +100 -0
- oxarchive-0.1.1/oxarchive/resources/funding.py +113 -0
- oxarchive-0.1.1/oxarchive/resources/instruments.py +55 -0
- oxarchive-0.1.1/oxarchive/resources/openinterest.py +113 -0
- oxarchive-0.1.1/oxarchive/resources/orderbook.py +148 -0
- oxarchive-0.1.1/oxarchive/resources/trades.py +125 -0
- oxarchive-0.1.1/oxarchive/types.py +304 -0
- oxarchive-0.1.1/oxarchive/websocket.py +629 -0
- oxarchive-0.1.1/pyproject.toml +69 -0
oxarchive-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oxarchive
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Official Python SDK for 0xarchive - Hyperliquid Historical Data API
|
|
5
|
+
Project-URL: Homepage, https://0xarchive.io
|
|
6
|
+
Project-URL: Documentation, https://0xarchive.io/docs/sdks
|
|
7
|
+
Project-URL: Repository, https://github.com/0xarchiveIO/sdk-python
|
|
8
|
+
Project-URL: Issues, https://github.com/0xarchiveIO/sdk-python/issues
|
|
9
|
+
Author-email: 0xarchive <support@0xarchive.io>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: 0xarchive,api,historical-data,hyperliquid,orderbook,sdk,trading
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Requires-Dist: httpx>=0.25.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: websockets>=12.0; extra == 'all'
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: mypy>=1.9.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
33
|
+
Provides-Extra: websocket
|
|
34
|
+
Requires-Dist: websockets>=12.0; extra == 'websocket'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# oxarchive
|
|
38
|
+
|
|
39
|
+
Official Python SDK for [0xarchive](https://0xarchive.io) - Hyperliquid Historical Data API.
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install oxarchive
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from oxarchive import Client
|
|
51
|
+
|
|
52
|
+
client = Client(api_key="ox_your_api_key")
|
|
53
|
+
|
|
54
|
+
# Get current order book
|
|
55
|
+
orderbook = client.orderbook.get("BTC")
|
|
56
|
+
print(f"BTC mid price: {orderbook.mid_price}")
|
|
57
|
+
|
|
58
|
+
# Get historical order book snapshots
|
|
59
|
+
history = client.orderbook.history(
|
|
60
|
+
"ETH",
|
|
61
|
+
start="2024-01-01",
|
|
62
|
+
end="2024-01-02",
|
|
63
|
+
limit=100
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Async Support
|
|
68
|
+
|
|
69
|
+
All methods have async versions prefixed with `a`:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
import asyncio
|
|
73
|
+
from oxarchive import Client
|
|
74
|
+
|
|
75
|
+
async def main():
|
|
76
|
+
client = Client(api_key="ox_your_api_key")
|
|
77
|
+
|
|
78
|
+
# Async get
|
|
79
|
+
orderbook = await client.orderbook.aget("BTC")
|
|
80
|
+
print(f"BTC mid price: {orderbook.mid_price}")
|
|
81
|
+
|
|
82
|
+
# Don't forget to close the client
|
|
83
|
+
await client.aclose()
|
|
84
|
+
|
|
85
|
+
asyncio.run(main())
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Or use as async context manager:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
async with Client(api_key="ox_your_api_key") as client:
|
|
92
|
+
orderbook = await client.orderbook.aget("BTC")
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
client = Client(
|
|
99
|
+
api_key="ox_your_api_key", # Required
|
|
100
|
+
base_url="https://api.0xarchive.io", # Optional
|
|
101
|
+
timeout=30.0, # Optional, request timeout in seconds
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## API Reference
|
|
106
|
+
|
|
107
|
+
### Order Book
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
# Get current order book
|
|
111
|
+
orderbook = client.orderbook.get("BTC")
|
|
112
|
+
|
|
113
|
+
# Get order book at specific timestamp
|
|
114
|
+
historical = client.orderbook.get("BTC", timestamp=1704067200000)
|
|
115
|
+
|
|
116
|
+
# Get with limited depth
|
|
117
|
+
shallow = client.orderbook.get("BTC", depth=10)
|
|
118
|
+
|
|
119
|
+
# Get historical snapshots
|
|
120
|
+
history = client.orderbook.history(
|
|
121
|
+
"BTC",
|
|
122
|
+
start="2024-01-01",
|
|
123
|
+
end="2024-01-02",
|
|
124
|
+
limit=1000
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Trades
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# Get recent trades
|
|
132
|
+
recent = client.trades.recent("BTC", limit=100)
|
|
133
|
+
|
|
134
|
+
# Get trade history
|
|
135
|
+
trades = client.trades.list(
|
|
136
|
+
"ETH",
|
|
137
|
+
start="2024-01-01",
|
|
138
|
+
end="2024-01-02",
|
|
139
|
+
side="buy" # Optional: filter by side
|
|
140
|
+
)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Candles (OHLCV)
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
# Get hourly candles
|
|
147
|
+
candles = client.candles.list(
|
|
148
|
+
"BTC",
|
|
149
|
+
interval="1h",
|
|
150
|
+
start="2024-01-01",
|
|
151
|
+
end="2024-01-02"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Available intervals: '1m', '5m', '15m', '1h', '4h', '1d'
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Instruments
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
# List all instruments
|
|
161
|
+
instruments = client.instruments.list()
|
|
162
|
+
|
|
163
|
+
# Get specific instrument
|
|
164
|
+
btc = client.instruments.get("BTC")
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Funding Rates
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
# Get current funding rate
|
|
171
|
+
current = client.funding.current("BTC")
|
|
172
|
+
|
|
173
|
+
# Get funding rate history
|
|
174
|
+
history = client.funding.history(
|
|
175
|
+
"ETH",
|
|
176
|
+
start="2024-01-01",
|
|
177
|
+
end="2024-01-07"
|
|
178
|
+
)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Open Interest
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
# Get current open interest
|
|
185
|
+
current = client.open_interest.current("BTC")
|
|
186
|
+
|
|
187
|
+
# Get open interest history
|
|
188
|
+
history = client.open_interest.history(
|
|
189
|
+
"ETH",
|
|
190
|
+
start="2024-01-01",
|
|
191
|
+
end="2024-01-07"
|
|
192
|
+
)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Timestamp Formats
|
|
196
|
+
|
|
197
|
+
The SDK accepts timestamps in multiple formats:
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
from datetime import datetime
|
|
201
|
+
|
|
202
|
+
# Unix milliseconds
|
|
203
|
+
client.orderbook.get("BTC", timestamp=1704067200000)
|
|
204
|
+
|
|
205
|
+
# ISO string
|
|
206
|
+
client.orderbook.history("BTC", start="2024-01-01", end="2024-01-02")
|
|
207
|
+
|
|
208
|
+
# datetime object
|
|
209
|
+
client.orderbook.history("BTC", start=datetime(2024, 1, 1), end=datetime(2024, 1, 2))
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## WebSocket Streaming
|
|
213
|
+
|
|
214
|
+
For real-time data, install with WebSocket support:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
pip install oxarchive[websocket]
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Basic Usage
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
import asyncio
|
|
224
|
+
from oxarchive import OxArchiveWs, WsOptions
|
|
225
|
+
|
|
226
|
+
async def main():
|
|
227
|
+
ws = OxArchiveWs(WsOptions(api_key="ox_your_api_key"))
|
|
228
|
+
|
|
229
|
+
# Set up handlers
|
|
230
|
+
ws.on_open(lambda: print("Connected"))
|
|
231
|
+
ws.on_close(lambda code, reason: print(f"Disconnected: {code}"))
|
|
232
|
+
ws.on_error(lambda e: print(f"Error: {e}"))
|
|
233
|
+
|
|
234
|
+
# Connect
|
|
235
|
+
await ws.connect()
|
|
236
|
+
|
|
237
|
+
# Subscribe to channels
|
|
238
|
+
ws.subscribe_orderbook("BTC")
|
|
239
|
+
ws.subscribe_orderbook("ETH")
|
|
240
|
+
ws.subscribe_trades("BTC")
|
|
241
|
+
ws.subscribe_all_tickers()
|
|
242
|
+
|
|
243
|
+
# Handle orderbook updates
|
|
244
|
+
ws.on_orderbook(lambda coin, data: print(f"{coin}: {data.mid_price}"))
|
|
245
|
+
|
|
246
|
+
# Handle trade updates
|
|
247
|
+
ws.on_trades(lambda coin, trades: print(f"{coin}: {len(trades)} trades"))
|
|
248
|
+
|
|
249
|
+
# Keep running
|
|
250
|
+
await asyncio.sleep(60)
|
|
251
|
+
|
|
252
|
+
# Disconnect
|
|
253
|
+
await ws.disconnect()
|
|
254
|
+
|
|
255
|
+
asyncio.run(main())
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Historical Replay (like Tardis.dev)
|
|
259
|
+
|
|
260
|
+
Replay historical data with timing preserved:
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
import asyncio
|
|
264
|
+
import time
|
|
265
|
+
from oxarchive import OxArchiveWs, WsOptions
|
|
266
|
+
|
|
267
|
+
async def main():
|
|
268
|
+
ws = OxArchiveWs(WsOptions(api_key="ox_..."))
|
|
269
|
+
|
|
270
|
+
# Handle replay data
|
|
271
|
+
ws.on_historical_data(lambda coin, ts, data:
|
|
272
|
+
print(f"{ts}: {data['mid_price']}")
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
ws.on_replay_start(lambda ch, coin, total, speed:
|
|
276
|
+
print(f"Starting replay of {total} records at {speed}x")
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
ws.on_replay_complete(lambda ch, coin, sent:
|
|
280
|
+
print(f"Replay complete: {sent} records")
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
await ws.connect()
|
|
284
|
+
|
|
285
|
+
# Start replay at 10x speed
|
|
286
|
+
await ws.replay(
|
|
287
|
+
"orderbook", "BTC",
|
|
288
|
+
start=int(time.time() * 1000) - 86400000, # 24 hours ago
|
|
289
|
+
speed=10
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# Control playback
|
|
293
|
+
await ws.replay_pause()
|
|
294
|
+
await ws.replay_resume()
|
|
295
|
+
await ws.replay_seek(1704067200000) # Jump to timestamp
|
|
296
|
+
await ws.replay_stop()
|
|
297
|
+
|
|
298
|
+
asyncio.run(main())
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Bulk Streaming (like Databento)
|
|
302
|
+
|
|
303
|
+
Fast bulk download for data pipelines:
|
|
304
|
+
|
|
305
|
+
```python
|
|
306
|
+
import asyncio
|
|
307
|
+
import time
|
|
308
|
+
from oxarchive import OxArchiveWs, WsOptions
|
|
309
|
+
|
|
310
|
+
async def main():
|
|
311
|
+
ws = OxArchiveWs(WsOptions(api_key="ox_..."))
|
|
312
|
+
all_data = []
|
|
313
|
+
|
|
314
|
+
# Handle batched data
|
|
315
|
+
ws.on_batch(lambda coin, records:
|
|
316
|
+
all_data.extend([r.data for r in records])
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
ws.on_stream_progress(lambda sent, total, pct:
|
|
320
|
+
print(f"Progress: {pct:.1f}%")
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
ws.on_stream_complete(lambda ch, coin, sent:
|
|
324
|
+
print(f"Downloaded {sent} records")
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
await ws.connect()
|
|
328
|
+
|
|
329
|
+
# Start bulk stream
|
|
330
|
+
await ws.stream(
|
|
331
|
+
"orderbook", "ETH",
|
|
332
|
+
start=int(time.time() * 1000) - 3600000, # 1 hour ago
|
|
333
|
+
end=int(time.time() * 1000),
|
|
334
|
+
batch_size=1000
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
# Stop stream if needed
|
|
338
|
+
await ws.stream_stop()
|
|
339
|
+
|
|
340
|
+
asyncio.run(main())
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Configuration
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
ws = OxArchiveWs(WsOptions(
|
|
347
|
+
api_key="ox_your_api_key",
|
|
348
|
+
ws_url="wss://api.0xarchive.io/ws", # Optional
|
|
349
|
+
auto_reconnect=True, # Auto-reconnect on disconnect
|
|
350
|
+
reconnect_delay=1.0, # Initial reconnect delay (seconds)
|
|
351
|
+
max_reconnect_attempts=10, # Max reconnect attempts
|
|
352
|
+
ping_interval=30.0, # Keep-alive ping interval (seconds)
|
|
353
|
+
))
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Available Channels
|
|
357
|
+
|
|
358
|
+
| Channel | Description | Requires Coin |
|
|
359
|
+
|---------|-------------|---------------|
|
|
360
|
+
| `orderbook` | L2 order book updates | Yes |
|
|
361
|
+
| `trades` | Trade/fill updates | Yes |
|
|
362
|
+
| `ticker` | Price and 24h volume | Yes |
|
|
363
|
+
| `all_tickers` | All market tickers | No |
|
|
364
|
+
|
|
365
|
+
## Error Handling
|
|
366
|
+
|
|
367
|
+
```python
|
|
368
|
+
from oxarchive import Client, OxArchiveError
|
|
369
|
+
|
|
370
|
+
client = Client(api_key="ox_your_api_key")
|
|
371
|
+
|
|
372
|
+
try:
|
|
373
|
+
orderbook = client.orderbook.get("INVALID")
|
|
374
|
+
except OxArchiveError as e:
|
|
375
|
+
print(f"API Error: {e.message}")
|
|
376
|
+
print(f"Status Code: {e.code}")
|
|
377
|
+
print(f"Request ID: {e.request_id}")
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Type Hints
|
|
381
|
+
|
|
382
|
+
Full type hint support with Pydantic models:
|
|
383
|
+
|
|
384
|
+
```python
|
|
385
|
+
from oxarchive import Client, OrderBook, Trade
|
|
386
|
+
|
|
387
|
+
client = Client(api_key="ox_your_api_key")
|
|
388
|
+
|
|
389
|
+
orderbook: OrderBook = client.orderbook.get("BTC")
|
|
390
|
+
trades: list[Trade] = client.trades.recent("BTC")
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## Requirements
|
|
394
|
+
|
|
395
|
+
- Python 3.9+
|
|
396
|
+
- httpx
|
|
397
|
+
- pydantic
|
|
398
|
+
|
|
399
|
+
## License
|
|
400
|
+
|
|
401
|
+
MIT
|