oxarchive 0.3.9__py3-none-any.whl → 0.3.11__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 +1 -1
- oxarchive/resources/funding.py +28 -13
- oxarchive/resources/openinterest.py +28 -13
- oxarchive/resources/orderbook.py +28 -13
- oxarchive/resources/trades.py +3 -146
- oxarchive/types.py +15 -0
- oxarchive/websocket.py +2 -1
- {oxarchive-0.3.9.dist-info → oxarchive-0.3.11.dist-info}/METADATA +1 -1
- oxarchive-0.3.11.dist-info/RECORD +14 -0
- oxarchive-0.3.9.dist-info/RECORD +0 -14
- {oxarchive-0.3.9.dist-info → oxarchive-0.3.11.dist-info}/WHEEL +0 -0
oxarchive/__init__.py
CHANGED
oxarchive/resources/funding.py
CHANGED
|
@@ -6,7 +6,7 @@ from datetime import datetime
|
|
|
6
6
|
from typing import Optional
|
|
7
7
|
|
|
8
8
|
from ..http import HttpClient
|
|
9
|
-
from ..types import FundingRate, Timestamp
|
|
9
|
+
from ..types import CursorResponse, FundingRate, Timestamp
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class FundingResource:
|
|
@@ -46,32 +46,44 @@ class FundingResource:
|
|
|
46
46
|
*,
|
|
47
47
|
start: Timestamp,
|
|
48
48
|
end: Timestamp,
|
|
49
|
+
cursor: Optional[Timestamp] = None,
|
|
49
50
|
limit: Optional[int] = None,
|
|
50
|
-
|
|
51
|
-
) -> list[FundingRate]:
|
|
51
|
+
) -> CursorResponse[list[FundingRate]]:
|
|
52
52
|
"""
|
|
53
|
-
Get funding rate history for a coin.
|
|
53
|
+
Get funding rate history for a coin with cursor-based pagination.
|
|
54
54
|
|
|
55
55
|
Args:
|
|
56
56
|
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
57
57
|
start: Start timestamp (required)
|
|
58
58
|
end: End timestamp (required)
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
cursor: Cursor from previous response's next_cursor (timestamp)
|
|
60
|
+
limit: Maximum number of results (default: 100, max: 1000)
|
|
61
61
|
|
|
62
62
|
Returns:
|
|
63
|
-
|
|
63
|
+
CursorResponse with funding rate records and next_cursor for pagination
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
>>> result = client.funding.history("BTC", start=start, end=end, limit=1000)
|
|
67
|
+
>>> rates = result.data
|
|
68
|
+
>>> while result.next_cursor:
|
|
69
|
+
... result = client.funding.history(
|
|
70
|
+
... "BTC", start=start, end=end, cursor=result.next_cursor, limit=1000
|
|
71
|
+
... )
|
|
72
|
+
... rates.extend(result.data)
|
|
64
73
|
"""
|
|
65
74
|
data = self._http.get(
|
|
66
75
|
f"/v1/funding/{coin.upper()}",
|
|
67
76
|
params={
|
|
68
77
|
"start": self._convert_timestamp(start),
|
|
69
78
|
"end": self._convert_timestamp(end),
|
|
79
|
+
"cursor": self._convert_timestamp(cursor),
|
|
70
80
|
"limit": limit,
|
|
71
|
-
"offset": offset,
|
|
72
81
|
},
|
|
73
82
|
)
|
|
74
|
-
return
|
|
83
|
+
return CursorResponse(
|
|
84
|
+
data=[FundingRate.model_validate(item) for item in data["data"]],
|
|
85
|
+
next_cursor=data.get("meta", {}).get("next_cursor"),
|
|
86
|
+
)
|
|
75
87
|
|
|
76
88
|
async def ahistory(
|
|
77
89
|
self,
|
|
@@ -79,20 +91,23 @@ class FundingResource:
|
|
|
79
91
|
*,
|
|
80
92
|
start: Timestamp,
|
|
81
93
|
end: Timestamp,
|
|
94
|
+
cursor: Optional[Timestamp] = None,
|
|
82
95
|
limit: Optional[int] = None,
|
|
83
|
-
|
|
84
|
-
) -> list[FundingRate]:
|
|
96
|
+
) -> CursorResponse[list[FundingRate]]:
|
|
85
97
|
"""Async version of history(). start and end are required."""
|
|
86
98
|
data = await self._http.aget(
|
|
87
99
|
f"/v1/funding/{coin.upper()}",
|
|
88
100
|
params={
|
|
89
101
|
"start": self._convert_timestamp(start),
|
|
90
102
|
"end": self._convert_timestamp(end),
|
|
103
|
+
"cursor": self._convert_timestamp(cursor),
|
|
91
104
|
"limit": limit,
|
|
92
|
-
"offset": offset,
|
|
93
105
|
},
|
|
94
106
|
)
|
|
95
|
-
return
|
|
107
|
+
return CursorResponse(
|
|
108
|
+
data=[FundingRate.model_validate(item) for item in data["data"]],
|
|
109
|
+
next_cursor=data.get("meta", {}).get("next_cursor"),
|
|
110
|
+
)
|
|
96
111
|
|
|
97
112
|
def current(self, coin: str) -> FundingRate:
|
|
98
113
|
"""
|
|
@@ -6,7 +6,7 @@ from datetime import datetime
|
|
|
6
6
|
from typing import Optional
|
|
7
7
|
|
|
8
8
|
from ..http import HttpClient
|
|
9
|
-
from ..types import OpenInterest, Timestamp
|
|
9
|
+
from ..types import CursorResponse, OpenInterest, Timestamp
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class OpenInterestResource:
|
|
@@ -46,32 +46,44 @@ class OpenInterestResource:
|
|
|
46
46
|
*,
|
|
47
47
|
start: Timestamp,
|
|
48
48
|
end: Timestamp,
|
|
49
|
+
cursor: Optional[Timestamp] = None,
|
|
49
50
|
limit: Optional[int] = None,
|
|
50
|
-
|
|
51
|
-
) -> list[OpenInterest]:
|
|
51
|
+
) -> CursorResponse[list[OpenInterest]]:
|
|
52
52
|
"""
|
|
53
|
-
Get open interest history for a coin.
|
|
53
|
+
Get open interest history for a coin with cursor-based pagination.
|
|
54
54
|
|
|
55
55
|
Args:
|
|
56
56
|
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
57
57
|
start: Start timestamp (required)
|
|
58
58
|
end: End timestamp (required)
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
cursor: Cursor from previous response's next_cursor (timestamp)
|
|
60
|
+
limit: Maximum number of results (default: 100, max: 1000)
|
|
61
61
|
|
|
62
62
|
Returns:
|
|
63
|
-
|
|
63
|
+
CursorResponse with open interest records and next_cursor for pagination
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
>>> result = client.open_interest.history("BTC", start=start, end=end, limit=1000)
|
|
67
|
+
>>> records = result.data
|
|
68
|
+
>>> while result.next_cursor:
|
|
69
|
+
... result = client.open_interest.history(
|
|
70
|
+
... "BTC", start=start, end=end, cursor=result.next_cursor, limit=1000
|
|
71
|
+
... )
|
|
72
|
+
... records.extend(result.data)
|
|
64
73
|
"""
|
|
65
74
|
data = self._http.get(
|
|
66
75
|
f"/v1/openinterest/{coin.upper()}",
|
|
67
76
|
params={
|
|
68
77
|
"start": self._convert_timestamp(start),
|
|
69
78
|
"end": self._convert_timestamp(end),
|
|
79
|
+
"cursor": self._convert_timestamp(cursor),
|
|
70
80
|
"limit": limit,
|
|
71
|
-
"offset": offset,
|
|
72
81
|
},
|
|
73
82
|
)
|
|
74
|
-
return
|
|
83
|
+
return CursorResponse(
|
|
84
|
+
data=[OpenInterest.model_validate(item) for item in data["data"]],
|
|
85
|
+
next_cursor=data.get("meta", {}).get("next_cursor"),
|
|
86
|
+
)
|
|
75
87
|
|
|
76
88
|
async def ahistory(
|
|
77
89
|
self,
|
|
@@ -79,20 +91,23 @@ class OpenInterestResource:
|
|
|
79
91
|
*,
|
|
80
92
|
start: Timestamp,
|
|
81
93
|
end: Timestamp,
|
|
94
|
+
cursor: Optional[Timestamp] = None,
|
|
82
95
|
limit: Optional[int] = None,
|
|
83
|
-
|
|
84
|
-
) -> list[OpenInterest]:
|
|
96
|
+
) -> CursorResponse[list[OpenInterest]]:
|
|
85
97
|
"""Async version of history(). start and end are required."""
|
|
86
98
|
data = await self._http.aget(
|
|
87
99
|
f"/v1/openinterest/{coin.upper()}",
|
|
88
100
|
params={
|
|
89
101
|
"start": self._convert_timestamp(start),
|
|
90
102
|
"end": self._convert_timestamp(end),
|
|
103
|
+
"cursor": self._convert_timestamp(cursor),
|
|
91
104
|
"limit": limit,
|
|
92
|
-
"offset": offset,
|
|
93
105
|
},
|
|
94
106
|
)
|
|
95
|
-
return
|
|
107
|
+
return CursorResponse(
|
|
108
|
+
data=[OpenInterest.model_validate(item) for item in data["data"]],
|
|
109
|
+
next_cursor=data.get("meta", {}).get("next_cursor"),
|
|
110
|
+
)
|
|
96
111
|
|
|
97
112
|
def current(self, coin: str) -> OpenInterest:
|
|
98
113
|
"""
|
oxarchive/resources/orderbook.py
CHANGED
|
@@ -6,7 +6,7 @@ from datetime import datetime
|
|
|
6
6
|
from typing import Optional, Union
|
|
7
7
|
|
|
8
8
|
from ..http import HttpClient
|
|
9
|
-
from ..types import OrderBook, Timestamp
|
|
9
|
+
from ..types import CursorResponse, OrderBook, Timestamp
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class OrderBookResource:
|
|
@@ -94,35 +94,47 @@ class OrderBookResource:
|
|
|
94
94
|
*,
|
|
95
95
|
start: Timestamp,
|
|
96
96
|
end: Timestamp,
|
|
97
|
+
cursor: Optional[Timestamp] = None,
|
|
97
98
|
limit: Optional[int] = None,
|
|
98
|
-
offset: Optional[int] = None,
|
|
99
99
|
depth: Optional[int] = None,
|
|
100
|
-
) -> list[OrderBook]:
|
|
100
|
+
) -> CursorResponse[list[OrderBook]]:
|
|
101
101
|
"""
|
|
102
|
-
Get historical order book snapshots.
|
|
102
|
+
Get historical order book snapshots with cursor-based pagination.
|
|
103
103
|
|
|
104
104
|
Args:
|
|
105
105
|
coin: The coin symbol (e.g., 'BTC', 'ETH')
|
|
106
106
|
start: Start timestamp (required)
|
|
107
107
|
end: End timestamp (required)
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
cursor: Cursor from previous response's next_cursor (timestamp)
|
|
109
|
+
limit: Maximum number of results (default: 100, max: 1000)
|
|
110
110
|
depth: Number of price levels per side
|
|
111
111
|
|
|
112
112
|
Returns:
|
|
113
|
-
|
|
113
|
+
CursorResponse with order book snapshots and next_cursor for pagination
|
|
114
|
+
|
|
115
|
+
Example:
|
|
116
|
+
>>> result = client.orderbook.history("BTC", start=start, end=end, limit=1000)
|
|
117
|
+
>>> snapshots = result.data
|
|
118
|
+
>>> while result.next_cursor:
|
|
119
|
+
... result = client.orderbook.history(
|
|
120
|
+
... "BTC", start=start, end=end, cursor=result.next_cursor, limit=1000
|
|
121
|
+
... )
|
|
122
|
+
... snapshots.extend(result.data)
|
|
114
123
|
"""
|
|
115
124
|
data = self._http.get(
|
|
116
125
|
f"/v1/orderbook/{coin.upper()}/history",
|
|
117
126
|
params={
|
|
118
127
|
"start": self._convert_timestamp(start),
|
|
119
128
|
"end": self._convert_timestamp(end),
|
|
129
|
+
"cursor": self._convert_timestamp(cursor),
|
|
120
130
|
"limit": limit,
|
|
121
|
-
"offset": offset,
|
|
122
131
|
"depth": depth,
|
|
123
132
|
},
|
|
124
133
|
)
|
|
125
|
-
return
|
|
134
|
+
return CursorResponse(
|
|
135
|
+
data=[OrderBook.model_validate(item) for item in data["data"]],
|
|
136
|
+
next_cursor=data.get("meta", {}).get("next_cursor"),
|
|
137
|
+
)
|
|
126
138
|
|
|
127
139
|
async def ahistory(
|
|
128
140
|
self,
|
|
@@ -130,19 +142,22 @@ class OrderBookResource:
|
|
|
130
142
|
*,
|
|
131
143
|
start: Timestamp,
|
|
132
144
|
end: Timestamp,
|
|
145
|
+
cursor: Optional[Timestamp] = None,
|
|
133
146
|
limit: Optional[int] = None,
|
|
134
|
-
offset: Optional[int] = None,
|
|
135
147
|
depth: Optional[int] = None,
|
|
136
|
-
) -> list[OrderBook]:
|
|
148
|
+
) -> CursorResponse[list[OrderBook]]:
|
|
137
149
|
"""Async version of history(). start and end are required."""
|
|
138
150
|
data = await self._http.aget(
|
|
139
151
|
f"/v1/orderbook/{coin.upper()}/history",
|
|
140
152
|
params={
|
|
141
153
|
"start": self._convert_timestamp(start),
|
|
142
154
|
"end": self._convert_timestamp(end),
|
|
155
|
+
"cursor": self._convert_timestamp(cursor),
|
|
143
156
|
"limit": limit,
|
|
144
|
-
"offset": offset,
|
|
145
157
|
"depth": depth,
|
|
146
158
|
},
|
|
147
159
|
)
|
|
148
|
-
return
|
|
160
|
+
return CursorResponse(
|
|
161
|
+
data=[OrderBook.model_validate(item) for item in data["data"]],
|
|
162
|
+
next_cursor=data.get("meta", {}).get("next_cursor"),
|
|
163
|
+
)
|
oxarchive/resources/trades.py
CHANGED
|
@@ -2,20 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import warnings
|
|
6
|
-
from dataclasses import dataclass
|
|
7
5
|
from datetime import datetime
|
|
8
6
|
from typing import Literal, Optional
|
|
9
7
|
|
|
10
8
|
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
|
|
9
|
+
from ..types import CursorResponse, Trade, Timestamp
|
|
19
10
|
|
|
20
11
|
|
|
21
12
|
class TradesResource:
|
|
@@ -64,7 +55,7 @@ class TradesResource:
|
|
|
64
55
|
cursor: Optional[Timestamp] = None,
|
|
65
56
|
limit: Optional[int] = None,
|
|
66
57
|
side: Optional[Literal["buy", "sell"]] = None,
|
|
67
|
-
) -> CursorResponse:
|
|
58
|
+
) -> CursorResponse[list[Trade]]:
|
|
68
59
|
"""
|
|
69
60
|
Get trade history for a coin using cursor-based pagination.
|
|
70
61
|
|
|
@@ -118,7 +109,7 @@ class TradesResource:
|
|
|
118
109
|
cursor: Optional[Timestamp] = None,
|
|
119
110
|
limit: Optional[int] = None,
|
|
120
111
|
side: Optional[Literal["buy", "sell"]] = None,
|
|
121
|
-
) -> CursorResponse:
|
|
112
|
+
) -> CursorResponse[list[Trade]]:
|
|
122
113
|
"""
|
|
123
114
|
Async version of list().
|
|
124
115
|
|
|
@@ -139,83 +130,6 @@ class TradesResource:
|
|
|
139
130
|
next_cursor=data.get("meta", {}).get("next_cursor"),
|
|
140
131
|
)
|
|
141
132
|
|
|
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
133
|
def recent(self, coin: str, limit: Optional[int] = None) -> list[Trade]:
|
|
220
134
|
"""
|
|
221
135
|
Get most recent trades for a coin.
|
|
@@ -240,60 +154,3 @@ class TradesResource:
|
|
|
240
154
|
params={"limit": limit},
|
|
241
155
|
)
|
|
242
156
|
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)
|
oxarchive/types.py
CHANGED
|
@@ -411,6 +411,21 @@ class OxArchiveError(Exception):
|
|
|
411
411
|
return f"[{self.code}] {self.message}"
|
|
412
412
|
|
|
413
413
|
|
|
414
|
+
# =============================================================================
|
|
415
|
+
# Pagination Types
|
|
416
|
+
# =============================================================================
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
class CursorResponse(BaseModel, Generic[T]):
|
|
420
|
+
"""Response with cursor for pagination."""
|
|
421
|
+
|
|
422
|
+
data: T
|
|
423
|
+
"""The paginated data."""
|
|
424
|
+
|
|
425
|
+
next_cursor: Optional[str] = None
|
|
426
|
+
"""Cursor for the next page (use as cursor parameter)."""
|
|
427
|
+
|
|
428
|
+
|
|
414
429
|
# Type alias for timestamp parameters
|
|
415
430
|
Timestamp = Union[int, str, datetime]
|
|
416
431
|
"""Timestamp can be Unix ms (int), ISO string, or datetime object."""
|
oxarchive/websocket.py
CHANGED
|
@@ -32,6 +32,7 @@ from typing import Any, Callable, Optional, Set, Union
|
|
|
32
32
|
|
|
33
33
|
try:
|
|
34
34
|
from websockets.asyncio.client import connect as ws_connect, ClientConnection
|
|
35
|
+
from websockets.exceptions import ConnectionClosed
|
|
35
36
|
from websockets.protocol import State as WsState
|
|
36
37
|
except ImportError:
|
|
37
38
|
raise ImportError(
|
|
@@ -650,7 +651,7 @@ class OxArchiveWs:
|
|
|
650
651
|
try:
|
|
651
652
|
message = await self._ws.recv()
|
|
652
653
|
self._handle_message(message)
|
|
653
|
-
except
|
|
654
|
+
except ConnectionClosed as e:
|
|
654
655
|
logger.info(f"Connection closed: {e.code} {e.reason}")
|
|
655
656
|
if self._on_close:
|
|
656
657
|
self._on_close(e.code, e.reason)
|
|
@@ -0,0 +1,14 @@
|
|
|
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,,
|
oxarchive-0.3.9.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
oxarchive/__init__.py,sha256=c1JP0iZrqbnOrcTSfbMHDoojzHoDmDobFv7Mvv7qk5A,2181
|
|
2
|
-
oxarchive/client.py,sha256=3P0fvOcyM5BWppkVV4054NduDHKvRg-cWeluoGymmRk,3163
|
|
3
|
-
oxarchive/http.py,sha256=SY_o9Ag8ADo1HI3i3uAKW1xwkYjPE75gRAjnMsddAGs,4211
|
|
4
|
-
oxarchive/types.py,sha256=lM3WrATnHcxGs0fLq54Lka-FTvXqiwWe2He2Qn9SrSA,10844
|
|
5
|
-
oxarchive/websocket.py,sha256=0w7OebFUo_4c3AnjG-9vfX9IBHKyTbvgAWUXhxFO53I,28336
|
|
6
|
-
oxarchive/resources/__init__.py,sha256=WQ4GYQ8p3L0D2Isk4IV4h1DRpvyZlt6tOF1t_CJr6ls,385
|
|
7
|
-
oxarchive/resources/funding.py,sha256=TXkZxodVQTVcVbzNG6SpMQAzf8AkLm2NYZJxnP4MNXw,3500
|
|
8
|
-
oxarchive/resources/instruments.py,sha256=flD1sH6x3P3CTqV1ZwkfwbranVacmhsHn5Dhr7lGQhM,1606
|
|
9
|
-
oxarchive/resources/openinterest.py,sha256=h13yLA72LpfryUf8IqF6W7uE4ObYY2Qbc-auv4LtPqc,3552
|
|
10
|
-
oxarchive/resources/orderbook.py,sha256=o_DTdpzKrZvHL9YXm8cGGUugPM8uUa6r9O_72r1ByV0,4557
|
|
11
|
-
oxarchive/resources/trades.py,sha256=XCi2rXA2hxaTt0KNlWw8f7W0hzAvNWyT7DaivMz_rHw,10012
|
|
12
|
-
oxarchive-0.3.9.dist-info/METADATA,sha256=O7olK5nYQ8HeHaxQwgvRUtayOudvTcgAYnhv1eTv-ro,11070
|
|
13
|
-
oxarchive-0.3.9.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
14
|
-
oxarchive-0.3.9.dist-info/RECORD,,
|
|
File without changes
|