oxarchive 0.4.1__tar.gz → 0.4.3__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.4.3}/PKG-INFO +77 -4
- {oxarchive-0.4.1 → oxarchive-0.4.3}/README.md +76 -3
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/__init__.py +5 -1
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/exchanges.py +5 -2
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/resources/__init__.py +2 -1
- oxarchive-0.4.3/oxarchive/resources/instruments.py +110 -0
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/resources/orderbook.py +18 -1
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/types.py +48 -1
- {oxarchive-0.4.1 → oxarchive-0.4.3}/pyproject.toml +1 -1
- oxarchive-0.4.1/oxarchive/resources/instruments.py +0 -56
- {oxarchive-0.4.1 → oxarchive-0.4.3}/.gitignore +0 -0
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/client.py +0 -0
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/http.py +0 -0
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/resources/funding.py +0 -0
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/resources/openinterest.py +0 -0
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/resources/trades.py +0 -0
- {oxarchive-0.4.1 → oxarchive-0.4.3}/oxarchive/websocket.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oxarchive
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
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,46 @@ orderbook = await client.hyperliquid.orderbook.aget("BTC")
|
|
|
153
153
|
history = await client.hyperliquid.orderbook.ahistory("BTC", start=..., end=...)
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
+
#### Lighter Orderbook Granularity
|
|
157
|
+
|
|
158
|
+
Lighter.xyz orderbook history supports a `granularity` parameter for different data resolutions. Tier restrictions apply.
|
|
159
|
+
|
|
160
|
+
| Granularity | Interval | Tier Required | Credit Multiplier |
|
|
161
|
+
|-------------|----------|---------------|-------------------|
|
|
162
|
+
| `checkpoint` | ~60s | Free+ | 1x |
|
|
163
|
+
| `30s` | 30s | Build+ | 2x |
|
|
164
|
+
| `10s` | 10s | Build+ | 3x |
|
|
165
|
+
| `1s` | 1s | Pro+ | 10x |
|
|
166
|
+
| `tick` | tick-level | Enterprise | 20x |
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
# Get Lighter orderbook history with 10s resolution (Build+ tier)
|
|
170
|
+
history = client.lighter.orderbook.history(
|
|
171
|
+
"BTC",
|
|
172
|
+
start="2024-01-01",
|
|
173
|
+
end="2024-01-02",
|
|
174
|
+
granularity="10s"
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Get 1-second resolution (Pro+ tier)
|
|
178
|
+
history = client.lighter.orderbook.history(
|
|
179
|
+
"BTC",
|
|
180
|
+
start="2024-01-01",
|
|
181
|
+
end="2024-01-02",
|
|
182
|
+
granularity="1s"
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
# Tick-level data (Enterprise tier) - returns checkpoint + raw deltas
|
|
186
|
+
history = client.lighter.orderbook.history(
|
|
187
|
+
"BTC",
|
|
188
|
+
start="2024-01-01",
|
|
189
|
+
end="2024-01-02",
|
|
190
|
+
granularity="tick"
|
|
191
|
+
)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Note:** The `granularity` parameter is ignored for Hyperliquid orderbook history.
|
|
195
|
+
|
|
156
196
|
### Trades
|
|
157
197
|
|
|
158
198
|
The trades API uses cursor-based pagination for efficient retrieval of large datasets.
|
|
@@ -187,17 +227,47 @@ result = await client.hyperliquid.trades.alist("ETH", start=..., end=...)
|
|
|
187
227
|
### Instruments
|
|
188
228
|
|
|
189
229
|
```python
|
|
190
|
-
# List all trading instruments
|
|
230
|
+
# List all trading instruments (Hyperliquid)
|
|
191
231
|
instruments = client.hyperliquid.instruments.list()
|
|
192
232
|
|
|
193
233
|
# Get specific instrument details
|
|
194
234
|
btc = client.hyperliquid.instruments.get("BTC")
|
|
235
|
+
print(f"BTC size decimals: {btc.sz_decimals}")
|
|
195
236
|
|
|
196
237
|
# Async versions
|
|
197
238
|
instruments = await client.hyperliquid.instruments.alist()
|
|
198
239
|
btc = await client.hyperliquid.instruments.aget("BTC")
|
|
199
240
|
```
|
|
200
241
|
|
|
242
|
+
#### Lighter.xyz Instruments
|
|
243
|
+
|
|
244
|
+
Lighter instruments have a different schema with additional fields for fees, market IDs, and minimum order amounts:
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
# List Lighter instruments (returns LighterInstrument, not Instrument)
|
|
248
|
+
lighter_instruments = client.lighter.instruments.list()
|
|
249
|
+
|
|
250
|
+
# Get specific Lighter instrument
|
|
251
|
+
eth = client.lighter.instruments.get("ETH")
|
|
252
|
+
print(f"ETH taker fee: {eth.taker_fee}")
|
|
253
|
+
print(f"ETH maker fee: {eth.maker_fee}")
|
|
254
|
+
print(f"ETH market ID: {eth.market_id}")
|
|
255
|
+
print(f"ETH min base amount: {eth.min_base_amount}")
|
|
256
|
+
|
|
257
|
+
# Async versions
|
|
258
|
+
lighter_instruments = await client.lighter.instruments.alist()
|
|
259
|
+
eth = await client.lighter.instruments.aget("ETH")
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**Key differences:**
|
|
263
|
+
| Field | Hyperliquid (`Instrument`) | Lighter (`LighterInstrument`) |
|
|
264
|
+
|-------|---------------------------|------------------------------|
|
|
265
|
+
| Symbol | `name` | `symbol` |
|
|
266
|
+
| Size decimals | `sz_decimals` | `size_decimals` |
|
|
267
|
+
| Fee info | Not available | `taker_fee`, `maker_fee`, `liquidation_fee` |
|
|
268
|
+
| Market ID | Not available | `market_id` |
|
|
269
|
+
| Min amounts | Not available | `min_base_amount`, `min_quote_amount` |
|
|
270
|
+
|
|
201
271
|
### Funding Rates
|
|
202
272
|
|
|
203
273
|
```python
|
|
@@ -449,8 +519,8 @@ except OxArchiveError as e:
|
|
|
449
519
|
Full type hint support with Pydantic models:
|
|
450
520
|
|
|
451
521
|
```python
|
|
452
|
-
from oxarchive import Client
|
|
453
|
-
from oxarchive.types import OrderBook, Trade, Instrument, FundingRate, OpenInterest
|
|
522
|
+
from oxarchive import Client, LighterGranularity
|
|
523
|
+
from oxarchive.types import OrderBook, Trade, Instrument, LighterInstrument, FundingRate, OpenInterest
|
|
454
524
|
from oxarchive.resources.trades import CursorResponse
|
|
455
525
|
|
|
456
526
|
client = Client(api_key="ox_your_api_key")
|
|
@@ -458,6 +528,9 @@ client = Client(api_key="ox_your_api_key")
|
|
|
458
528
|
orderbook: OrderBook = client.orderbook.get("BTC")
|
|
459
529
|
trades: list[Trade] = client.trades.recent("BTC")
|
|
460
530
|
result: CursorResponse = client.trades.list("BTC", start=..., end=...)
|
|
531
|
+
|
|
532
|
+
# Lighter granularity type hint
|
|
533
|
+
granularity: LighterGranularity = "10s"
|
|
461
534
|
```
|
|
462
535
|
|
|
463
536
|
## Requirements
|
|
@@ -116,6 +116,46 @@ orderbook = await client.hyperliquid.orderbook.aget("BTC")
|
|
|
116
116
|
history = await client.hyperliquid.orderbook.ahistory("BTC", start=..., end=...)
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
#### Lighter Orderbook Granularity
|
|
120
|
+
|
|
121
|
+
Lighter.xyz orderbook history supports a `granularity` parameter for different data resolutions. Tier restrictions apply.
|
|
122
|
+
|
|
123
|
+
| Granularity | Interval | Tier Required | Credit Multiplier |
|
|
124
|
+
|-------------|----------|---------------|-------------------|
|
|
125
|
+
| `checkpoint` | ~60s | Free+ | 1x |
|
|
126
|
+
| `30s` | 30s | Build+ | 2x |
|
|
127
|
+
| `10s` | 10s | Build+ | 3x |
|
|
128
|
+
| `1s` | 1s | Pro+ | 10x |
|
|
129
|
+
| `tick` | tick-level | Enterprise | 20x |
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# Get Lighter orderbook history with 10s resolution (Build+ tier)
|
|
133
|
+
history = client.lighter.orderbook.history(
|
|
134
|
+
"BTC",
|
|
135
|
+
start="2024-01-01",
|
|
136
|
+
end="2024-01-02",
|
|
137
|
+
granularity="10s"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Get 1-second resolution (Pro+ tier)
|
|
141
|
+
history = client.lighter.orderbook.history(
|
|
142
|
+
"BTC",
|
|
143
|
+
start="2024-01-01",
|
|
144
|
+
end="2024-01-02",
|
|
145
|
+
granularity="1s"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Tick-level data (Enterprise tier) - returns checkpoint + raw deltas
|
|
149
|
+
history = client.lighter.orderbook.history(
|
|
150
|
+
"BTC",
|
|
151
|
+
start="2024-01-01",
|
|
152
|
+
end="2024-01-02",
|
|
153
|
+
granularity="tick"
|
|
154
|
+
)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Note:** The `granularity` parameter is ignored for Hyperliquid orderbook history.
|
|
158
|
+
|
|
119
159
|
### Trades
|
|
120
160
|
|
|
121
161
|
The trades API uses cursor-based pagination for efficient retrieval of large datasets.
|
|
@@ -150,17 +190,47 @@ result = await client.hyperliquid.trades.alist("ETH", start=..., end=...)
|
|
|
150
190
|
### Instruments
|
|
151
191
|
|
|
152
192
|
```python
|
|
153
|
-
# List all trading instruments
|
|
193
|
+
# List all trading instruments (Hyperliquid)
|
|
154
194
|
instruments = client.hyperliquid.instruments.list()
|
|
155
195
|
|
|
156
196
|
# Get specific instrument details
|
|
157
197
|
btc = client.hyperliquid.instruments.get("BTC")
|
|
198
|
+
print(f"BTC size decimals: {btc.sz_decimals}")
|
|
158
199
|
|
|
159
200
|
# Async versions
|
|
160
201
|
instruments = await client.hyperliquid.instruments.alist()
|
|
161
202
|
btc = await client.hyperliquid.instruments.aget("BTC")
|
|
162
203
|
```
|
|
163
204
|
|
|
205
|
+
#### Lighter.xyz Instruments
|
|
206
|
+
|
|
207
|
+
Lighter instruments have a different schema with additional fields for fees, market IDs, and minimum order amounts:
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
# List Lighter instruments (returns LighterInstrument, not Instrument)
|
|
211
|
+
lighter_instruments = client.lighter.instruments.list()
|
|
212
|
+
|
|
213
|
+
# Get specific Lighter instrument
|
|
214
|
+
eth = client.lighter.instruments.get("ETH")
|
|
215
|
+
print(f"ETH taker fee: {eth.taker_fee}")
|
|
216
|
+
print(f"ETH maker fee: {eth.maker_fee}")
|
|
217
|
+
print(f"ETH market ID: {eth.market_id}")
|
|
218
|
+
print(f"ETH min base amount: {eth.min_base_amount}")
|
|
219
|
+
|
|
220
|
+
# Async versions
|
|
221
|
+
lighter_instruments = await client.lighter.instruments.alist()
|
|
222
|
+
eth = await client.lighter.instruments.aget("ETH")
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**Key differences:**
|
|
226
|
+
| Field | Hyperliquid (`Instrument`) | Lighter (`LighterInstrument`) |
|
|
227
|
+
|-------|---------------------------|------------------------------|
|
|
228
|
+
| Symbol | `name` | `symbol` |
|
|
229
|
+
| Size decimals | `sz_decimals` | `size_decimals` |
|
|
230
|
+
| Fee info | Not available | `taker_fee`, `maker_fee`, `liquidation_fee` |
|
|
231
|
+
| Market ID | Not available | `market_id` |
|
|
232
|
+
| Min amounts | Not available | `min_base_amount`, `min_quote_amount` |
|
|
233
|
+
|
|
164
234
|
### Funding Rates
|
|
165
235
|
|
|
166
236
|
```python
|
|
@@ -412,8 +482,8 @@ except OxArchiveError as e:
|
|
|
412
482
|
Full type hint support with Pydantic models:
|
|
413
483
|
|
|
414
484
|
```python
|
|
415
|
-
from oxarchive import Client
|
|
416
|
-
from oxarchive.types import OrderBook, Trade, Instrument, FundingRate, OpenInterest
|
|
485
|
+
from oxarchive import Client, LighterGranularity
|
|
486
|
+
from oxarchive.types import OrderBook, Trade, Instrument, LighterInstrument, FundingRate, OpenInterest
|
|
417
487
|
from oxarchive.resources.trades import CursorResponse
|
|
418
488
|
|
|
419
489
|
client = Client(api_key="ox_your_api_key")
|
|
@@ -421,6 +491,9 @@ client = Client(api_key="ox_your_api_key")
|
|
|
421
491
|
orderbook: OrderBook = client.orderbook.get("BTC")
|
|
422
492
|
trades: list[Trade] = client.trades.recent("BTC")
|
|
423
493
|
result: CursorResponse = client.trades.list("BTC", start=..., end=...)
|
|
494
|
+
|
|
495
|
+
# Lighter granularity type hint
|
|
496
|
+
granularity: LighterGranularity = "10s"
|
|
424
497
|
```
|
|
425
498
|
|
|
426
499
|
## Requirements
|
|
@@ -23,10 +23,12 @@ 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,
|
|
32
34
|
OxArchiveError,
|
|
@@ -63,7 +65,7 @@ except ImportError:
|
|
|
63
65
|
OxArchiveWs = None # type: ignore
|
|
64
66
|
WsOptions = None # type: ignore
|
|
65
67
|
|
|
66
|
-
__version__ = "0.4.
|
|
68
|
+
__version__ = "0.4.3"
|
|
67
69
|
|
|
68
70
|
__all__ = [
|
|
69
71
|
# Client
|
|
@@ -78,6 +80,8 @@ __all__ = [
|
|
|
78
80
|
"OrderBook",
|
|
79
81
|
"Trade",
|
|
80
82
|
"Instrument",
|
|
83
|
+
"LighterInstrument",
|
|
84
|
+
"LighterGranularity",
|
|
81
85
|
"FundingRate",
|
|
82
86
|
"OpenInterest",
|
|
83
87
|
"OxArchiveError",
|
|
@@ -7,6 +7,7 @@ from .resources import (
|
|
|
7
7
|
OrderBookResource,
|
|
8
8
|
TradesResource,
|
|
9
9
|
InstrumentsResource,
|
|
10
|
+
LighterInstrumentsResource,
|
|
10
11
|
FundingResource,
|
|
11
12
|
OpenInterestResource,
|
|
12
13
|
)
|
|
@@ -54,6 +55,8 @@ class LighterClient:
|
|
|
54
55
|
>>> client = oxarchive.Client(api_key="...")
|
|
55
56
|
>>> orderbook = client.lighter.orderbook.get("BTC")
|
|
56
57
|
>>> trades = client.lighter.trades.list("ETH", start=..., end=...)
|
|
58
|
+
>>> instruments = client.lighter.instruments.list()
|
|
59
|
+
>>> print(f"ETH taker fee: {instruments[0].taker_fee}")
|
|
57
60
|
"""
|
|
58
61
|
|
|
59
62
|
def __init__(self, http: HttpClient):
|
|
@@ -66,8 +69,8 @@ class LighterClient:
|
|
|
66
69
|
self.trades = TradesResource(http, base_path)
|
|
67
70
|
"""Trade/fill history"""
|
|
68
71
|
|
|
69
|
-
self.instruments =
|
|
70
|
-
"""Trading instruments metadata"""
|
|
72
|
+
self.instruments = LighterInstrumentsResource(http, base_path)
|
|
73
|
+
"""Trading instruments metadata (returns LighterInstrument with fees, min amounts, etc.)"""
|
|
71
74
|
|
|
72
75
|
self.funding = FundingResource(http, base_path)
|
|
73
76
|
"""Funding rates"""
|
|
@@ -2,7 +2,7 @@
|
|
|
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
8
|
|
|
@@ -10,6 +10,7 @@ __all__ = [
|
|
|
10
10
|
"OrderBookResource",
|
|
11
11
|
"TradesResource",
|
|
12
12
|
"InstrumentsResource",
|
|
13
|
+
"LighterInstrumentsResource",
|
|
13
14
|
"FundingResource",
|
|
14
15
|
"OpenInterestResource",
|
|
15
16
|
]
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Instruments API resource."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ..http import HttpClient
|
|
6
|
+
from ..types import Instrument, LighterInstrument
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class InstrumentsResource:
|
|
10
|
+
"""
|
|
11
|
+
Instruments API resource.
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
>>> # List all instruments
|
|
15
|
+
>>> instruments = client.instruments.list()
|
|
16
|
+
>>>
|
|
17
|
+
>>> # Get specific instrument
|
|
18
|
+
>>> btc = client.instruments.get("BTC")
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, http: HttpClient, base_path: str = "/v1"):
|
|
22
|
+
self._http = http
|
|
23
|
+
self._base_path = base_path
|
|
24
|
+
|
|
25
|
+
def list(self) -> list[Instrument]:
|
|
26
|
+
"""
|
|
27
|
+
List all available trading instruments.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
List of instruments
|
|
31
|
+
"""
|
|
32
|
+
data = self._http.get(f"{self._base_path}/instruments")
|
|
33
|
+
return [Instrument.model_validate(item) for item in data["data"]]
|
|
34
|
+
|
|
35
|
+
async def alist(self) -> list[Instrument]:
|
|
36
|
+
"""Async version of list()."""
|
|
37
|
+
data = await self._http.aget(f"{self._base_path}/instruments")
|
|
38
|
+
return [Instrument.model_validate(item) for item in data["data"]]
|
|
39
|
+
|
|
40
|
+
def get(self, coin: str) -> Instrument:
|
|
41
|
+
"""
|
|
42
|
+
Get a specific instrument by coin symbol.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Instrument details
|
|
49
|
+
"""
|
|
50
|
+
data = self._http.get(f"{self._base_path}/instruments/{coin.upper()}")
|
|
51
|
+
return Instrument.model_validate(data["data"])
|
|
52
|
+
|
|
53
|
+
async def aget(self, coin: str) -> Instrument:
|
|
54
|
+
"""Async version of get()."""
|
|
55
|
+
data = await self._http.aget(f"{self._base_path}/instruments/{coin.upper()}")
|
|
56
|
+
return Instrument.model_validate(data["data"])
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class LighterInstrumentsResource:
|
|
60
|
+
"""
|
|
61
|
+
Lighter.xyz Instruments API resource.
|
|
62
|
+
|
|
63
|
+
Lighter instruments have a different schema than Hyperliquid with more
|
|
64
|
+
detailed market configuration including fees and minimum amounts.
|
|
65
|
+
|
|
66
|
+
Example:
|
|
67
|
+
>>> # List all Lighter instruments
|
|
68
|
+
>>> instruments = client.lighter.instruments.list()
|
|
69
|
+
>>>
|
|
70
|
+
>>> # Get specific instrument
|
|
71
|
+
>>> btc = client.lighter.instruments.get("BTC")
|
|
72
|
+
>>> print(f"Taker fee: {btc.taker_fee}")
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, http: HttpClient, base_path: str = "/v1/lighter"):
|
|
76
|
+
self._http = http
|
|
77
|
+
self._base_path = base_path
|
|
78
|
+
|
|
79
|
+
def list(self) -> list[LighterInstrument]:
|
|
80
|
+
"""
|
|
81
|
+
List all available Lighter trading instruments.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
List of Lighter instruments with full market configuration
|
|
85
|
+
"""
|
|
86
|
+
data = self._http.get(f"{self._base_path}/instruments")
|
|
87
|
+
return [LighterInstrument.model_validate(item) for item in data["data"]]
|
|
88
|
+
|
|
89
|
+
async def alist(self) -> list[LighterInstrument]:
|
|
90
|
+
"""Async version of list()."""
|
|
91
|
+
data = await self._http.aget(f"{self._base_path}/instruments")
|
|
92
|
+
return [LighterInstrument.model_validate(item) for item in data["data"]]
|
|
93
|
+
|
|
94
|
+
def get(self, coin: str) -> LighterInstrument:
|
|
95
|
+
"""
|
|
96
|
+
Get a specific Lighter instrument by coin symbol.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Lighter instrument details with full market configuration
|
|
103
|
+
"""
|
|
104
|
+
data = self._http.get(f"{self._base_path}/instruments/{coin.upper()}")
|
|
105
|
+
return LighterInstrument.model_validate(data["data"])
|
|
106
|
+
|
|
107
|
+
async def aget(self, coin: str) -> LighterInstrument:
|
|
108
|
+
"""Async version of get()."""
|
|
109
|
+
data = await self._http.aget(f"{self._base_path}/instruments/{coin.upper()}")
|
|
110
|
+
return LighterInstrument.model_validate(data["data"])
|
|
@@ -6,8 +6,13 @@ from datetime import datetime
|
|
|
6
6
|
from typing import Optional, Union
|
|
7
7
|
|
|
8
8
|
from ..http import HttpClient
|
|
9
|
+
from typing import Literal
|
|
10
|
+
|
|
9
11
|
from ..types import CursorResponse, OrderBook, Timestamp
|
|
10
12
|
|
|
13
|
+
# Lighter orderbook granularity levels (Lighter.xyz only)
|
|
14
|
+
LighterGranularity = Literal["checkpoint", "30s", "10s", "1s", "tick"]
|
|
15
|
+
|
|
11
16
|
|
|
12
17
|
class OrderBookResource:
|
|
13
18
|
"""
|
|
@@ -101,6 +106,7 @@ class OrderBookResource:
|
|
|
101
106
|
cursor: Optional[Timestamp] = None,
|
|
102
107
|
limit: Optional[int] = None,
|
|
103
108
|
depth: Optional[int] = None,
|
|
109
|
+
granularity: Optional[LighterGranularity] = None,
|
|
104
110
|
) -> CursorResponse[list[OrderBook]]:
|
|
105
111
|
"""
|
|
106
112
|
Get historical order book snapshots with cursor-based pagination.
|
|
@@ -112,6 +118,9 @@ class OrderBookResource:
|
|
|
112
118
|
cursor: Cursor from previous response's next_cursor (timestamp)
|
|
113
119
|
limit: Maximum number of results (default: 100, max: 1000)
|
|
114
120
|
depth: Number of price levels per side
|
|
121
|
+
granularity: Data resolution for Lighter orderbook (Lighter.xyz only, ignored for Hyperliquid).
|
|
122
|
+
Options: 'checkpoint' (1min, default), '30s', '10s', '1s', 'tick'.
|
|
123
|
+
Tier restrictions apply. Credit multipliers: checkpoint=1x, 30s=2x, 10s=3x, 1s=10x, tick=20x.
|
|
115
124
|
|
|
116
125
|
Returns:
|
|
117
126
|
CursorResponse with order book snapshots and next_cursor for pagination
|
|
@@ -124,6 +133,11 @@ class OrderBookResource:
|
|
|
124
133
|
... "BTC", start=start, end=end, cursor=result.next_cursor, limit=1000
|
|
125
134
|
... )
|
|
126
135
|
... snapshots.extend(result.data)
|
|
136
|
+
>>>
|
|
137
|
+
>>> # Lighter.xyz with 10s granularity (Build+ tier)
|
|
138
|
+
>>> result = client.lighter.orderbook.history(
|
|
139
|
+
... "BTC", start=start, end=end, granularity="10s"
|
|
140
|
+
... )
|
|
127
141
|
"""
|
|
128
142
|
data = self._http.get(
|
|
129
143
|
f"{self._base_path}/orderbook/{coin.upper()}/history",
|
|
@@ -133,6 +147,7 @@ class OrderBookResource:
|
|
|
133
147
|
"cursor": self._convert_timestamp(cursor),
|
|
134
148
|
"limit": limit,
|
|
135
149
|
"depth": depth,
|
|
150
|
+
"granularity": granularity,
|
|
136
151
|
},
|
|
137
152
|
)
|
|
138
153
|
return CursorResponse(
|
|
@@ -149,8 +164,9 @@ class OrderBookResource:
|
|
|
149
164
|
cursor: Optional[Timestamp] = None,
|
|
150
165
|
limit: Optional[int] = None,
|
|
151
166
|
depth: Optional[int] = None,
|
|
167
|
+
granularity: Optional[LighterGranularity] = None,
|
|
152
168
|
) -> CursorResponse[list[OrderBook]]:
|
|
153
|
-
"""Async version of history(). start and end are required."""
|
|
169
|
+
"""Async version of history(). start and end are required. See history() for granularity details."""
|
|
154
170
|
data = await self._http.aget(
|
|
155
171
|
f"{self._base_path}/orderbook/{coin.upper()}/history",
|
|
156
172
|
params={
|
|
@@ -159,6 +175,7 @@ class OrderBookResource:
|
|
|
159
175
|
"cursor": self._convert_timestamp(cursor),
|
|
160
176
|
"limit": limit,
|
|
161
177
|
"depth": depth,
|
|
178
|
+
"granularity": granularity,
|
|
162
179
|
},
|
|
163
180
|
)
|
|
164
181
|
return CursorResponse(
|
|
@@ -140,7 +140,7 @@ class Trade(BaseModel):
|
|
|
140
140
|
|
|
141
141
|
|
|
142
142
|
class Instrument(BaseModel):
|
|
143
|
-
"""Trading instrument specification."""
|
|
143
|
+
"""Trading instrument specification (Hyperliquid)."""
|
|
144
144
|
|
|
145
145
|
model_config = {"populate_by_name": True}
|
|
146
146
|
|
|
@@ -163,6 +163,53 @@ class Instrument(BaseModel):
|
|
|
163
163
|
"""Whether the instrument is currently tradeable."""
|
|
164
164
|
|
|
165
165
|
|
|
166
|
+
class LighterInstrument(BaseModel):
|
|
167
|
+
"""Trading instrument specification (Lighter.xyz).
|
|
168
|
+
|
|
169
|
+
Lighter instruments have a different schema than Hyperliquid with more
|
|
170
|
+
detailed market configuration including fees and minimum amounts.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
symbol: str
|
|
174
|
+
"""Instrument symbol (e.g., BTC, ETH)."""
|
|
175
|
+
|
|
176
|
+
market_id: int
|
|
177
|
+
"""Unique market identifier."""
|
|
178
|
+
|
|
179
|
+
market_type: str
|
|
180
|
+
"""Market type (e.g., 'perp')."""
|
|
181
|
+
|
|
182
|
+
status: str
|
|
183
|
+
"""Market status (e.g., 'active')."""
|
|
184
|
+
|
|
185
|
+
taker_fee: float
|
|
186
|
+
"""Taker fee rate (e.g., 0.0005 = 0.05%)."""
|
|
187
|
+
|
|
188
|
+
maker_fee: float
|
|
189
|
+
"""Maker fee rate (e.g., 0.0002 = 0.02%)."""
|
|
190
|
+
|
|
191
|
+
liquidation_fee: float
|
|
192
|
+
"""Liquidation fee rate."""
|
|
193
|
+
|
|
194
|
+
min_base_amount: float
|
|
195
|
+
"""Minimum order size in base currency."""
|
|
196
|
+
|
|
197
|
+
min_quote_amount: float
|
|
198
|
+
"""Minimum order size in quote currency."""
|
|
199
|
+
|
|
200
|
+
size_decimals: int
|
|
201
|
+
"""Size decimal precision."""
|
|
202
|
+
|
|
203
|
+
price_decimals: int
|
|
204
|
+
"""Price decimal precision."""
|
|
205
|
+
|
|
206
|
+
quote_decimals: int
|
|
207
|
+
"""Quote currency decimal precision."""
|
|
208
|
+
|
|
209
|
+
is_active: bool
|
|
210
|
+
"""Whether the instrument is currently tradeable."""
|
|
211
|
+
|
|
212
|
+
|
|
166
213
|
# =============================================================================
|
|
167
214
|
# Funding Types
|
|
168
215
|
# =============================================================================
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"""Instruments API resource."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from ..http import HttpClient
|
|
6
|
-
from ..types import Instrument
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class InstrumentsResource:
|
|
10
|
-
"""
|
|
11
|
-
Instruments API resource.
|
|
12
|
-
|
|
13
|
-
Example:
|
|
14
|
-
>>> # List all instruments
|
|
15
|
-
>>> instruments = client.instruments.list()
|
|
16
|
-
>>>
|
|
17
|
-
>>> # Get specific instrument
|
|
18
|
-
>>> btc = client.instruments.get("BTC")
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
def __init__(self, http: HttpClient, base_path: str = "/v1"):
|
|
22
|
-
self._http = http
|
|
23
|
-
self._base_path = base_path
|
|
24
|
-
|
|
25
|
-
def list(self) -> list[Instrument]:
|
|
26
|
-
"""
|
|
27
|
-
List all available trading instruments.
|
|
28
|
-
|
|
29
|
-
Returns:
|
|
30
|
-
List of instruments
|
|
31
|
-
"""
|
|
32
|
-
data = self._http.get(f"{self._base_path}/instruments")
|
|
33
|
-
return [Instrument.model_validate(item) for item in data["data"]]
|
|
34
|
-
|
|
35
|
-
async def alist(self) -> list[Instrument]:
|
|
36
|
-
"""Async version of list()."""
|
|
37
|
-
data = await self._http.aget(f"{self._base_path}/instruments")
|
|
38
|
-
return [Instrument.model_validate(item) for item in data["data"]]
|
|
39
|
-
|
|
40
|
-
def get(self, coin: str) -> Instrument:
|
|
41
|
-
"""
|
|
42
|
-
Get a specific instrument by coin symbol.
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
46
|
-
|
|
47
|
-
Returns:
|
|
48
|
-
Instrument details
|
|
49
|
-
"""
|
|
50
|
-
data = self._http.get(f"{self._base_path}/instruments/{coin.upper()}")
|
|
51
|
-
return Instrument.model_validate(data["data"])
|
|
52
|
-
|
|
53
|
-
async def aget(self, coin: str) -> Instrument:
|
|
54
|
-
"""Async version of get()."""
|
|
55
|
-
data = await self._http.aget(f"{self._base_path}/instruments/{coin.upper()}")
|
|
56
|
-
return Instrument.model_validate(data["data"])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|