oxarchive 0.3.11__py3-none-any.whl → 0.4.1__py3-none-any.whl
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/__init__.py +15 -6
- oxarchive/client.py +39 -17
- oxarchive/exchanges.py +76 -0
- oxarchive/resources/funding.py +6 -5
- oxarchive/resources/instruments.py +6 -5
- oxarchive/resources/openinterest.py +6 -5
- oxarchive/resources/orderbook.py +13 -9
- oxarchive/resources/trades.py +6 -5
- {oxarchive-0.3.11.dist-info → oxarchive-0.4.1.dist-info}/METADATA +62 -34
- oxarchive-0.4.1.dist-info/RECORD +15 -0
- oxarchive-0.3.11.dist-info/RECORD +0 -14
- {oxarchive-0.3.11.dist-info → oxarchive-0.4.1.dist-info}/WHEEL +0 -0
oxarchive/__init__.py
CHANGED
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
"""
|
|
2
2
|
oxarchive - Official Python SDK for 0xarchive
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Historical Market Data API for multiple exchanges:
|
|
5
|
+
- Hyperliquid (perpetuals data from April 2023)
|
|
6
|
+
- Lighter.xyz (perpetuals data)
|
|
5
7
|
|
|
6
8
|
Example:
|
|
7
9
|
>>> from oxarchive import Client
|
|
8
10
|
>>>
|
|
9
11
|
>>> client = Client(api_key="ox_your_api_key")
|
|
10
12
|
>>>
|
|
11
|
-
>>> #
|
|
12
|
-
>>>
|
|
13
|
-
>>> print(f"BTC mid price: {
|
|
13
|
+
>>> # Hyperliquid data
|
|
14
|
+
>>> hl_orderbook = client.hyperliquid.orderbook.get("BTC")
|
|
15
|
+
>>> print(f"BTC mid price: {hl_orderbook.mid_price}")
|
|
16
|
+
>>>
|
|
17
|
+
>>> # Lighter.xyz data
|
|
18
|
+
>>> lighter_orderbook = client.lighter.orderbook.get("BTC")
|
|
14
19
|
>>>
|
|
15
20
|
>>> # Get historical snapshots
|
|
16
|
-
>>> history = client.orderbook.history("ETH", start="2024-01-01", end="2024-01-02")
|
|
21
|
+
>>> history = client.hyperliquid.orderbook.history("ETH", start="2024-01-01", end="2024-01-02")
|
|
17
22
|
"""
|
|
18
23
|
|
|
19
24
|
from .client import Client
|
|
25
|
+
from .exchanges import HyperliquidClient, LighterClient
|
|
20
26
|
from .types import (
|
|
21
27
|
OrderBook,
|
|
22
28
|
Trade,
|
|
@@ -57,11 +63,14 @@ except ImportError:
|
|
|
57
63
|
OxArchiveWs = None # type: ignore
|
|
58
64
|
WsOptions = None # type: ignore
|
|
59
65
|
|
|
60
|
-
__version__ = "0.
|
|
66
|
+
__version__ = "0.4.1"
|
|
61
67
|
|
|
62
68
|
__all__ = [
|
|
63
69
|
# Client
|
|
64
70
|
"Client",
|
|
71
|
+
# Exchange Clients
|
|
72
|
+
"HyperliquidClient",
|
|
73
|
+
"LighterClient",
|
|
65
74
|
# WebSocket Client
|
|
66
75
|
"OxArchiveWs",
|
|
67
76
|
"WsOptions",
|
oxarchive/client.py
CHANGED
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
7
|
from .http import HttpClient
|
|
8
|
+
from .exchanges import HyperliquidClient, LighterClient
|
|
8
9
|
from .resources import (
|
|
9
10
|
OrderBookResource,
|
|
10
11
|
TradesResource,
|
|
@@ -21,20 +22,27 @@ class Client:
|
|
|
21
22
|
"""
|
|
22
23
|
0xarchive API client.
|
|
23
24
|
|
|
25
|
+
Supports multiple exchanges:
|
|
26
|
+
- `client.hyperliquid` - Hyperliquid perpetuals (April 2023+)
|
|
27
|
+
- `client.lighter` - Lighter.xyz perpetuals
|
|
28
|
+
|
|
24
29
|
Example:
|
|
25
30
|
>>> from oxarchive import Client
|
|
26
31
|
>>>
|
|
27
32
|
>>> client = Client(api_key="ox_your_api_key")
|
|
28
33
|
>>>
|
|
29
|
-
>>> #
|
|
30
|
-
>>>
|
|
31
|
-
>>> print(f"BTC mid price: {
|
|
34
|
+
>>> # Hyperliquid data
|
|
35
|
+
>>> hl_orderbook = client.hyperliquid.orderbook.get("BTC")
|
|
36
|
+
>>> print(f"BTC mid price: {hl_orderbook.mid_price}")
|
|
37
|
+
>>>
|
|
38
|
+
>>> # Lighter.xyz data
|
|
39
|
+
>>> lighter_orderbook = client.lighter.orderbook.get("BTC")
|
|
32
40
|
>>>
|
|
33
41
|
>>> # Get historical snapshots
|
|
34
|
-
>>> history = client.orderbook.history("ETH", start="2024-01-01", end="2024-01-02")
|
|
42
|
+
>>> history = client.hyperliquid.orderbook.history("ETH", start="2024-01-01", end="2024-01-02")
|
|
35
43
|
>>>
|
|
36
44
|
>>> # List all instruments
|
|
37
|
-
>>> instruments = client.instruments.list()
|
|
45
|
+
>>> instruments = client.hyperliquid.instruments.list()
|
|
38
46
|
|
|
39
47
|
Async example:
|
|
40
48
|
>>> import asyncio
|
|
@@ -42,11 +50,15 @@ class Client:
|
|
|
42
50
|
>>>
|
|
43
51
|
>>> async def main():
|
|
44
52
|
... client = Client(api_key="ox_your_api_key")
|
|
45
|
-
... orderbook = await client.orderbook.aget("BTC")
|
|
53
|
+
... orderbook = await client.hyperliquid.orderbook.aget("BTC")
|
|
46
54
|
... print(f"BTC mid price: {orderbook.mid_price}")
|
|
47
55
|
... await client.aclose()
|
|
48
56
|
>>>
|
|
49
57
|
>>> asyncio.run(main())
|
|
58
|
+
|
|
59
|
+
Legacy usage (deprecated, will be removed in v2.0):
|
|
60
|
+
>>> # These still work but use client.hyperliquid.* instead
|
|
61
|
+
>>> orderbook = client.orderbook.get("BTC") # deprecated
|
|
50
62
|
"""
|
|
51
63
|
|
|
52
64
|
def __init__(
|
|
@@ -73,21 +85,31 @@ class Client:
|
|
|
73
85
|
timeout=timeout or DEFAULT_TIMEOUT,
|
|
74
86
|
)
|
|
75
87
|
|
|
76
|
-
#
|
|
77
|
-
self.
|
|
78
|
-
"""
|
|
88
|
+
# Exchange-specific clients (recommended)
|
|
89
|
+
self.hyperliquid = HyperliquidClient(self._http)
|
|
90
|
+
"""Hyperliquid exchange data (orderbook, trades, funding, OI from April 2023)"""
|
|
91
|
+
|
|
92
|
+
self.lighter = LighterClient(self._http)
|
|
93
|
+
"""Lighter.xyz exchange data (August 2025+)"""
|
|
94
|
+
|
|
95
|
+
# Legacy resource namespaces (deprecated - use client.hyperliquid.* instead)
|
|
96
|
+
# These will be removed in v2.0
|
|
97
|
+
# Note: Using /v1/hyperliquid base path for backward compatibility
|
|
98
|
+
legacy_base = "/v1/hyperliquid"
|
|
99
|
+
self.orderbook = OrderBookResource(self._http, legacy_base)
|
|
100
|
+
"""[DEPRECATED] Use client.hyperliquid.orderbook instead"""
|
|
79
101
|
|
|
80
|
-
self.trades = TradesResource(self._http)
|
|
81
|
-
"""
|
|
102
|
+
self.trades = TradesResource(self._http, legacy_base)
|
|
103
|
+
"""[DEPRECATED] Use client.hyperliquid.trades instead"""
|
|
82
104
|
|
|
83
|
-
self.instruments = InstrumentsResource(self._http)
|
|
84
|
-
"""
|
|
105
|
+
self.instruments = InstrumentsResource(self._http, legacy_base)
|
|
106
|
+
"""[DEPRECATED] Use client.hyperliquid.instruments instead"""
|
|
85
107
|
|
|
86
|
-
self.funding = FundingResource(self._http)
|
|
87
|
-
"""
|
|
108
|
+
self.funding = FundingResource(self._http, legacy_base)
|
|
109
|
+
"""[DEPRECATED] Use client.hyperliquid.funding instead"""
|
|
88
110
|
|
|
89
|
-
self.open_interest = OpenInterestResource(self._http)
|
|
90
|
-
"""
|
|
111
|
+
self.open_interest = OpenInterestResource(self._http, legacy_base)
|
|
112
|
+
"""[DEPRECATED] Use client.hyperliquid.open_interest instead"""
|
|
91
113
|
|
|
92
114
|
def close(self) -> None:
|
|
93
115
|
"""Close the HTTP client and release resources."""
|
oxarchive/exchanges.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Exchange-specific client classes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .http import HttpClient
|
|
6
|
+
from .resources import (
|
|
7
|
+
OrderBookResource,
|
|
8
|
+
TradesResource,
|
|
9
|
+
InstrumentsResource,
|
|
10
|
+
FundingResource,
|
|
11
|
+
OpenInterestResource,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class HyperliquidClient:
|
|
16
|
+
"""
|
|
17
|
+
Hyperliquid exchange client.
|
|
18
|
+
|
|
19
|
+
Access Hyperliquid market data through the 0xarchive API.
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
>>> client = oxarchive.Client(api_key="...")
|
|
23
|
+
>>> orderbook = client.hyperliquid.orderbook.get("BTC")
|
|
24
|
+
>>> trades = client.hyperliquid.trades.list("ETH", start=..., end=...)
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, http: HttpClient):
|
|
28
|
+
self._http = http
|
|
29
|
+
base_path = "/v1/hyperliquid"
|
|
30
|
+
|
|
31
|
+
self.orderbook = OrderBookResource(http, base_path)
|
|
32
|
+
"""Order book data (L2 snapshots from April 2023)"""
|
|
33
|
+
|
|
34
|
+
self.trades = TradesResource(http, base_path)
|
|
35
|
+
"""Trade/fill history"""
|
|
36
|
+
|
|
37
|
+
self.instruments = InstrumentsResource(http, base_path)
|
|
38
|
+
"""Trading instruments metadata"""
|
|
39
|
+
|
|
40
|
+
self.funding = FundingResource(http, base_path)
|
|
41
|
+
"""Funding rates"""
|
|
42
|
+
|
|
43
|
+
self.open_interest = OpenInterestResource(http, base_path)
|
|
44
|
+
"""Open interest"""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class LighterClient:
|
|
48
|
+
"""
|
|
49
|
+
Lighter.xyz exchange client.
|
|
50
|
+
|
|
51
|
+
Access Lighter.xyz market data through the 0xarchive API.
|
|
52
|
+
|
|
53
|
+
Example:
|
|
54
|
+
>>> client = oxarchive.Client(api_key="...")
|
|
55
|
+
>>> orderbook = client.lighter.orderbook.get("BTC")
|
|
56
|
+
>>> trades = client.lighter.trades.list("ETH", start=..., end=...)
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def __init__(self, http: HttpClient):
|
|
60
|
+
self._http = http
|
|
61
|
+
base_path = "/v1/lighter"
|
|
62
|
+
|
|
63
|
+
self.orderbook = OrderBookResource(http, base_path)
|
|
64
|
+
"""Order book data (L2 snapshots)"""
|
|
65
|
+
|
|
66
|
+
self.trades = TradesResource(http, base_path)
|
|
67
|
+
"""Trade/fill history"""
|
|
68
|
+
|
|
69
|
+
self.instruments = InstrumentsResource(http, base_path)
|
|
70
|
+
"""Trading instruments metadata"""
|
|
71
|
+
|
|
72
|
+
self.funding = FundingResource(http, base_path)
|
|
73
|
+
"""Funding rates"""
|
|
74
|
+
|
|
75
|
+
self.open_interest = OpenInterestResource(http, base_path)
|
|
76
|
+
"""Open interest"""
|
oxarchive/resources/funding.py
CHANGED
|
@@ -21,8 +21,9 @@ class FundingResource:
|
|
|
21
21
|
>>> history = client.funding.history("ETH", start="2024-01-01", end="2024-01-07")
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
def __init__(self, http: HttpClient):
|
|
24
|
+
def __init__(self, http: HttpClient, base_path: str = "/v1"):
|
|
25
25
|
self._http = http
|
|
26
|
+
self._base_path = base_path
|
|
26
27
|
|
|
27
28
|
def _convert_timestamp(self, ts: Optional[Timestamp]) -> Optional[int]:
|
|
28
29
|
"""Convert timestamp to Unix milliseconds."""
|
|
@@ -72,7 +73,7 @@ class FundingResource:
|
|
|
72
73
|
... rates.extend(result.data)
|
|
73
74
|
"""
|
|
74
75
|
data = self._http.get(
|
|
75
|
-
f"/
|
|
76
|
+
f"{self._base_path}/funding/{coin.upper()}",
|
|
76
77
|
params={
|
|
77
78
|
"start": self._convert_timestamp(start),
|
|
78
79
|
"end": self._convert_timestamp(end),
|
|
@@ -96,7 +97,7 @@ class FundingResource:
|
|
|
96
97
|
) -> CursorResponse[list[FundingRate]]:
|
|
97
98
|
"""Async version of history(). start and end are required."""
|
|
98
99
|
data = await self._http.aget(
|
|
99
|
-
f"/
|
|
100
|
+
f"{self._base_path}/funding/{coin.upper()}",
|
|
100
101
|
params={
|
|
101
102
|
"start": self._convert_timestamp(start),
|
|
102
103
|
"end": self._convert_timestamp(end),
|
|
@@ -119,10 +120,10 @@ class FundingResource:
|
|
|
119
120
|
Returns:
|
|
120
121
|
Current funding rate
|
|
121
122
|
"""
|
|
122
|
-
data = self._http.get(f"/
|
|
123
|
+
data = self._http.get(f"{self._base_path}/funding/{coin.upper()}/current")
|
|
123
124
|
return FundingRate.model_validate(data["data"])
|
|
124
125
|
|
|
125
126
|
async def acurrent(self, coin: str) -> FundingRate:
|
|
126
127
|
"""Async version of current()."""
|
|
127
|
-
data = await self._http.aget(f"/
|
|
128
|
+
data = await self._http.aget(f"{self._base_path}/funding/{coin.upper()}/current")
|
|
128
129
|
return FundingRate.model_validate(data["data"])
|
|
@@ -18,8 +18,9 @@ class InstrumentsResource:
|
|
|
18
18
|
>>> btc = client.instruments.get("BTC")
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
def __init__(self, http: HttpClient):
|
|
21
|
+
def __init__(self, http: HttpClient, base_path: str = "/v1"):
|
|
22
22
|
self._http = http
|
|
23
|
+
self._base_path = base_path
|
|
23
24
|
|
|
24
25
|
def list(self) -> list[Instrument]:
|
|
25
26
|
"""
|
|
@@ -28,12 +29,12 @@ class InstrumentsResource:
|
|
|
28
29
|
Returns:
|
|
29
30
|
List of instruments
|
|
30
31
|
"""
|
|
31
|
-
data = self._http.get("/
|
|
32
|
+
data = self._http.get(f"{self._base_path}/instruments")
|
|
32
33
|
return [Instrument.model_validate(item) for item in data["data"]]
|
|
33
34
|
|
|
34
35
|
async def alist(self) -> list[Instrument]:
|
|
35
36
|
"""Async version of list()."""
|
|
36
|
-
data = await self._http.aget("/
|
|
37
|
+
data = await self._http.aget(f"{self._base_path}/instruments")
|
|
37
38
|
return [Instrument.model_validate(item) for item in data["data"]]
|
|
38
39
|
|
|
39
40
|
def get(self, coin: str) -> Instrument:
|
|
@@ -46,10 +47,10 @@ class InstrumentsResource:
|
|
|
46
47
|
Returns:
|
|
47
48
|
Instrument details
|
|
48
49
|
"""
|
|
49
|
-
data = self._http.get(f"/
|
|
50
|
+
data = self._http.get(f"{self._base_path}/instruments/{coin.upper()}")
|
|
50
51
|
return Instrument.model_validate(data["data"])
|
|
51
52
|
|
|
52
53
|
async def aget(self, coin: str) -> Instrument:
|
|
53
54
|
"""Async version of get()."""
|
|
54
|
-
data = await self._http.aget(f"/
|
|
55
|
+
data = await self._http.aget(f"{self._base_path}/instruments/{coin.upper()}")
|
|
55
56
|
return Instrument.model_validate(data["data"])
|
|
@@ -21,8 +21,9 @@ class OpenInterestResource:
|
|
|
21
21
|
>>> history = client.open_interest.history("ETH", start="2024-01-01", end="2024-01-07")
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
def __init__(self, http: HttpClient):
|
|
24
|
+
def __init__(self, http: HttpClient, base_path: str = "/v1"):
|
|
25
25
|
self._http = http
|
|
26
|
+
self._base_path = base_path
|
|
26
27
|
|
|
27
28
|
def _convert_timestamp(self, ts: Optional[Timestamp]) -> Optional[int]:
|
|
28
29
|
"""Convert timestamp to Unix milliseconds."""
|
|
@@ -72,7 +73,7 @@ class OpenInterestResource:
|
|
|
72
73
|
... records.extend(result.data)
|
|
73
74
|
"""
|
|
74
75
|
data = self._http.get(
|
|
75
|
-
f"/
|
|
76
|
+
f"{self._base_path}/openinterest/{coin.upper()}",
|
|
76
77
|
params={
|
|
77
78
|
"start": self._convert_timestamp(start),
|
|
78
79
|
"end": self._convert_timestamp(end),
|
|
@@ -96,7 +97,7 @@ class OpenInterestResource:
|
|
|
96
97
|
) -> CursorResponse[list[OpenInterest]]:
|
|
97
98
|
"""Async version of history(). start and end are required."""
|
|
98
99
|
data = await self._http.aget(
|
|
99
|
-
f"/
|
|
100
|
+
f"{self._base_path}/openinterest/{coin.upper()}",
|
|
100
101
|
params={
|
|
101
102
|
"start": self._convert_timestamp(start),
|
|
102
103
|
"end": self._convert_timestamp(end),
|
|
@@ -119,10 +120,10 @@ class OpenInterestResource:
|
|
|
119
120
|
Returns:
|
|
120
121
|
Current open interest
|
|
121
122
|
"""
|
|
122
|
-
data = self._http.get(f"/
|
|
123
|
+
data = self._http.get(f"{self._base_path}/openinterest/{coin.upper()}/current")
|
|
123
124
|
return OpenInterest.model_validate(data["data"])
|
|
124
125
|
|
|
125
126
|
async def acurrent(self, coin: str) -> OpenInterest:
|
|
126
127
|
"""Async version of current()."""
|
|
127
|
-
data = await self._http.aget(f"/
|
|
128
|
+
data = await self._http.aget(f"{self._base_path}/openinterest/{coin.upper()}/current")
|
|
128
129
|
return OpenInterest.model_validate(data["data"])
|
oxarchive/resources/orderbook.py
CHANGED
|
@@ -14,18 +14,22 @@ class OrderBookResource:
|
|
|
14
14
|
Order book API resource.
|
|
15
15
|
|
|
16
16
|
Example:
|
|
17
|
-
>>> # Get current order book
|
|
18
|
-
>>> orderbook = client.orderbook.get("BTC")
|
|
17
|
+
>>> # Get current order book (Hyperliquid)
|
|
18
|
+
>>> orderbook = client.hyperliquid.orderbook.get("BTC")
|
|
19
19
|
>>>
|
|
20
20
|
>>> # Get order book at specific timestamp
|
|
21
|
-
>>> historical = client.orderbook.get("ETH", timestamp=1704067200000)
|
|
21
|
+
>>> historical = client.hyperliquid.orderbook.get("ETH", timestamp=1704067200000)
|
|
22
22
|
>>>
|
|
23
23
|
>>> # Get order book history
|
|
24
|
-
>>> history = client.orderbook.history("BTC", start="2024-01-01", end="2024-01-02")
|
|
24
|
+
>>> history = client.hyperliquid.orderbook.history("BTC", start="2024-01-01", end="2024-01-02")
|
|
25
|
+
>>>
|
|
26
|
+
>>> # Lighter.xyz order book
|
|
27
|
+
>>> lighter_ob = client.lighter.orderbook.get("BTC")
|
|
25
28
|
"""
|
|
26
29
|
|
|
27
|
-
def __init__(self, http: HttpClient):
|
|
30
|
+
def __init__(self, http: HttpClient, base_path: str = "/v1"):
|
|
28
31
|
self._http = http
|
|
32
|
+
self._base_path = base_path
|
|
29
33
|
|
|
30
34
|
def _convert_timestamp(self, ts: Optional[Timestamp]) -> Optional[int]:
|
|
31
35
|
"""Convert timestamp to Unix milliseconds."""
|
|
@@ -63,7 +67,7 @@ class OrderBookResource:
|
|
|
63
67
|
Order book snapshot
|
|
64
68
|
"""
|
|
65
69
|
data = self._http.get(
|
|
66
|
-
f"/
|
|
70
|
+
f"{self._base_path}/orderbook/{coin.upper()}",
|
|
67
71
|
params={
|
|
68
72
|
"timestamp": self._convert_timestamp(timestamp),
|
|
69
73
|
"depth": depth,
|
|
@@ -80,7 +84,7 @@ class OrderBookResource:
|
|
|
80
84
|
) -> OrderBook:
|
|
81
85
|
"""Async version of get()."""
|
|
82
86
|
data = await self._http.aget(
|
|
83
|
-
f"/
|
|
87
|
+
f"{self._base_path}/orderbook/{coin.upper()}",
|
|
84
88
|
params={
|
|
85
89
|
"timestamp": self._convert_timestamp(timestamp),
|
|
86
90
|
"depth": depth,
|
|
@@ -122,7 +126,7 @@ class OrderBookResource:
|
|
|
122
126
|
... snapshots.extend(result.data)
|
|
123
127
|
"""
|
|
124
128
|
data = self._http.get(
|
|
125
|
-
f"/
|
|
129
|
+
f"{self._base_path}/orderbook/{coin.upper()}/history",
|
|
126
130
|
params={
|
|
127
131
|
"start": self._convert_timestamp(start),
|
|
128
132
|
"end": self._convert_timestamp(end),
|
|
@@ -148,7 +152,7 @@ class OrderBookResource:
|
|
|
148
152
|
) -> CursorResponse[list[OrderBook]]:
|
|
149
153
|
"""Async version of history(). start and end are required."""
|
|
150
154
|
data = await self._http.aget(
|
|
151
|
-
f"/
|
|
155
|
+
f"{self._base_path}/orderbook/{coin.upper()}/history",
|
|
152
156
|
params={
|
|
153
157
|
"start": self._convert_timestamp(start),
|
|
154
158
|
"end": self._convert_timestamp(end),
|
oxarchive/resources/trades.py
CHANGED
|
@@ -27,8 +27,9 @@ class TradesResource:
|
|
|
27
27
|
... trades.extend(result.data)
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
|
-
def __init__(self, http: HttpClient):
|
|
30
|
+
def __init__(self, http: HttpClient, base_path: str = "/v1"):
|
|
31
31
|
self._http = http
|
|
32
|
+
self._base_path = base_path
|
|
32
33
|
|
|
33
34
|
def _convert_timestamp(self, ts: Optional[Timestamp]) -> Optional[int]:
|
|
34
35
|
"""Convert timestamp to Unix milliseconds."""
|
|
@@ -86,7 +87,7 @@ class TradesResource:
|
|
|
86
87
|
... trades.extend(result.data)
|
|
87
88
|
"""
|
|
88
89
|
data = self._http.get(
|
|
89
|
-
f"/
|
|
90
|
+
f"{self._base_path}/trades/{coin.upper()}",
|
|
90
91
|
params={
|
|
91
92
|
"start": self._convert_timestamp(start),
|
|
92
93
|
"end": self._convert_timestamp(end),
|
|
@@ -116,7 +117,7 @@ class TradesResource:
|
|
|
116
117
|
Uses cursor-based pagination by default.
|
|
117
118
|
"""
|
|
118
119
|
data = await self._http.aget(
|
|
119
|
-
f"/
|
|
120
|
+
f"{self._base_path}/trades/{coin.upper()}",
|
|
120
121
|
params={
|
|
121
122
|
"start": self._convert_timestamp(start),
|
|
122
123
|
"end": self._convert_timestamp(end),
|
|
@@ -142,7 +143,7 @@ class TradesResource:
|
|
|
142
143
|
List of recent trades
|
|
143
144
|
"""
|
|
144
145
|
data = self._http.get(
|
|
145
|
-
f"/
|
|
146
|
+
f"{self._base_path}/trades/{coin.upper()}/recent",
|
|
146
147
|
params={"limit": limit},
|
|
147
148
|
)
|
|
148
149
|
return [Trade.model_validate(item) for item in data["data"]]
|
|
@@ -150,7 +151,7 @@ class TradesResource:
|
|
|
150
151
|
async def arecent(self, coin: str, limit: Optional[int] = None) -> list[Trade]:
|
|
151
152
|
"""Async version of recent()."""
|
|
152
153
|
data = await self._http.aget(
|
|
153
|
-
f"/
|
|
154
|
+
f"{self._base_path}/trades/{coin.upper()}/recent",
|
|
154
155
|
params={"limit": limit},
|
|
155
156
|
)
|
|
156
157
|
return [Trade.model_validate(item) for item in data["data"]]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oxarchive
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
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
|
|
@@ -37,7 +37,11 @@ Description-Content-Type: text/markdown
|
|
|
37
37
|
|
|
38
38
|
# oxarchive
|
|
39
39
|
|
|
40
|
-
Official Python SDK for [0xarchive](https://0xarchive.io) -
|
|
40
|
+
Official Python SDK for [0xarchive](https://0xarchive.io) - Historical Market Data API.
|
|
41
|
+
|
|
42
|
+
Supports multiple exchanges:
|
|
43
|
+
- **Hyperliquid** - Perpetuals data from April 2023
|
|
44
|
+
- **Lighter.xyz** - Perpetuals data (August 2025+ for fills, Jan 2026+ for OB, OI, Funding Rate)
|
|
41
45
|
|
|
42
46
|
## Installation
|
|
43
47
|
|
|
@@ -58,12 +62,16 @@ from oxarchive import Client
|
|
|
58
62
|
|
|
59
63
|
client = Client(api_key="ox_your_api_key")
|
|
60
64
|
|
|
61
|
-
#
|
|
62
|
-
|
|
63
|
-
print(f"BTC mid price: {
|
|
65
|
+
# Hyperliquid data
|
|
66
|
+
hl_orderbook = client.hyperliquid.orderbook.get("BTC")
|
|
67
|
+
print(f"Hyperliquid BTC mid price: {hl_orderbook.mid_price}")
|
|
68
|
+
|
|
69
|
+
# Lighter.xyz data
|
|
70
|
+
lighter_orderbook = client.lighter.orderbook.get("BTC")
|
|
71
|
+
print(f"Lighter BTC mid price: {lighter_orderbook.mid_price}")
|
|
64
72
|
|
|
65
73
|
# Get historical order book snapshots
|
|
66
|
-
history = client.orderbook.history(
|
|
74
|
+
history = client.hyperliquid.orderbook.history(
|
|
67
75
|
"ETH",
|
|
68
76
|
start="2024-01-01",
|
|
69
77
|
end="2024-01-02",
|
|
@@ -82,10 +90,13 @@ from oxarchive import Client
|
|
|
82
90
|
async def main():
|
|
83
91
|
client = Client(api_key="ox_your_api_key")
|
|
84
92
|
|
|
85
|
-
# Async get
|
|
86
|
-
orderbook = await client.orderbook.aget("BTC")
|
|
93
|
+
# Async get (Hyperliquid)
|
|
94
|
+
orderbook = await client.hyperliquid.orderbook.aget("BTC")
|
|
87
95
|
print(f"BTC mid price: {orderbook.mid_price}")
|
|
88
96
|
|
|
97
|
+
# Async get (Lighter.xyz)
|
|
98
|
+
lighter_ob = await client.lighter.orderbook.aget("BTC")
|
|
99
|
+
|
|
89
100
|
# Don't forget to close the client
|
|
90
101
|
await client.aclose()
|
|
91
102
|
|
|
@@ -96,7 +107,7 @@ Or use as async context manager:
|
|
|
96
107
|
|
|
97
108
|
```python
|
|
98
109
|
async with Client(api_key="ox_your_api_key") as client:
|
|
99
|
-
orderbook = await client.orderbook.aget("BTC")
|
|
110
|
+
orderbook = await client.hyperliquid.orderbook.aget("BTC")
|
|
100
111
|
```
|
|
101
112
|
|
|
102
113
|
## Configuration
|
|
@@ -111,20 +122,25 @@ client = Client(
|
|
|
111
122
|
|
|
112
123
|
## REST API Reference
|
|
113
124
|
|
|
125
|
+
All examples use `client.hyperliquid.*` but the same methods are available on `client.lighter.*` for Lighter.xyz data.
|
|
126
|
+
|
|
114
127
|
### Order Book
|
|
115
128
|
|
|
116
129
|
```python
|
|
117
|
-
# Get current order book
|
|
118
|
-
orderbook = client.orderbook.get("BTC")
|
|
130
|
+
# Get current order book (Hyperliquid)
|
|
131
|
+
orderbook = client.hyperliquid.orderbook.get("BTC")
|
|
132
|
+
|
|
133
|
+
# Get current order book (Lighter.xyz)
|
|
134
|
+
orderbook = client.lighter.orderbook.get("BTC")
|
|
119
135
|
|
|
120
136
|
# Get order book at specific timestamp
|
|
121
|
-
historical = client.orderbook.get("BTC", timestamp=1704067200000)
|
|
137
|
+
historical = client.hyperliquid.orderbook.get("BTC", timestamp=1704067200000)
|
|
122
138
|
|
|
123
139
|
# Get with limited depth
|
|
124
|
-
shallow = client.orderbook.get("BTC", depth=10)
|
|
140
|
+
shallow = client.hyperliquid.orderbook.get("BTC", depth=10)
|
|
125
141
|
|
|
126
142
|
# Get historical snapshots (start and end are required)
|
|
127
|
-
history = client.orderbook.history(
|
|
143
|
+
history = client.hyperliquid.orderbook.history(
|
|
128
144
|
"BTC",
|
|
129
145
|
start="2024-01-01",
|
|
130
146
|
end="2024-01-02",
|
|
@@ -133,8 +149,8 @@ history = client.orderbook.history(
|
|
|
133
149
|
)
|
|
134
150
|
|
|
135
151
|
# Async versions
|
|
136
|
-
orderbook = await client.orderbook.aget("BTC")
|
|
137
|
-
history = await client.orderbook.ahistory("BTC", start=..., end=...)
|
|
152
|
+
orderbook = await client.hyperliquid.orderbook.aget("BTC")
|
|
153
|
+
history = await client.hyperliquid.orderbook.ahistory("BTC", start=..., end=...)
|
|
138
154
|
```
|
|
139
155
|
|
|
140
156
|
### Trades
|
|
@@ -143,15 +159,15 @@ The trades API uses cursor-based pagination for efficient retrieval of large dat
|
|
|
143
159
|
|
|
144
160
|
```python
|
|
145
161
|
# Get recent trades
|
|
146
|
-
recent = client.trades.recent("BTC", limit=100)
|
|
162
|
+
recent = client.hyperliquid.trades.recent("BTC", limit=100)
|
|
147
163
|
|
|
148
164
|
# Get trade history with cursor-based pagination
|
|
149
|
-
result = client.trades.list("ETH", start="2024-01-01", end="2024-01-02", limit=1000)
|
|
165
|
+
result = client.hyperliquid.trades.list("ETH", start="2024-01-01", end="2024-01-02", limit=1000)
|
|
150
166
|
trades = result.data
|
|
151
167
|
|
|
152
168
|
# Paginate through all results
|
|
153
169
|
while result.next_cursor:
|
|
154
|
-
result = client.trades.list(
|
|
170
|
+
result = client.hyperliquid.trades.list(
|
|
155
171
|
"ETH",
|
|
156
172
|
start="2024-01-01",
|
|
157
173
|
end="2024-01-02",
|
|
@@ -161,61 +177,73 @@ while result.next_cursor:
|
|
|
161
177
|
trades.extend(result.data)
|
|
162
178
|
|
|
163
179
|
# Filter by side
|
|
164
|
-
buys = client.trades.list("BTC", start=..., end=..., side="buy")
|
|
180
|
+
buys = client.hyperliquid.trades.list("BTC", start=..., end=..., side="buy")
|
|
165
181
|
|
|
166
182
|
# Async versions
|
|
167
|
-
recent = await client.trades.arecent("BTC")
|
|
168
|
-
result = await client.trades.alist("ETH", start=..., end=...)
|
|
183
|
+
recent = await client.hyperliquid.trades.arecent("BTC")
|
|
184
|
+
result = await client.hyperliquid.trades.alist("ETH", start=..., end=...)
|
|
169
185
|
```
|
|
170
186
|
|
|
171
187
|
### Instruments
|
|
172
188
|
|
|
173
189
|
```python
|
|
174
190
|
# List all trading instruments
|
|
175
|
-
instruments = client.instruments.list()
|
|
191
|
+
instruments = client.hyperliquid.instruments.list()
|
|
176
192
|
|
|
177
193
|
# Get specific instrument details
|
|
178
|
-
btc = client.instruments.get("BTC")
|
|
194
|
+
btc = client.hyperliquid.instruments.get("BTC")
|
|
179
195
|
|
|
180
196
|
# Async versions
|
|
181
|
-
instruments = await client.instruments.alist()
|
|
182
|
-
btc = await client.instruments.aget("BTC")
|
|
197
|
+
instruments = await client.hyperliquid.instruments.alist()
|
|
198
|
+
btc = await client.hyperliquid.instruments.aget("BTC")
|
|
183
199
|
```
|
|
184
200
|
|
|
185
201
|
### Funding Rates
|
|
186
202
|
|
|
187
203
|
```python
|
|
188
204
|
# Get current funding rate
|
|
189
|
-
current = client.funding.current("BTC")
|
|
205
|
+
current = client.hyperliquid.funding.current("BTC")
|
|
190
206
|
|
|
191
207
|
# Get funding rate history (start is required)
|
|
192
|
-
history = client.funding.history(
|
|
208
|
+
history = client.hyperliquid.funding.history(
|
|
193
209
|
"ETH",
|
|
194
210
|
start="2024-01-01",
|
|
195
211
|
end="2024-01-07"
|
|
196
212
|
)
|
|
197
213
|
|
|
198
214
|
# Async versions
|
|
199
|
-
current = await client.funding.acurrent("BTC")
|
|
200
|
-
history = await client.funding.ahistory("ETH", start=..., end=...)
|
|
215
|
+
current = await client.hyperliquid.funding.acurrent("BTC")
|
|
216
|
+
history = await client.hyperliquid.funding.ahistory("ETH", start=..., end=...)
|
|
201
217
|
```
|
|
202
218
|
|
|
203
219
|
### Open Interest
|
|
204
220
|
|
|
205
221
|
```python
|
|
206
222
|
# Get current open interest
|
|
207
|
-
current = client.open_interest.current("BTC")
|
|
223
|
+
current = client.hyperliquid.open_interest.current("BTC")
|
|
208
224
|
|
|
209
225
|
# Get open interest history (start is required)
|
|
210
|
-
history = client.open_interest.history(
|
|
226
|
+
history = client.hyperliquid.open_interest.history(
|
|
211
227
|
"ETH",
|
|
212
228
|
start="2024-01-01",
|
|
213
229
|
end="2024-01-07"
|
|
214
230
|
)
|
|
215
231
|
|
|
216
232
|
# Async versions
|
|
217
|
-
current = await client.open_interest.acurrent("BTC")
|
|
218
|
-
history = await client.open_interest.ahistory("ETH", start=..., end=...)
|
|
233
|
+
current = await client.hyperliquid.open_interest.acurrent("BTC")
|
|
234
|
+
history = await client.hyperliquid.open_interest.ahistory("ETH", start=..., end=...)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Legacy API (Deprecated)
|
|
238
|
+
|
|
239
|
+
The following legacy methods are deprecated and will be removed in v2.0. They default to Hyperliquid data:
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
# Deprecated - use client.hyperliquid.orderbook.get() instead
|
|
243
|
+
orderbook = client.orderbook.get("BTC")
|
|
244
|
+
|
|
245
|
+
# Deprecated - use client.hyperliquid.trades.list() instead
|
|
246
|
+
trades = client.trades.list("BTC", start=..., end=...)
|
|
219
247
|
```
|
|
220
248
|
|
|
221
249
|
## WebSocket Client
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
oxarchive/__init__.py,sha256=akj4sbUig6R_C56h9oOIMc1GHyg0o4XtnsSmesS8jc8,2536
|
|
2
|
+
oxarchive/client.py,sha256=XWQ_VEBQy3UIAnmZQ-Z_FyzXnvMA3FITwtinBOf3o-Y,4453
|
|
3
|
+
oxarchive/exchanges.py,sha256=DDM6cua8p9Fvhvkgl0Hy9vZW_mUauvKx94Axx9gNX2Y,2202
|
|
4
|
+
oxarchive/http.py,sha256=SY_o9Ag8ADo1HI3i3uAKW1xwkYjPE75gRAjnMsddAGs,4211
|
|
5
|
+
oxarchive/types.py,sha256=RUnni6RMGHxK3-tTajcDVtT3Rk_sJqlOJLiG5SMc3Do,11278
|
|
6
|
+
oxarchive/websocket.py,sha256=MyffJxaabDBonECcJg9vF4hAQ_4thjP4DaS7MaR4uno,28381
|
|
7
|
+
oxarchive/resources/__init__.py,sha256=WQ4GYQ8p3L0D2Isk4IV4h1DRpvyZlt6tOF1t_CJr6ls,385
|
|
8
|
+
oxarchive/resources/funding.py,sha256=ybMWkpoccrkdwnd6W3oHgsaor7cBcA2nkYy4CbjmHUg,4485
|
|
9
|
+
oxarchive/resources/instruments.py,sha256=9XAqYcwiJ1UXh17AgfKHYC-ExOLjn4hkmxmOTQdhcY4,1725
|
|
10
|
+
oxarchive/resources/openinterest.py,sha256=whwo60KFNLGwvVrDmDYYc-rMZr35Fcizb5Iil-DSvD8,4553
|
|
11
|
+
oxarchive/resources/orderbook.py,sha256=-paXBdGYBCMX-LK-MeXIKlcFz97iW2UWn9Am2XCgg2U,5717
|
|
12
|
+
oxarchive/resources/trades.py,sha256=t4iicyi1waaHzC7Q_cC-c7O4yVx1vqS4eMH8F8_5hxk,5503
|
|
13
|
+
oxarchive-0.4.1.dist-info/METADATA,sha256=wSR3bx71sBvSbl3N3gRf-MbsJWbtFhHlZgILxpZ5sh4,12428
|
|
14
|
+
oxarchive-0.4.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
15
|
+
oxarchive-0.4.1.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
oxarchive/__init__.py,sha256=Gjh2Ygt74OHNVSp-NLYumXBM8WGR62QJf95oBDBlFJ4,2182
|
|
2
|
-
oxarchive/client.py,sha256=3P0fvOcyM5BWppkVV4054NduDHKvRg-cWeluoGymmRk,3163
|
|
3
|
-
oxarchive/http.py,sha256=SY_o9Ag8ADo1HI3i3uAKW1xwkYjPE75gRAjnMsddAGs,4211
|
|
4
|
-
oxarchive/types.py,sha256=RUnni6RMGHxK3-tTajcDVtT3Rk_sJqlOJLiG5SMc3Do,11278
|
|
5
|
-
oxarchive/websocket.py,sha256=MyffJxaabDBonECcJg9vF4hAQ_4thjP4DaS7MaR4uno,28381
|
|
6
|
-
oxarchive/resources/__init__.py,sha256=WQ4GYQ8p3L0D2Isk4IV4h1DRpvyZlt6tOF1t_CJr6ls,385
|
|
7
|
-
oxarchive/resources/funding.py,sha256=g-c_zeCxFoPKEYymeDVswsIvfZIAKz4wd_2pTYpe8zQ,4368
|
|
8
|
-
oxarchive/resources/instruments.py,sha256=flD1sH6x3P3CTqV1ZwkfwbranVacmhsHn5Dhr7lGQhM,1606
|
|
9
|
-
oxarchive/resources/openinterest.py,sha256=Il9OzvnYM0-UCuspPUGqXy6dHMfxBvbLojPDKfS4kzU,4436
|
|
10
|
-
oxarchive/resources/orderbook.py,sha256=2aq9v2gK5ZJ2C_i6vY2plvtMdI0n50Gx8GsJLUIAEJA,5437
|
|
11
|
-
oxarchive/resources/trades.py,sha256=6Gm0ryUk1XBg2Tv7g69D5QQFuN6ZKLCAD1-TJ_J0jjU,5386
|
|
12
|
-
oxarchive-0.3.11.dist-info/METADATA,sha256=N_uQ-prJ3oKnXcpyjhumUvlmOAAIQP0VI5da4n4jMOA,11071
|
|
13
|
-
oxarchive-0.3.11.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
14
|
-
oxarchive-0.3.11.dist-info/RECORD,,
|
|
File without changes
|