unicex 0.15.2__py3-none-any.whl → 0.16.0__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.
- unicex/_abc/exchange_info.py +1 -1
- unicex/_abc/uni_client.py +1 -1
- unicex/_abc/uni_websocket_manager.py +1 -1
- unicex/_base/client.py +7 -0
- unicex/binance/adapter.py +5 -1
- unicex/bingx/adapter.py +1 -1
- unicex/bingx/uni_websocket_manager.py +2 -2
- unicex/bingx/websocket_manager.py +2 -4
- unicex/bitget/adapter.py +1 -0
- unicex/bitget/uni_websocket_manager.py +21 -4
- unicex/bitget/websocket_manager.py +2 -4
- unicex/bybit/adapter.py +1 -0
- unicex/bybit/websocket_manager.py +7 -24
- unicex/extra.py +23 -23
- unicex/gate/adapter.py +103 -0
- unicex/gate/uni_websocket_manager.py +41 -7
- unicex/hyperliquid/adapter.py +1 -0
- unicex/kucoin/adapter.py +4 -9
- unicex/kucoin/client.py +13 -0
- unicex/kucoin/uni_client.py +2 -14
- unicex/mexc/_spot_ws_proto/__init__.py +335 -335
- unicex/mexc/adapter.py +104 -0
- unicex/mexc/uni_websocket_manager.py +25 -7
- unicex/mexc/websocket_manager.py +26 -5
- unicex/okx/adapter.py +51 -0
- unicex/okx/uni_websocket_manager.py +44 -7
- unicex/types.py +6 -3
- unicex/utils.py +22 -1
- {unicex-0.15.2.dist-info → unicex-0.16.0.dist-info}/METADATA +5 -5
- {unicex-0.15.2.dist-info → unicex-0.16.0.dist-info}/RECORD +33 -33
- {unicex-0.15.2.dist-info → unicex-0.16.0.dist-info}/WHEEL +0 -0
- {unicex-0.15.2.dist-info → unicex-0.16.0.dist-info}/licenses/LICENSE +0 -0
- {unicex-0.15.2.dist-info → unicex-0.16.0.dist-info}/top_level.txt +0 -0
unicex/mexc/adapter.py
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
__all__ = ["Adapter"]
|
|
2
2
|
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
3
5
|
from unicex.types import (
|
|
4
6
|
KlineDict,
|
|
5
7
|
OpenInterestDict,
|
|
6
8
|
OpenInterestItem,
|
|
7
9
|
TickerDailyDict,
|
|
8
10
|
TickerDailyItem,
|
|
11
|
+
TradeDict,
|
|
9
12
|
)
|
|
10
13
|
from unicex.utils import catch_adapter_errors, decorate_all_methods
|
|
11
14
|
|
|
@@ -127,6 +130,7 @@ class Adapter:
|
|
|
127
130
|
result[symbol] = OpenInterestItem(
|
|
128
131
|
t=item["timestamp"],
|
|
129
132
|
v=float(item["holdVol"]) * Adapter._get_contract_size(symbol),
|
|
133
|
+
u="coins",
|
|
130
134
|
)
|
|
131
135
|
return result
|
|
132
136
|
|
|
@@ -230,6 +234,106 @@ class Adapter:
|
|
|
230
234
|
|
|
231
235
|
return sorted(klines, key=lambda kline_item: kline_item["t"])
|
|
232
236
|
|
|
237
|
+
@staticmethod
|
|
238
|
+
def klines_message(raw_msg: Any) -> list[KlineDict]:
|
|
239
|
+
"""Преобразует вебсокет-сообщение со свечами в унифицированный формат.
|
|
240
|
+
|
|
241
|
+
Параметры:
|
|
242
|
+
raw_msg (Any): Сырое сообщение с вебсокета.
|
|
243
|
+
|
|
244
|
+
Возвращает:
|
|
245
|
+
list[KlineDict]: Список свечей в унифицированном формате.
|
|
246
|
+
"""
|
|
247
|
+
kline = raw_msg["publicSpotKline"]
|
|
248
|
+
return [
|
|
249
|
+
KlineDict(
|
|
250
|
+
s=raw_msg["symbol"],
|
|
251
|
+
t=int(kline["windowStart"]) * 1000,
|
|
252
|
+
o=float(kline["openingPrice"]),
|
|
253
|
+
h=float(kline["highestPrice"]),
|
|
254
|
+
l=float(kline["lowestPrice"]),
|
|
255
|
+
c=float(kline["closingPrice"]),
|
|
256
|
+
v=float(kline["volume"]),
|
|
257
|
+
T=int(kline["windowEnd"]) * 1000,
|
|
258
|
+
x=None,
|
|
259
|
+
q=float(kline["amount"]),
|
|
260
|
+
)
|
|
261
|
+
]
|
|
262
|
+
|
|
263
|
+
@staticmethod
|
|
264
|
+
def futures_klines_message(raw_msg: Any) -> list[KlineDict]:
|
|
265
|
+
"""Преобразует вебсокет-сообщение со свечами в унифицированный формат.
|
|
266
|
+
|
|
267
|
+
Параметры:
|
|
268
|
+
raw_msg (Any): Сырое сообщение с вебсокета.
|
|
269
|
+
|
|
270
|
+
Возвращает:
|
|
271
|
+
list[KlineDict]: Список свечей в унифицированном формате.
|
|
272
|
+
"""
|
|
273
|
+
data = raw_msg["data"]
|
|
274
|
+
return [
|
|
275
|
+
KlineDict(
|
|
276
|
+
s=data["symbol"],
|
|
277
|
+
t=data["t"] * 1000,
|
|
278
|
+
o=data["o"],
|
|
279
|
+
h=data["h"],
|
|
280
|
+
l=data["l"],
|
|
281
|
+
c=data["c"],
|
|
282
|
+
v=data["q"], # Контракты
|
|
283
|
+
q=data["a"],
|
|
284
|
+
T=None,
|
|
285
|
+
x=None,
|
|
286
|
+
)
|
|
287
|
+
]
|
|
288
|
+
|
|
289
|
+
@staticmethod
|
|
290
|
+
def trades_message(raw_msg: Any) -> list[TradeDict]:
|
|
291
|
+
"""Преобразует вебсокет-сообщение со сделками в унифицированный формат.
|
|
292
|
+
|
|
293
|
+
Параметры:
|
|
294
|
+
raw_msg (Any): Сырое сообщение с вебсокета.
|
|
295
|
+
|
|
296
|
+
Возвращает:
|
|
297
|
+
list[TradeDict]: Список сделок в унифицированном формате.
|
|
298
|
+
"""
|
|
299
|
+
return [
|
|
300
|
+
TradeDict(
|
|
301
|
+
t=trade["time"],
|
|
302
|
+
s=raw_msg["symbol"],
|
|
303
|
+
S="BUY" if trade["tradeType"] == 1 else "SELL",
|
|
304
|
+
p=float(trade["price"]),
|
|
305
|
+
v=float(trade["quantity"]),
|
|
306
|
+
)
|
|
307
|
+
for trade in sorted(
|
|
308
|
+
raw_msg["publicAggreDeals"]["deals"],
|
|
309
|
+
key=lambda item: item["time"],
|
|
310
|
+
)
|
|
311
|
+
]
|
|
312
|
+
|
|
313
|
+
@staticmethod
|
|
314
|
+
def futures_trades_message(raw_msg: Any) -> list[TradeDict]:
|
|
315
|
+
"""Преобразует вебсокет-сообщение со сделками в унифицированный формат.
|
|
316
|
+
|
|
317
|
+
Параметры:
|
|
318
|
+
raw_msg (Any): Сырое сообщение с вебсокета.
|
|
319
|
+
|
|
320
|
+
Возвращает:
|
|
321
|
+
list[TradeDict]: Список сделок в унифицированном формате.
|
|
322
|
+
"""
|
|
323
|
+
return [
|
|
324
|
+
TradeDict(
|
|
325
|
+
t=item["t"],
|
|
326
|
+
s=raw_msg["symbol"],
|
|
327
|
+
S="BUY" if item["T"] == 1 else "SELL",
|
|
328
|
+
p=item["p"],
|
|
329
|
+
v=item["v"],
|
|
330
|
+
)
|
|
331
|
+
for item in sorted(
|
|
332
|
+
raw_msg["data"],
|
|
333
|
+
key=lambda item: item["t"],
|
|
334
|
+
)
|
|
335
|
+
]
|
|
336
|
+
|
|
233
337
|
@staticmethod
|
|
234
338
|
def _get_contract_size(symbol: str) -> float:
|
|
235
339
|
"""Возвращает размер контракта для указанного символа тикера."""
|
|
@@ -5,7 +5,7 @@ from typing import Any, overload
|
|
|
5
5
|
|
|
6
6
|
from unicex._abc import IUniWebsocketManager
|
|
7
7
|
from unicex._base import Websocket
|
|
8
|
-
from unicex.enums import Timeframe
|
|
8
|
+
from unicex.enums import Exchange, MarketType, Timeframe
|
|
9
9
|
from unicex.types import LoggerLike
|
|
10
10
|
|
|
11
11
|
from .adapter import Adapter
|
|
@@ -76,7 +76,15 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
76
76
|
Возвращает:
|
|
77
77
|
`Websocket`: Экземпляр вебсокета для управления соединением.
|
|
78
78
|
"""
|
|
79
|
-
|
|
79
|
+
wrapper = self._make_wrapper(self._adapter.klines_message, callback)
|
|
80
|
+
return self._websocket_manager.klines(
|
|
81
|
+
callback=wrapper,
|
|
82
|
+
symbol=symbol,
|
|
83
|
+
symbols=symbols,
|
|
84
|
+
interval=timeframe.to_exchange_format(
|
|
85
|
+
Exchange.MEXC, MarketType.FUTURES
|
|
86
|
+
), # Тут фьючерсный интервал, потому что для вебсокета MEXC решили что сделают так (идиоты)
|
|
87
|
+
)
|
|
80
88
|
|
|
81
89
|
@overload
|
|
82
90
|
def futures_klines(
|
|
@@ -118,7 +126,13 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
118
126
|
Возвращает:
|
|
119
127
|
`Websocket`: Экземпляр вебсокета.
|
|
120
128
|
"""
|
|
121
|
-
|
|
129
|
+
wrapper = self._make_wrapper(self._adapter.futures_klines_message, callback)
|
|
130
|
+
return self._websocket_manager.futures_kline(
|
|
131
|
+
callback=wrapper,
|
|
132
|
+
symbol=symbol,
|
|
133
|
+
symbols=symbols,
|
|
134
|
+
interval=timeframe.to_exchange_format(Exchange.MEXC, MarketType.FUTURES),
|
|
135
|
+
)
|
|
122
136
|
|
|
123
137
|
@overload
|
|
124
138
|
def trades(
|
|
@@ -156,7 +170,8 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
156
170
|
Возвращает:
|
|
157
171
|
`Websocket`: Экземпляр вебсокета.
|
|
158
172
|
"""
|
|
159
|
-
|
|
173
|
+
wrapper = self._make_wrapper(self._adapter.trades_message, callback)
|
|
174
|
+
return self._websocket_manager.trade(callback=wrapper, symbol=symbol, symbols=symbols)
|
|
160
175
|
|
|
161
176
|
@overload
|
|
162
177
|
def aggtrades(
|
|
@@ -194,7 +209,7 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
194
209
|
Возвращает:
|
|
195
210
|
`Websocket`: Экземпляр вебсокета.
|
|
196
211
|
"""
|
|
197
|
-
|
|
212
|
+
return self.trades(callback=callback, symbol=symbol, symbols=symbols) # type: ignore[reportCallIssue]
|
|
198
213
|
|
|
199
214
|
@overload
|
|
200
215
|
def futures_trades(
|
|
@@ -232,7 +247,10 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
232
247
|
Возвращает:
|
|
233
248
|
`Websocket`: Экземпляр вебсокета.
|
|
234
249
|
"""
|
|
235
|
-
|
|
250
|
+
wrapper = self._make_wrapper(self._adapter.futures_trades_message, callback)
|
|
251
|
+
return self._websocket_manager.futures_trade(
|
|
252
|
+
callback=wrapper, symbol=symbol, symbols=symbols
|
|
253
|
+
)
|
|
236
254
|
|
|
237
255
|
@overload
|
|
238
256
|
def futures_aggtrades(
|
|
@@ -270,4 +288,4 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
270
288
|
Возвращает:
|
|
271
289
|
`Websocket`: Экземпляр вебсокета.
|
|
272
290
|
"""
|
|
273
|
-
|
|
291
|
+
return self.futures_trades(callback=callback, symbol=symbol, symbols=symbols) # type: ignore[reportCallIssue]
|
unicex/mexc/websocket_manager.py
CHANGED
|
@@ -8,6 +8,7 @@ import orjson
|
|
|
8
8
|
from google.protobuf.json_format import MessageToDict
|
|
9
9
|
|
|
10
10
|
from unicex._base import Websocket
|
|
11
|
+
from unicex.utils import validate_single_symbol_args
|
|
11
12
|
|
|
12
13
|
from ._spot_ws_proto import PushDataV3ApiWrapper
|
|
13
14
|
from .client import Client
|
|
@@ -55,10 +56,7 @@ class WebsocketManager:
|
|
|
55
56
|
**template_kwargs: Any,
|
|
56
57
|
) -> list[str]:
|
|
57
58
|
"""Сформировать сообщение для подписки на вебсокет."""
|
|
58
|
-
|
|
59
|
-
raise ValueError("Parameters symbol and symbols cannot be used together")
|
|
60
|
-
if not (symbol or symbols):
|
|
61
|
-
raise ValueError("Either symbol or symbols must be provided")
|
|
59
|
+
validate_single_symbol_args(symbol, symbols)
|
|
62
60
|
|
|
63
61
|
if symbol:
|
|
64
62
|
params = [channel_template.format(symbol=symbol, **template_kwargs)]
|
|
@@ -382,7 +380,30 @@ class WebsocketManager:
|
|
|
382
380
|
`Websocket`: Объект для управления вебсокет соединением.
|
|
383
381
|
"""
|
|
384
382
|
subscription_messages = self._generate_futures_subscription_message(
|
|
385
|
-
topic="sub.
|
|
383
|
+
topic="sub.kline", symbol=symbol, symbols=symbols, interval=interval
|
|
384
|
+
)
|
|
385
|
+
return self._create_futures_websocket(callback, subscription_messages)
|
|
386
|
+
|
|
387
|
+
def futures_trade(
|
|
388
|
+
self,
|
|
389
|
+
callback: CallbackType,
|
|
390
|
+
symbol: str | None = None,
|
|
391
|
+
symbols: Sequence[str] | None = None,
|
|
392
|
+
) -> Websocket:
|
|
393
|
+
"""Создает вебсокет для получения сделок по фьючерсным контрактам.
|
|
394
|
+
|
|
395
|
+
https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
|
|
396
|
+
|
|
397
|
+
Параметры:
|
|
398
|
+
callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
|
|
399
|
+
symbol (`str | None`): Символ фьючерсного контракта.
|
|
400
|
+
symbols (`Sequence[str] | None`): Последовательность символов фьючерсных контрактов.
|
|
401
|
+
|
|
402
|
+
Возвращает:
|
|
403
|
+
`Websocket`: Объект для управления вебсокет соединением.
|
|
404
|
+
"""
|
|
405
|
+
subscription_messages = self._generate_futures_subscription_message(
|
|
406
|
+
topic="sub.deal", symbol=symbol, symbols=symbols
|
|
386
407
|
)
|
|
387
408
|
return self._create_futures_websocket(callback, subscription_messages)
|
|
388
409
|
|
unicex/okx/adapter.py
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
__all__ = ["Adapter"]
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
4
6
|
from unicex.types import (
|
|
5
7
|
KlineDict,
|
|
6
8
|
OpenInterestDict,
|
|
7
9
|
OpenInterestItem,
|
|
8
10
|
TickerDailyDict,
|
|
9
11
|
TickerDailyItem,
|
|
12
|
+
TradeDict,
|
|
10
13
|
)
|
|
11
14
|
from unicex.utils import catch_adapter_errors, decorate_all_methods
|
|
12
15
|
|
|
@@ -135,6 +138,54 @@ class Adapter:
|
|
|
135
138
|
item["instId"]: OpenInterestItem(
|
|
136
139
|
t=int(item["ts"]),
|
|
137
140
|
v=float(item["oiCcy"]),
|
|
141
|
+
u="coins",
|
|
138
142
|
)
|
|
139
143
|
for item in raw_data["data"]
|
|
140
144
|
}
|
|
145
|
+
|
|
146
|
+
@staticmethod
|
|
147
|
+
def klines_message(raw_msg: Any) -> list[KlineDict]:
|
|
148
|
+
"""Преобразует вебсокет-сообщение со свечами в унифицированный формат.
|
|
149
|
+
|
|
150
|
+
Параметры:
|
|
151
|
+
raw_msg (Any): Сырое сообщение с вебсокета.
|
|
152
|
+
|
|
153
|
+
Возвращает:
|
|
154
|
+
list[KlineDict]: Список свечей в унифицированном формате.
|
|
155
|
+
"""
|
|
156
|
+
return [
|
|
157
|
+
KlineDict(
|
|
158
|
+
s=raw_msg["arg"]["instId"],
|
|
159
|
+
t=int(kline[0]),
|
|
160
|
+
o=float(kline[1]),
|
|
161
|
+
h=float(kline[2]),
|
|
162
|
+
l=float(kline[3]),
|
|
163
|
+
c=float(kline[4]),
|
|
164
|
+
v=float(kline[6]),
|
|
165
|
+
q=float(kline[7]),
|
|
166
|
+
T=None,
|
|
167
|
+
x=bool(int(kline[8])),
|
|
168
|
+
)
|
|
169
|
+
for kline in sorted(raw_msg["data"], key=lambda item: int(item[0]))
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
@staticmethod
|
|
173
|
+
def trades_message(raw_msg: Any) -> list[TradeDict]:
|
|
174
|
+
"""Преобразует вебсокет-сообщение со сделками в унифицированный формат.
|
|
175
|
+
|
|
176
|
+
Параметры:
|
|
177
|
+
raw_msg (Any): Сырое сообщение с вебсокета.
|
|
178
|
+
|
|
179
|
+
Возвращает:
|
|
180
|
+
list[TradeDict]: Список сделок в унифицированном формате.
|
|
181
|
+
"""
|
|
182
|
+
return [
|
|
183
|
+
TradeDict(
|
|
184
|
+
t=int(trade["ts"]),
|
|
185
|
+
s=trade["instId"],
|
|
186
|
+
S=trade["side"].upper(),
|
|
187
|
+
p=float(trade["px"]),
|
|
188
|
+
v=float(trade["sz"]),
|
|
189
|
+
)
|
|
190
|
+
for trade in sorted(raw_msg["data"], key=lambda item: int(item["ts"]))
|
|
191
|
+
]
|
|
@@ -5,7 +5,7 @@ from typing import Any, overload
|
|
|
5
5
|
|
|
6
6
|
from unicex._abc import IUniWebsocketManager
|
|
7
7
|
from unicex._base import Websocket
|
|
8
|
-
from unicex.enums import Timeframe
|
|
8
|
+
from unicex.enums import Exchange, Timeframe
|
|
9
9
|
from unicex.types import LoggerLike
|
|
10
10
|
|
|
11
11
|
from .adapter import Adapter
|
|
@@ -36,6 +36,23 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
36
36
|
self._websocket_manager = WebsocketManager(self._client, **ws_kwargs) # type: ignore
|
|
37
37
|
self._adapter = Adapter()
|
|
38
38
|
|
|
39
|
+
def _normalize_symbol(
|
|
40
|
+
self,
|
|
41
|
+
symbol: str | None,
|
|
42
|
+
symbols: Sequence[str] | None,
|
|
43
|
+
) -> str:
|
|
44
|
+
"""Преобразует параметры symbol/symbols в один тикер."""
|
|
45
|
+
if symbol and symbols:
|
|
46
|
+
raise ValueError("Parameters symbol and symbols cannot be used together")
|
|
47
|
+
if symbol:
|
|
48
|
+
return symbol
|
|
49
|
+
if symbols:
|
|
50
|
+
normalized = list(symbols)
|
|
51
|
+
if len(normalized) != 1:
|
|
52
|
+
raise ValueError("OKX websocket поддерживает только один тикер на соединение")
|
|
53
|
+
return normalized[0]
|
|
54
|
+
raise ValueError("Either symbol or symbols must be provided")
|
|
55
|
+
|
|
39
56
|
@overload
|
|
40
57
|
def klines(
|
|
41
58
|
self,
|
|
@@ -76,7 +93,13 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
76
93
|
Возвращает:
|
|
77
94
|
`Websocket`: Экземпляр вебсокета для управления соединением.
|
|
78
95
|
"""
|
|
79
|
-
|
|
96
|
+
inst_id = self._normalize_symbol(symbol, symbols)
|
|
97
|
+
wrapper = self._make_wrapper(self._adapter.klines_message, callback)
|
|
98
|
+
return self._websocket_manager.candlesticks(
|
|
99
|
+
callback=wrapper,
|
|
100
|
+
interval=timeframe.to_exchange_format(Exchange.OKX), # type: ignore
|
|
101
|
+
inst_id=inst_id,
|
|
102
|
+
)
|
|
80
103
|
|
|
81
104
|
@overload
|
|
82
105
|
def futures_klines(
|
|
@@ -118,7 +141,13 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
118
141
|
Возвращает:
|
|
119
142
|
`Websocket`: Экземпляр вебсокета.
|
|
120
143
|
"""
|
|
121
|
-
|
|
144
|
+
inst_id = self._normalize_symbol(symbol, symbols)
|
|
145
|
+
wrapper = self._make_wrapper(self._adapter.klines_message, callback)
|
|
146
|
+
return self._websocket_manager.candlesticks(
|
|
147
|
+
callback=wrapper,
|
|
148
|
+
interval=timeframe.to_exchange_format(Exchange.OKX), # type: ignore
|
|
149
|
+
inst_id=inst_id,
|
|
150
|
+
)
|
|
122
151
|
|
|
123
152
|
@overload
|
|
124
153
|
def trades(
|
|
@@ -156,7 +185,9 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
156
185
|
Возвращает:
|
|
157
186
|
`Websocket`: Экземпляр вебсокета.
|
|
158
187
|
"""
|
|
159
|
-
|
|
188
|
+
inst_id = self._normalize_symbol(symbol, symbols)
|
|
189
|
+
wrapper = self._make_wrapper(self._adapter.trades_message, callback)
|
|
190
|
+
return self._websocket_manager.all_trades(callback=wrapper, inst_id=inst_id)
|
|
160
191
|
|
|
161
192
|
@overload
|
|
162
193
|
def aggtrades(
|
|
@@ -194,7 +225,9 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
194
225
|
Возвращает:
|
|
195
226
|
`Websocket`: Экземпляр вебсокета.
|
|
196
227
|
"""
|
|
197
|
-
|
|
228
|
+
inst_id = self._normalize_symbol(symbol, symbols)
|
|
229
|
+
wrapper = self._make_wrapper(self._adapter.trades_message, callback)
|
|
230
|
+
return self._websocket_manager.trades(callback=wrapper, inst_id=inst_id)
|
|
198
231
|
|
|
199
232
|
@overload
|
|
200
233
|
def futures_trades(
|
|
@@ -232,7 +265,9 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
232
265
|
Возвращает:
|
|
233
266
|
`Websocket`: Экземпляр вебсокета.
|
|
234
267
|
"""
|
|
235
|
-
|
|
268
|
+
inst_id = self._normalize_symbol(symbol, symbols)
|
|
269
|
+
wrapper = self._make_wrapper(self._adapter.trades_message, callback)
|
|
270
|
+
return self._websocket_manager.all_trades(callback=wrapper, inst_id=inst_id)
|
|
236
271
|
|
|
237
272
|
@overload
|
|
238
273
|
def futures_aggtrades(
|
|
@@ -270,4 +305,6 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
270
305
|
Возвращает:
|
|
271
306
|
`Websocket`: Экземпляр вебсокета.
|
|
272
307
|
"""
|
|
273
|
-
|
|
308
|
+
inst_id = self._normalize_symbol(symbol, symbols)
|
|
309
|
+
wrapper = self._make_wrapper(self._adapter.trades_message, callback)
|
|
310
|
+
return self._websocket_manager.trades(callback=wrapper, inst_id=inst_id)
|
unicex/types.py
CHANGED
|
@@ -79,10 +79,10 @@ class KlineDict(TypedDict):
|
|
|
79
79
|
q: float
|
|
80
80
|
"""Объем свечи. В долларах."""
|
|
81
81
|
|
|
82
|
-
T: int | None
|
|
82
|
+
T: int | None # `None` means untrackable
|
|
83
83
|
"""Время закрытия. В миллисекундах."""
|
|
84
84
|
|
|
85
|
-
x: bool | None
|
|
85
|
+
x: bool | None # `None` means untrackable
|
|
86
86
|
"""Флаг закрыта ли свеча."""
|
|
87
87
|
|
|
88
88
|
|
|
@@ -118,7 +118,10 @@ class OpenInterestItem(TypedDict):
|
|
|
118
118
|
"""Время. В миллисекундах."""
|
|
119
119
|
|
|
120
120
|
v: float
|
|
121
|
-
"""Открытый интерес.
|
|
121
|
+
"""Открытый интерес."""
|
|
122
|
+
|
|
123
|
+
u: Literal["coins", "usd"]
|
|
124
|
+
"""Единица измерения открытого интереса."""
|
|
122
125
|
|
|
123
126
|
|
|
124
127
|
type OpenInterestDict = dict[str, OpenInterestItem]
|
unicex/utils.py
CHANGED
|
@@ -10,6 +10,7 @@ __all__ = [
|
|
|
10
10
|
"catch_adapter_errors",
|
|
11
11
|
"decorate_all_methods",
|
|
12
12
|
"symbol_to_exchange_format",
|
|
13
|
+
"validate_single_symbol_args",
|
|
13
14
|
]
|
|
14
15
|
|
|
15
16
|
import base64
|
|
@@ -17,7 +18,7 @@ import hashlib
|
|
|
17
18
|
import hmac
|
|
18
19
|
import json
|
|
19
20
|
import time
|
|
20
|
-
from collections.abc import Callable, Iterable
|
|
21
|
+
from collections.abc import Callable, Iterable, Sequence
|
|
21
22
|
from functools import wraps
|
|
22
23
|
from typing import Any, Literal
|
|
23
24
|
from urllib.parse import urlencode
|
|
@@ -232,9 +233,29 @@ def symbol_to_exchange_format(
|
|
|
232
233
|
return symbol.removesuffix("USDT") # Вот тут мб и не так, там вроде что-то к USDC
|
|
233
234
|
elif exchange == Exchange.KUCOIN:
|
|
234
235
|
if market_type == MarketType.FUTURES:
|
|
236
|
+
if symbol_upper == "BTCUSDT":
|
|
237
|
+
return "XBTUSDTM"
|
|
235
238
|
return symbol_upper + "M"
|
|
236
239
|
else:
|
|
237
240
|
return symbol_upper.replace("USDT", "-USDT")
|
|
238
241
|
elif exchange == Exchange.BINGX:
|
|
239
242
|
return symbol_upper.replace("USDT", "-USDT")
|
|
240
243
|
return symbol_upper
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def validate_single_symbol_args(
|
|
247
|
+
symbol: str | None = None, symbols: Sequence[str] | None = None
|
|
248
|
+
) -> None:
|
|
249
|
+
"""Проверяет, что передан ровно один из аргументов symbol/symbols.
|
|
250
|
+
|
|
251
|
+
Параметры:
|
|
252
|
+
symbol (`str | None`, опционально): Одиночный торговый символ.
|
|
253
|
+
symbols (`Sequence[str] | None`, опционально): Список торговых символов.
|
|
254
|
+
|
|
255
|
+
Возвращает:
|
|
256
|
+
`None`: Ничего не возвращает, выбрасывает ValueError при нарушении условий.
|
|
257
|
+
"""
|
|
258
|
+
if symbol and symbols:
|
|
259
|
+
raise ValueError("Parameters symbol and symbols cannot be used together")
|
|
260
|
+
if not (symbol or symbols):
|
|
261
|
+
raise ValueError("Either symbol or symbols must be provided")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unicex
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Summary: Unified Crypto Exchange API
|
|
5
5
|
Author-email: LoveBloodAndDiamonds <ayazshakirzyanov27@gmail.com>
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -56,12 +56,12 @@ Dynamic: license-file
|
|
|
56
56
|
| Exchange | Client | Auth | WS Manager | User WS | Uni Client | Uni WS Manager | ExchangeInfo |
|
|
57
57
|
|-----------------|--------|------|------------|---------|------------|----------------|--------------|
|
|
58
58
|
| **Binance** | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
59
|
-
| **Bitget** | ✓ | ✓ | ✓ | | ✓ |
|
|
59
|
+
| **Bitget** | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ |
|
|
60
60
|
| **Bybit** | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ |
|
|
61
|
-
| **Gateio** | ✓ | ✓ | ✓ | | ✓ |
|
|
61
|
+
| **Gateio** | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ |
|
|
62
62
|
| **Hyperliquid** | ✓ | ✓ | ✓ | ✓ | ✓ | | |
|
|
63
|
-
| **Mexc** | ✓ | ✓ | ✓ | | ✓ |
|
|
64
|
-
| **Okx** | ✓ | ✓ | ✓ | | ✓ |
|
|
63
|
+
| **Mexc** | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ |
|
|
64
|
+
| **Okx** | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ |
|
|
65
65
|
| **Kucoin** | | | | | ✓ | | |
|
|
66
66
|
| **BingX** | | | | | ✓ | | |
|
|
67
67
|
---
|