oxarchive 0.1.1__tar.gz → 0.3.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 → oxarchive-0.3.1}/PKG-INFO +5 -19
- {oxarchive-0.1.1 → oxarchive-0.3.1}/README.md +4 -18
- {oxarchive-0.1.1 → oxarchive-0.3.1}/oxarchive/__init__.py +0 -4
- {oxarchive-0.1.1 → oxarchive-0.3.1}/oxarchive/client.py +0 -4
- {oxarchive-0.1.1 → oxarchive-0.3.1}/oxarchive/resources/__init__.py +0 -2
- {oxarchive-0.1.1 → oxarchive-0.3.1}/oxarchive/resources/funding.py +7 -7
- {oxarchive-0.1.1 → oxarchive-0.3.1}/oxarchive/resources/openinterest.py +7 -7
- {oxarchive-0.1.1 → oxarchive-0.3.1}/oxarchive/resources/orderbook.py +7 -7
- oxarchive-0.3.1/oxarchive/resources/trades.py +299 -0
- oxarchive-0.3.1/oxarchive/types.py +413 -0
- {oxarchive-0.1.1 → oxarchive-0.3.1}/oxarchive/websocket.py +81 -20
- {oxarchive-0.1.1 → oxarchive-0.3.1}/pyproject.toml +1 -1
- oxarchive-0.1.1/oxarchive/resources/candles.py +0 -100
- oxarchive-0.1.1/oxarchive/resources/trades.py +0 -125
- oxarchive-0.1.1/oxarchive/types.py +0 -304
- {oxarchive-0.1.1 → oxarchive-0.3.1}/oxarchive/http.py +0 -0
- {oxarchive-0.1.1 → oxarchive-0.3.1}/oxarchive/resources/instruments.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oxarchive
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.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
|
|
@@ -140,20 +140,6 @@ trades = client.trades.list(
|
|
|
140
140
|
)
|
|
141
141
|
```
|
|
142
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
143
|
### Instruments
|
|
158
144
|
|
|
159
145
|
```python
|
|
@@ -272,8 +258,8 @@ async def main():
|
|
|
272
258
|
print(f"{ts}: {data['mid_price']}")
|
|
273
259
|
)
|
|
274
260
|
|
|
275
|
-
ws.on_replay_start(lambda ch, coin,
|
|
276
|
-
print(f"Starting replay
|
|
261
|
+
ws.on_replay_start(lambda ch, coin, start, end, speed:
|
|
262
|
+
print(f"Starting replay from {start} to {end} at {speed}x")
|
|
277
263
|
)
|
|
278
264
|
|
|
279
265
|
ws.on_replay_complete(lambda ch, coin, sent:
|
|
@@ -316,8 +302,8 @@ async def main():
|
|
|
316
302
|
all_data.extend([r.data for r in records])
|
|
317
303
|
)
|
|
318
304
|
|
|
319
|
-
ws.on_stream_progress(lambda
|
|
320
|
-
print(f"
|
|
305
|
+
ws.on_stream_progress(lambda snapshots_sent:
|
|
306
|
+
print(f"Sent: {snapshots_sent} snapshots")
|
|
321
307
|
)
|
|
322
308
|
|
|
323
309
|
ws.on_stream_complete(lambda ch, coin, sent:
|
|
@@ -104,20 +104,6 @@ trades = client.trades.list(
|
|
|
104
104
|
)
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
### Candles (OHLCV)
|
|
108
|
-
|
|
109
|
-
```python
|
|
110
|
-
# Get hourly candles
|
|
111
|
-
candles = client.candles.list(
|
|
112
|
-
"BTC",
|
|
113
|
-
interval="1h",
|
|
114
|
-
start="2024-01-01",
|
|
115
|
-
end="2024-01-02"
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
# Available intervals: '1m', '5m', '15m', '1h', '4h', '1d'
|
|
119
|
-
```
|
|
120
|
-
|
|
121
107
|
### Instruments
|
|
122
108
|
|
|
123
109
|
```python
|
|
@@ -236,8 +222,8 @@ async def main():
|
|
|
236
222
|
print(f"{ts}: {data['mid_price']}")
|
|
237
223
|
)
|
|
238
224
|
|
|
239
|
-
ws.on_replay_start(lambda ch, coin,
|
|
240
|
-
print(f"Starting replay
|
|
225
|
+
ws.on_replay_start(lambda ch, coin, start, end, speed:
|
|
226
|
+
print(f"Starting replay from {start} to {end} at {speed}x")
|
|
241
227
|
)
|
|
242
228
|
|
|
243
229
|
ws.on_replay_complete(lambda ch, coin, sent:
|
|
@@ -280,8 +266,8 @@ async def main():
|
|
|
280
266
|
all_data.extend([r.data for r in records])
|
|
281
267
|
)
|
|
282
268
|
|
|
283
|
-
ws.on_stream_progress(lambda
|
|
284
|
-
print(f"
|
|
269
|
+
ws.on_stream_progress(lambda snapshots_sent:
|
|
270
|
+
print(f"Sent: {snapshots_sent} snapshots")
|
|
285
271
|
)
|
|
286
272
|
|
|
287
273
|
ws.on_stream_complete(lambda ch, coin, sent:
|
|
@@ -20,8 +20,6 @@ from .client import Client
|
|
|
20
20
|
from .types import (
|
|
21
21
|
OrderBook,
|
|
22
22
|
Trade,
|
|
23
|
-
Candle,
|
|
24
|
-
CandleInterval,
|
|
25
23
|
Instrument,
|
|
26
24
|
FundingRate,
|
|
27
25
|
OpenInterest,
|
|
@@ -70,8 +68,6 @@ __all__ = [
|
|
|
70
68
|
# Types
|
|
71
69
|
"OrderBook",
|
|
72
70
|
"Trade",
|
|
73
|
-
"Candle",
|
|
74
|
-
"CandleInterval",
|
|
75
71
|
"Instrument",
|
|
76
72
|
"FundingRate",
|
|
77
73
|
"OpenInterest",
|
|
@@ -8,7 +8,6 @@ from .http import HttpClient
|
|
|
8
8
|
from .resources import (
|
|
9
9
|
OrderBookResource,
|
|
10
10
|
TradesResource,
|
|
11
|
-
CandlesResource,
|
|
12
11
|
InstrumentsResource,
|
|
13
12
|
FundingResource,
|
|
14
13
|
OpenInterestResource,
|
|
@@ -81,9 +80,6 @@ class Client:
|
|
|
81
80
|
self.trades = TradesResource(self._http)
|
|
82
81
|
"""Trade/fill history"""
|
|
83
82
|
|
|
84
|
-
self.candles = CandlesResource(self._http)
|
|
85
|
-
"""OHLCV candles"""
|
|
86
|
-
|
|
87
83
|
self.instruments = InstrumentsResource(self._http)
|
|
88
84
|
"""Trading instruments metadata"""
|
|
89
85
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from .orderbook import OrderBookResource
|
|
4
4
|
from .trades import TradesResource
|
|
5
|
-
from .candles import CandlesResource
|
|
6
5
|
from .instruments import InstrumentsResource
|
|
7
6
|
from .funding import FundingResource
|
|
8
7
|
from .openinterest import OpenInterestResource
|
|
@@ -10,7 +9,6 @@ from .openinterest import OpenInterestResource
|
|
|
10
9
|
__all__ = [
|
|
11
10
|
"OrderBookResource",
|
|
12
11
|
"TradesResource",
|
|
13
|
-
"CandlesResource",
|
|
14
12
|
"InstrumentsResource",
|
|
15
13
|
"FundingResource",
|
|
16
14
|
"OpenInterestResource",
|
|
@@ -44,8 +44,8 @@ class FundingResource:
|
|
|
44
44
|
self,
|
|
45
45
|
coin: str,
|
|
46
46
|
*,
|
|
47
|
-
start:
|
|
48
|
-
end:
|
|
47
|
+
start: Timestamp,
|
|
48
|
+
end: Timestamp,
|
|
49
49
|
limit: Optional[int] = None,
|
|
50
50
|
offset: Optional[int] = None,
|
|
51
51
|
) -> list[FundingRate]:
|
|
@@ -54,8 +54,8 @@ class FundingResource:
|
|
|
54
54
|
|
|
55
55
|
Args:
|
|
56
56
|
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
57
|
-
start: Start timestamp
|
|
58
|
-
end: End timestamp
|
|
57
|
+
start: Start timestamp (required)
|
|
58
|
+
end: End timestamp (required)
|
|
59
59
|
limit: Maximum number of results
|
|
60
60
|
offset: Number of results to skip
|
|
61
61
|
|
|
@@ -77,12 +77,12 @@ class FundingResource:
|
|
|
77
77
|
self,
|
|
78
78
|
coin: str,
|
|
79
79
|
*,
|
|
80
|
-
start:
|
|
81
|
-
end:
|
|
80
|
+
start: Timestamp,
|
|
81
|
+
end: Timestamp,
|
|
82
82
|
limit: Optional[int] = None,
|
|
83
83
|
offset: Optional[int] = None,
|
|
84
84
|
) -> list[FundingRate]:
|
|
85
|
-
"""Async version of history()."""
|
|
85
|
+
"""Async version of history(). start and end are required."""
|
|
86
86
|
data = await self._http.aget(
|
|
87
87
|
f"/v1/funding/{coin.upper()}",
|
|
88
88
|
params={
|
|
@@ -44,8 +44,8 @@ class OpenInterestResource:
|
|
|
44
44
|
self,
|
|
45
45
|
coin: str,
|
|
46
46
|
*,
|
|
47
|
-
start:
|
|
48
|
-
end:
|
|
47
|
+
start: Timestamp,
|
|
48
|
+
end: Timestamp,
|
|
49
49
|
limit: Optional[int] = None,
|
|
50
50
|
offset: Optional[int] = None,
|
|
51
51
|
) -> list[OpenInterest]:
|
|
@@ -54,8 +54,8 @@ class OpenInterestResource:
|
|
|
54
54
|
|
|
55
55
|
Args:
|
|
56
56
|
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
57
|
-
start: Start timestamp
|
|
58
|
-
end: End timestamp
|
|
57
|
+
start: Start timestamp (required)
|
|
58
|
+
end: End timestamp (required)
|
|
59
59
|
limit: Maximum number of results
|
|
60
60
|
offset: Number of results to skip
|
|
61
61
|
|
|
@@ -77,12 +77,12 @@ class OpenInterestResource:
|
|
|
77
77
|
self,
|
|
78
78
|
coin: str,
|
|
79
79
|
*,
|
|
80
|
-
start:
|
|
81
|
-
end:
|
|
80
|
+
start: Timestamp,
|
|
81
|
+
end: Timestamp,
|
|
82
82
|
limit: Optional[int] = None,
|
|
83
83
|
offset: Optional[int] = None,
|
|
84
84
|
) -> list[OpenInterest]:
|
|
85
|
-
"""Async version of history()."""
|
|
85
|
+
"""Async version of history(). start and end are required."""
|
|
86
86
|
data = await self._http.aget(
|
|
87
87
|
f"/v1/openinterest/{coin.upper()}",
|
|
88
88
|
params={
|
|
@@ -92,8 +92,8 @@ class OrderBookResource:
|
|
|
92
92
|
self,
|
|
93
93
|
coin: str,
|
|
94
94
|
*,
|
|
95
|
-
start:
|
|
96
|
-
end:
|
|
95
|
+
start: Timestamp,
|
|
96
|
+
end: Timestamp,
|
|
97
97
|
limit: Optional[int] = None,
|
|
98
98
|
offset: Optional[int] = None,
|
|
99
99
|
depth: Optional[int] = None,
|
|
@@ -103,8 +103,8 @@ class OrderBookResource:
|
|
|
103
103
|
|
|
104
104
|
Args:
|
|
105
105
|
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
106
|
-
start: Start timestamp
|
|
107
|
-
end: End timestamp
|
|
106
|
+
start: Start timestamp (required)
|
|
107
|
+
end: End timestamp (required)
|
|
108
108
|
limit: Maximum number of results
|
|
109
109
|
offset: Number of results to skip
|
|
110
110
|
depth: Number of price levels per side
|
|
@@ -128,13 +128,13 @@ class OrderBookResource:
|
|
|
128
128
|
self,
|
|
129
129
|
coin: str,
|
|
130
130
|
*,
|
|
131
|
-
start:
|
|
132
|
-
end:
|
|
131
|
+
start: Timestamp,
|
|
132
|
+
end: Timestamp,
|
|
133
133
|
limit: Optional[int] = None,
|
|
134
134
|
offset: Optional[int] = None,
|
|
135
135
|
depth: Optional[int] = None,
|
|
136
136
|
) -> list[OrderBook]:
|
|
137
|
-
"""Async version of history()."""
|
|
137
|
+
"""Async version of history(). start and end are required."""
|
|
138
138
|
data = await self._http.aget(
|
|
139
139
|
f"/v1/orderbook/{coin.upper()}/history",
|
|
140
140
|
params={
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"""Trades API resource."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import warnings
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Literal, Optional
|
|
9
|
+
|
|
10
|
+
from ..http import HttpClient
|
|
11
|
+
from ..types import Trade, Timestamp
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class CursorResponse:
|
|
16
|
+
"""Response with cursor for pagination."""
|
|
17
|
+
data: list[Trade]
|
|
18
|
+
next_cursor: Optional[str] = None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TradesResource:
|
|
22
|
+
"""
|
|
23
|
+
Trades API resource.
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
>>> # Get recent trades
|
|
27
|
+
>>> trades = client.trades.recent("BTC")
|
|
28
|
+
>>>
|
|
29
|
+
>>> # Get trade history with cursor-based pagination (recommended)
|
|
30
|
+
>>> result = client.trades.list("BTC", start="2024-01-01", end="2024-01-02")
|
|
31
|
+
>>> trades = result.data
|
|
32
|
+
>>>
|
|
33
|
+
>>> # Get all pages
|
|
34
|
+
>>> while result.next_cursor:
|
|
35
|
+
... result = client.trades.list("BTC", start="2024-01-01", end="2024-01-02", cursor=result.next_cursor)
|
|
36
|
+
... trades.extend(result.data)
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, http: HttpClient):
|
|
40
|
+
self._http = http
|
|
41
|
+
|
|
42
|
+
def _convert_timestamp(self, ts: Optional[Timestamp]) -> Optional[int]:
|
|
43
|
+
"""Convert timestamp to Unix milliseconds."""
|
|
44
|
+
if ts is None:
|
|
45
|
+
return None
|
|
46
|
+
if isinstance(ts, int):
|
|
47
|
+
return ts
|
|
48
|
+
if isinstance(ts, datetime):
|
|
49
|
+
return int(ts.timestamp() * 1000)
|
|
50
|
+
if isinstance(ts, str):
|
|
51
|
+
try:
|
|
52
|
+
dt = datetime.fromisoformat(ts.replace("Z", "+00:00"))
|
|
53
|
+
return int(dt.timestamp() * 1000)
|
|
54
|
+
except ValueError:
|
|
55
|
+
return int(ts)
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
def list(
|
|
59
|
+
self,
|
|
60
|
+
coin: str,
|
|
61
|
+
*,
|
|
62
|
+
start: Timestamp,
|
|
63
|
+
end: Timestamp,
|
|
64
|
+
cursor: Optional[Timestamp] = None,
|
|
65
|
+
limit: Optional[int] = None,
|
|
66
|
+
side: Optional[Literal["buy", "sell"]] = None,
|
|
67
|
+
) -> CursorResponse:
|
|
68
|
+
"""
|
|
69
|
+
Get trade history for a coin using cursor-based pagination.
|
|
70
|
+
|
|
71
|
+
Uses cursor-based pagination by default, which is more efficient for large datasets.
|
|
72
|
+
Use the next_cursor from the response as the cursor parameter to get the next page.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
76
|
+
start: Start timestamp (required)
|
|
77
|
+
end: End timestamp (required)
|
|
78
|
+
cursor: Cursor from previous response's next_cursor (timestamp)
|
|
79
|
+
limit: Maximum number of results (default: 100, max: 1000)
|
|
80
|
+
side: Filter by trade side
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
CursorResponse with trades and next_cursor for pagination
|
|
84
|
+
|
|
85
|
+
Example:
|
|
86
|
+
>>> # First page
|
|
87
|
+
>>> result = client.trades.list("BTC", start=start, end=end, limit=1000)
|
|
88
|
+
>>> trades = result.data
|
|
89
|
+
>>>
|
|
90
|
+
>>> # Subsequent pages
|
|
91
|
+
>>> while result.next_cursor:
|
|
92
|
+
... result = client.trades.list(
|
|
93
|
+
... "BTC", start=start, end=end, cursor=result.next_cursor, limit=1000
|
|
94
|
+
... )
|
|
95
|
+
... trades.extend(result.data)
|
|
96
|
+
"""
|
|
97
|
+
data = self._http.get(
|
|
98
|
+
f"/v1/trades/{coin.upper()}",
|
|
99
|
+
params={
|
|
100
|
+
"start": self._convert_timestamp(start),
|
|
101
|
+
"end": self._convert_timestamp(end),
|
|
102
|
+
"cursor": self._convert_timestamp(cursor),
|
|
103
|
+
"limit": limit,
|
|
104
|
+
"side": side,
|
|
105
|
+
},
|
|
106
|
+
)
|
|
107
|
+
return CursorResponse(
|
|
108
|
+
data=[Trade.model_validate(item) for item in data["data"]],
|
|
109
|
+
next_cursor=data.get("meta", {}).get("next_cursor"),
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
async def alist(
|
|
113
|
+
self,
|
|
114
|
+
coin: str,
|
|
115
|
+
*,
|
|
116
|
+
start: Timestamp,
|
|
117
|
+
end: Timestamp,
|
|
118
|
+
cursor: Optional[Timestamp] = None,
|
|
119
|
+
limit: Optional[int] = None,
|
|
120
|
+
side: Optional[Literal["buy", "sell"]] = None,
|
|
121
|
+
) -> CursorResponse:
|
|
122
|
+
"""
|
|
123
|
+
Async version of list().
|
|
124
|
+
|
|
125
|
+
Uses cursor-based pagination by default.
|
|
126
|
+
"""
|
|
127
|
+
data = await self._http.aget(
|
|
128
|
+
f"/v1/trades/{coin.upper()}",
|
|
129
|
+
params={
|
|
130
|
+
"start": self._convert_timestamp(start),
|
|
131
|
+
"end": self._convert_timestamp(end),
|
|
132
|
+
"cursor": self._convert_timestamp(cursor),
|
|
133
|
+
"limit": limit,
|
|
134
|
+
"side": side,
|
|
135
|
+
},
|
|
136
|
+
)
|
|
137
|
+
return CursorResponse(
|
|
138
|
+
data=[Trade.model_validate(item) for item in data["data"]],
|
|
139
|
+
next_cursor=data.get("meta", {}).get("next_cursor"),
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def list_with_offset(
|
|
143
|
+
self,
|
|
144
|
+
coin: str,
|
|
145
|
+
*,
|
|
146
|
+
start: Timestamp,
|
|
147
|
+
end: Timestamp,
|
|
148
|
+
limit: Optional[int] = None,
|
|
149
|
+
offset: Optional[int] = None,
|
|
150
|
+
side: Optional[Literal["buy", "sell"]] = None,
|
|
151
|
+
) -> list[Trade]:
|
|
152
|
+
"""
|
|
153
|
+
Get trade history using offset-based pagination.
|
|
154
|
+
|
|
155
|
+
.. deprecated::
|
|
156
|
+
Use list() with cursor-based pagination instead for better performance.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
160
|
+
start: Start timestamp (required)
|
|
161
|
+
end: End timestamp (required)
|
|
162
|
+
limit: Maximum number of results
|
|
163
|
+
offset: Number of results to skip
|
|
164
|
+
side: Filter by trade side
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
List of trades
|
|
168
|
+
"""
|
|
169
|
+
warnings.warn(
|
|
170
|
+
"list_with_offset() is deprecated. Use list() with cursor-based pagination instead.",
|
|
171
|
+
DeprecationWarning,
|
|
172
|
+
stacklevel=2,
|
|
173
|
+
)
|
|
174
|
+
data = self._http.get(
|
|
175
|
+
f"/v1/trades/{coin.upper()}",
|
|
176
|
+
params={
|
|
177
|
+
"start": self._convert_timestamp(start),
|
|
178
|
+
"end": self._convert_timestamp(end),
|
|
179
|
+
"limit": limit,
|
|
180
|
+
"offset": offset,
|
|
181
|
+
"side": side,
|
|
182
|
+
},
|
|
183
|
+
)
|
|
184
|
+
return [Trade.model_validate(item) for item in data["data"]]
|
|
185
|
+
|
|
186
|
+
async def alist_with_offset(
|
|
187
|
+
self,
|
|
188
|
+
coin: str,
|
|
189
|
+
*,
|
|
190
|
+
start: Timestamp,
|
|
191
|
+
end: Timestamp,
|
|
192
|
+
limit: Optional[int] = None,
|
|
193
|
+
offset: Optional[int] = None,
|
|
194
|
+
side: Optional[Literal["buy", "sell"]] = None,
|
|
195
|
+
) -> list[Trade]:
|
|
196
|
+
"""
|
|
197
|
+
Async version of list_with_offset().
|
|
198
|
+
|
|
199
|
+
.. deprecated::
|
|
200
|
+
Use alist() with cursor-based pagination instead.
|
|
201
|
+
"""
|
|
202
|
+
warnings.warn(
|
|
203
|
+
"alist_with_offset() is deprecated. Use alist() with cursor-based pagination instead.",
|
|
204
|
+
DeprecationWarning,
|
|
205
|
+
stacklevel=2,
|
|
206
|
+
)
|
|
207
|
+
data = await self._http.aget(
|
|
208
|
+
f"/v1/trades/{coin.upper()}",
|
|
209
|
+
params={
|
|
210
|
+
"start": self._convert_timestamp(start),
|
|
211
|
+
"end": self._convert_timestamp(end),
|
|
212
|
+
"limit": limit,
|
|
213
|
+
"offset": offset,
|
|
214
|
+
"side": side,
|
|
215
|
+
},
|
|
216
|
+
)
|
|
217
|
+
return [Trade.model_validate(item) for item in data["data"]]
|
|
218
|
+
|
|
219
|
+
def recent(self, coin: str, limit: Optional[int] = None) -> list[Trade]:
|
|
220
|
+
"""
|
|
221
|
+
Get most recent trades for a coin.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
225
|
+
limit: Number of trades to return (default: 100)
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
List of recent trades
|
|
229
|
+
"""
|
|
230
|
+
data = self._http.get(
|
|
231
|
+
f"/v1/trades/{coin.upper()}/recent",
|
|
232
|
+
params={"limit": limit},
|
|
233
|
+
)
|
|
234
|
+
return [Trade.model_validate(item) for item in data["data"]]
|
|
235
|
+
|
|
236
|
+
async def arecent(self, coin: str, limit: Optional[int] = None) -> list[Trade]:
|
|
237
|
+
"""Async version of recent()."""
|
|
238
|
+
data = await self._http.aget(
|
|
239
|
+
f"/v1/trades/{coin.upper()}/recent",
|
|
240
|
+
params={"limit": limit},
|
|
241
|
+
)
|
|
242
|
+
return [Trade.model_validate(item) for item in data["data"]]
|
|
243
|
+
|
|
244
|
+
def list_cursor(
|
|
245
|
+
self,
|
|
246
|
+
coin: str,
|
|
247
|
+
*,
|
|
248
|
+
start: Timestamp,
|
|
249
|
+
end: Timestamp,
|
|
250
|
+
cursor: Optional[Timestamp] = None,
|
|
251
|
+
limit: Optional[int] = None,
|
|
252
|
+
side: Optional[Literal["buy", "sell"]] = None,
|
|
253
|
+
) -> CursorResponse:
|
|
254
|
+
"""
|
|
255
|
+
Get trade history using cursor-based pagination.
|
|
256
|
+
|
|
257
|
+
.. deprecated::
|
|
258
|
+
Use list() instead - it now uses cursor-based pagination by default.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
262
|
+
start: Start timestamp (required)
|
|
263
|
+
end: End timestamp (required)
|
|
264
|
+
cursor: Cursor from previous response's next_cursor (timestamp)
|
|
265
|
+
limit: Maximum number of results
|
|
266
|
+
side: Filter by trade side
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
CursorResponse with trades and next_cursor for pagination
|
|
270
|
+
"""
|
|
271
|
+
warnings.warn(
|
|
272
|
+
"list_cursor() is deprecated. Use list() instead - it now uses cursor-based pagination by default.",
|
|
273
|
+
DeprecationWarning,
|
|
274
|
+
stacklevel=2,
|
|
275
|
+
)
|
|
276
|
+
return self.list(coin, start=start, end=end, cursor=cursor, limit=limit, side=side)
|
|
277
|
+
|
|
278
|
+
async def alist_cursor(
|
|
279
|
+
self,
|
|
280
|
+
coin: str,
|
|
281
|
+
*,
|
|
282
|
+
start: Timestamp,
|
|
283
|
+
end: Timestamp,
|
|
284
|
+
cursor: Optional[Timestamp] = None,
|
|
285
|
+
limit: Optional[int] = None,
|
|
286
|
+
side: Optional[Literal["buy", "sell"]] = None,
|
|
287
|
+
) -> CursorResponse:
|
|
288
|
+
"""
|
|
289
|
+
Async version of list_cursor().
|
|
290
|
+
|
|
291
|
+
.. deprecated::
|
|
292
|
+
Use alist() instead - it now uses cursor-based pagination by default.
|
|
293
|
+
"""
|
|
294
|
+
warnings.warn(
|
|
295
|
+
"alist_cursor() is deprecated. Use alist() instead - it now uses cursor-based pagination by default.",
|
|
296
|
+
DeprecationWarning,
|
|
297
|
+
stacklevel=2,
|
|
298
|
+
)
|
|
299
|
+
return await self.alist(coin, start=start, end=end, cursor=cursor, limit=limit, side=side)
|