unicex 0.13.17__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.
Files changed (93) hide show
  1. unicex/__init__.py +200 -0
  2. unicex/_abc/__init__.py +11 -0
  3. unicex/_abc/exchange_info.py +216 -0
  4. unicex/_abc/uni_client.py +329 -0
  5. unicex/_abc/uni_websocket_manager.py +294 -0
  6. unicex/_base/__init__.py +9 -0
  7. unicex/_base/client.py +214 -0
  8. unicex/_base/websocket.py +261 -0
  9. unicex/binance/__init__.py +27 -0
  10. unicex/binance/adapter.py +202 -0
  11. unicex/binance/client.py +1577 -0
  12. unicex/binance/exchange_info.py +62 -0
  13. unicex/binance/uni_client.py +188 -0
  14. unicex/binance/uni_websocket_manager.py +166 -0
  15. unicex/binance/user_websocket.py +186 -0
  16. unicex/binance/websocket_manager.py +912 -0
  17. unicex/bitget/__init__.py +27 -0
  18. unicex/bitget/adapter.py +188 -0
  19. unicex/bitget/client.py +2514 -0
  20. unicex/bitget/exchange_info.py +48 -0
  21. unicex/bitget/uni_client.py +198 -0
  22. unicex/bitget/uni_websocket_manager.py +275 -0
  23. unicex/bitget/user_websocket.py +7 -0
  24. unicex/bitget/websocket_manager.py +232 -0
  25. unicex/bybit/__init__.py +27 -0
  26. unicex/bybit/adapter.py +208 -0
  27. unicex/bybit/client.py +1876 -0
  28. unicex/bybit/exchange_info.py +53 -0
  29. unicex/bybit/uni_client.py +200 -0
  30. unicex/bybit/uni_websocket_manager.py +291 -0
  31. unicex/bybit/user_websocket.py +7 -0
  32. unicex/bybit/websocket_manager.py +339 -0
  33. unicex/enums.py +273 -0
  34. unicex/exceptions.py +64 -0
  35. unicex/extra.py +335 -0
  36. unicex/gate/__init__.py +27 -0
  37. unicex/gate/adapter.py +178 -0
  38. unicex/gate/client.py +1667 -0
  39. unicex/gate/exchange_info.py +55 -0
  40. unicex/gate/uni_client.py +214 -0
  41. unicex/gate/uni_websocket_manager.py +269 -0
  42. unicex/gate/user_websocket.py +7 -0
  43. unicex/gate/websocket_manager.py +513 -0
  44. unicex/hyperliquid/__init__.py +27 -0
  45. unicex/hyperliquid/adapter.py +261 -0
  46. unicex/hyperliquid/client.py +2315 -0
  47. unicex/hyperliquid/exchange_info.py +119 -0
  48. unicex/hyperliquid/uni_client.py +325 -0
  49. unicex/hyperliquid/uni_websocket_manager.py +269 -0
  50. unicex/hyperliquid/user_websocket.py +7 -0
  51. unicex/hyperliquid/websocket_manager.py +393 -0
  52. unicex/mapper.py +111 -0
  53. unicex/mexc/__init__.py +27 -0
  54. unicex/mexc/_spot_ws_proto/PrivateAccountV3Api_pb2.py +38 -0
  55. unicex/mexc/_spot_ws_proto/PrivateDealsV3Api_pb2.py +38 -0
  56. unicex/mexc/_spot_ws_proto/PrivateOrdersV3Api_pb2.py +38 -0
  57. unicex/mexc/_spot_ws_proto/PublicAggreBookTickerV3Api_pb2.py +38 -0
  58. unicex/mexc/_spot_ws_proto/PublicAggreDealsV3Api_pb2.py +40 -0
  59. unicex/mexc/_spot_ws_proto/PublicAggreDepthsV3Api_pb2.py +40 -0
  60. unicex/mexc/_spot_ws_proto/PublicBookTickerBatchV3Api_pb2.py +38 -0
  61. unicex/mexc/_spot_ws_proto/PublicBookTickerV3Api_pb2.py +38 -0
  62. unicex/mexc/_spot_ws_proto/PublicDealsV3Api_pb2.py +40 -0
  63. unicex/mexc/_spot_ws_proto/PublicFuture_pb2.py +103 -0
  64. unicex/mexc/_spot_ws_proto/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  65. unicex/mexc/_spot_ws_proto/PublicIncreaseDepthsV3Api_pb2.py +40 -0
  66. unicex/mexc/_spot_ws_proto/PublicLimitDepthsV3Api_pb2.py +40 -0
  67. unicex/mexc/_spot_ws_proto/PublicMiniTickerV3Api_pb2.py +38 -0
  68. unicex/mexc/_spot_ws_proto/PublicMiniTickersV3Api_pb2.py +38 -0
  69. unicex/mexc/_spot_ws_proto/PublicSpotKlineV3Api_pb2.py +38 -0
  70. unicex/mexc/_spot_ws_proto/PushDataV3ApiWrapper_pb2.py +38 -0
  71. unicex/mexc/_spot_ws_proto/__init__.py +335 -0
  72. unicex/mexc/adapter.py +239 -0
  73. unicex/mexc/client.py +846 -0
  74. unicex/mexc/exchange_info.py +47 -0
  75. unicex/mexc/uni_client.py +211 -0
  76. unicex/mexc/uni_websocket_manager.py +269 -0
  77. unicex/mexc/user_websocket.py +7 -0
  78. unicex/mexc/websocket_manager.py +456 -0
  79. unicex/okx/__init__.py +27 -0
  80. unicex/okx/adapter.py +150 -0
  81. unicex/okx/client.py +2864 -0
  82. unicex/okx/exchange_info.py +47 -0
  83. unicex/okx/uni_client.py +202 -0
  84. unicex/okx/uni_websocket_manager.py +269 -0
  85. unicex/okx/user_websocket.py +7 -0
  86. unicex/okx/websocket_manager.py +743 -0
  87. unicex/types.py +164 -0
  88. unicex/utils.py +218 -0
  89. unicex-0.13.17.dist-info/METADATA +243 -0
  90. unicex-0.13.17.dist-info/RECORD +93 -0
  91. unicex-0.13.17.dist-info/WHEEL +5 -0
  92. unicex-0.13.17.dist-info/licenses/LICENSE +28 -0
  93. unicex-0.13.17.dist-info/top_level.txt +1 -0
@@ -0,0 +1,232 @@
1
+ __all__ = ["WebsocketManager"]
2
+
3
+
4
+ import json
5
+ from collections.abc import Awaitable, Callable, Sequence
6
+ from typing import Any, Literal
7
+
8
+ from unicex._base import Websocket
9
+
10
+ from .client import Client
11
+
12
+ type CallbackType = Callable[[Any], Awaitable[None]]
13
+
14
+
15
+ class WebsocketManager:
16
+ """Менеджер асинхронных вебсокетов для Bitget."""
17
+
18
+ _URL: str = "wss://ws.bitget.com/v2/ws/public"
19
+ """Базовый URL для вебсокета."""
20
+
21
+ def __init__(self, client: Client | None = None, **ws_kwargs: Any) -> None:
22
+ """Инициализирует менеджер вебсокетов для Bitget.
23
+
24
+ Параметры:
25
+ client (`Client | None`): Клиент для выполнения запросов. Нужен, чтобы открыть приватные вебсокеты.
26
+ ws_kwargs (`dict[str, Any]`): Дополнительные аргументы, котоыре прокидываются в `Websocket`.
27
+ """
28
+ self.client = client
29
+ self._ws_kwargs = {"ping_message": "ping", **ws_kwargs}
30
+
31
+ def _generate_subscription_message(
32
+ self,
33
+ topic: str,
34
+ market_type: Literal["SPOT", "USDT-FUTURES"],
35
+ symbol: str | None = None,
36
+ symbols: Sequence[str] | None = None,
37
+ ) -> list[str]:
38
+ """Сформировать сообщение для подписки на вебсокет.
39
+
40
+ Параметры:
41
+ topic (`str`): Канал подписки (например: "ticker", "candle1m", "depth").
42
+ market_type (`"SPOT" | "USDT-FUTURES"`): Тип рынка для подписки.
43
+ symbol (`str | None`): Торговая пара. Нельзя использовать одновременно с `symbols`.
44
+ symbols (`Sequence[str] | None`): Список торговых пар. Нельзя использовать одновременно с `symbol`.
45
+
46
+ Возвращает:
47
+ `str`: JSON-строка с сообщением для подписки на вебсокет.
48
+ """
49
+ if symbol and symbols:
50
+ raise ValueError("Parameters symbol and symbols cannot be used together")
51
+ if not (symbol or symbols):
52
+ raise ValueError("Either symbol or symbols must be provided")
53
+
54
+ tickers = [symbol] if symbol else symbols
55
+ streams: list[dict] = [
56
+ {
57
+ "instType": market_type,
58
+ "channel": topic,
59
+ "instId": ticker.upper(),
60
+ }
61
+ for ticker in tickers # type: ignore
62
+ ]
63
+
64
+ return [json.dumps({"op": "subscribe", "args": streams})]
65
+
66
+ def trade(
67
+ self,
68
+ callback: CallbackType,
69
+ market_type: Literal["SPOT", "USDT-FUTURES"],
70
+ symbol: str | None = None,
71
+ symbols: Sequence[str] | None = None,
72
+ ) -> Websocket:
73
+ """Создает вебсокет для получения сделок.
74
+
75
+ https://www.bitget.com/api-doc/spot/websocket/public/Trades-Channel
76
+
77
+ Параметры:
78
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
79
+ market_type (`Literal["SPOT", "USDT-FUTURES"]`): Тип рынка.
80
+ symbol (`str | None`): Один символ для подписки.
81
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
82
+
83
+ Возвращает:
84
+ `Websocket`: Объект для управления вебсокет соединением.
85
+ """
86
+ subsription_messages = self._generate_subscription_message(
87
+ topic="trade",
88
+ market_type=market_type,
89
+ symbol=symbol,
90
+ symbols=symbols,
91
+ )
92
+ return Websocket(
93
+ callback=callback,
94
+ url=self._URL,
95
+ subscription_messages=subsription_messages,
96
+ **self._ws_kwargs,
97
+ )
98
+
99
+ def ticker(
100
+ self,
101
+ callback: CallbackType,
102
+ market_type: Literal["SPOT", "USDT-FUTURES"],
103
+ symbol: str | None = None,
104
+ symbols: Sequence[str] | None = None,
105
+ ) -> Websocket:
106
+ """Создает вебсокет для получения тикеров.
107
+
108
+ https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
109
+
110
+ Параметры:
111
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
112
+ market_type (`Literal["SPOT", "USDT-FUTURES"]`): Тип рынка.
113
+ symbol (`str | None`): Один символ для подписки.
114
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
115
+
116
+ Возвращает:
117
+ `Websocket`: Объект для управления вебсокет соединением.
118
+ """
119
+ subscription_messages = self._generate_subscription_message(
120
+ topic="ticker",
121
+ market_type=market_type,
122
+ symbol=symbol,
123
+ symbols=symbols,
124
+ )
125
+ return Websocket(
126
+ callback=callback,
127
+ url=self._URL,
128
+ subscription_messages=subscription_messages,
129
+ **self._ws_kwargs,
130
+ )
131
+
132
+ def candlestick(
133
+ self,
134
+ callback: CallbackType,
135
+ market_type: Literal["SPOT", "USDT-FUTURES"],
136
+ interval: str,
137
+ symbol: str | None = None,
138
+ symbols: Sequence[str] | None = None,
139
+ ) -> Websocket:
140
+ """Создает вебсокет для получения данных свечей (candlestick).
141
+
142
+ https://www.bitget.com/api-doc/spot/websocket/public/Candlesticks-Channel
143
+
144
+ Параметры:
145
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
146
+ market_type (`Literal["SPOT", "USDT-FUTURES"]`): Тип рынка.
147
+ interval (`str`): Интервал свечи, например "1m", "1H", "1Dutc".
148
+ symbol (`str | None`): Один символ для подписки.
149
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
150
+
151
+ Возвращает:
152
+ `Websocket`: Объект для управления вебсокет соединением.
153
+ """
154
+ topic = f"candle{interval}"
155
+ subscription_messages = self._generate_subscription_message(
156
+ topic=topic,
157
+ market_type=market_type,
158
+ symbol=symbol,
159
+ symbols=symbols,
160
+ )
161
+ return Websocket(
162
+ callback=callback,
163
+ url=self._URL,
164
+ subscription_messages=subscription_messages,
165
+ **self._ws_kwargs,
166
+ )
167
+
168
+ def depth(
169
+ self,
170
+ callback: CallbackType,
171
+ market_type: Literal["SPOT", "USDT-FUTURES"],
172
+ depth_type: str = "books",
173
+ symbol: str | None = None,
174
+ symbols: Sequence[str] | None = None,
175
+ ) -> Websocket:
176
+ """Создает вебсокет для получения данных глубины рынка (order book).
177
+
178
+ https://www.bitget.com/api-doc/spot/websocket/public/Depth-Channel
179
+
180
+ Параметры:
181
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
182
+ market_type (`Literal["SPOT", "USDT-FUTURES"]`): Тип рынка.
183
+ depth_type (`str`): Тип глубины: "books", "books1", "books5", "books15".
184
+ symbol (`str | None`): Один символ для подписки.
185
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
186
+
187
+ Возвращает:
188
+ `Websocket`: Объект для управления вебсокет соединением.
189
+ """
190
+ subscription_messages = self._generate_subscription_message(
191
+ topic=depth_type,
192
+ market_type=market_type,
193
+ symbol=symbol,
194
+ symbols=symbols,
195
+ )
196
+ return Websocket(
197
+ callback=callback,
198
+ url=self._URL,
199
+ subscription_messages=subscription_messages,
200
+ **self._ws_kwargs,
201
+ )
202
+
203
+ def auction(
204
+ self,
205
+ callback: CallbackType,
206
+ symbol: str | None = None,
207
+ symbols: Sequence[str] | None = None,
208
+ ) -> Websocket:
209
+ """Создает вебсокет для получения информации о Call Auction.
210
+
211
+ https://www.bitget.com/api-doc/spot/websocket/public/Auction-Channel
212
+
213
+ Параметры:
214
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
215
+ symbol (`str | None`): Один символ для подписки.
216
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
217
+
218
+ Возвращает:
219
+ `Websocket`: Объект для управления вебсокет соединением.
220
+ """
221
+ subscription_messages = self._generate_subscription_message(
222
+ topic="auction",
223
+ market_type="SPOT",
224
+ symbol=symbol,
225
+ symbols=symbols,
226
+ )
227
+ return Websocket(
228
+ callback=callback,
229
+ url=self._URL,
230
+ subscription_messages=subscription_messages,
231
+ **self._ws_kwargs,
232
+ )
@@ -0,0 +1,27 @@
1
+ """Пакет, содержащий реализации клиентов и менеджеров для работы с биржей Bybit."""
2
+
3
+ __all__ = [
4
+ "Client",
5
+ "UniClient",
6
+ "UserWebsocket",
7
+ "WebsocketManager",
8
+ "UniWebsocketManager",
9
+ "ExchangeInfo",
10
+ ]
11
+
12
+ from .client import Client
13
+ from .exchange_info import ExchangeInfo
14
+ from .uni_client import UniClient
15
+ from .uni_websocket_manager import UniWebsocketManager
16
+ from .user_websocket import UserWebsocket
17
+ from .websocket_manager import WebsocketManager
18
+
19
+
20
+ async def load_exchange_info() -> None:
21
+ """Загружает информацию о бирже Bybit."""
22
+ await ExchangeInfo.load_exchange_info()
23
+
24
+
25
+ async def start_exchange_info(parse_interval_seconds: int = 60 * 60) -> None:
26
+ """Запускает процесс обновления информации о бирже Bybit."""
27
+ await ExchangeInfo.start(parse_interval_seconds)
@@ -0,0 +1,208 @@
1
+ __all__ = ["Adapter"]
2
+
3
+ from typing import Any
4
+
5
+ from unicex.types import (
6
+ KlineDict,
7
+ LiquidationDict,
8
+ OpenInterestDict,
9
+ OpenInterestItem,
10
+ TickerDailyDict,
11
+ TickerDailyItem,
12
+ TradeDict,
13
+ )
14
+ from unicex.utils import catch_adapter_errors, decorate_all_methods
15
+
16
+
17
+ @decorate_all_methods(catch_adapter_errors)
18
+ class Adapter:
19
+ """Адаптер для унификации данных с Bybit API."""
20
+
21
+ @staticmethod
22
+ def tickers(raw_data: dict, only_usdt: bool) -> list[str]:
23
+ """Преобразует сырой ответ, в котором содержатся данные о тикерах в список тикеров.
24
+
25
+ Параметры:
26
+ raw_data (dict): Сырой ответ с биржи.
27
+ only_usdt (bool): Флаг, указывающий, нужно ли включать только тикеры в паре к USDT.
28
+
29
+ Возвращает:
30
+ list[str]: Список тикеров.
31
+ """
32
+ return [
33
+ item["symbol"]
34
+ for item in raw_data["result"]["list"]
35
+ if item["symbol"].endswith("USDT") or not only_usdt
36
+ ]
37
+
38
+ @staticmethod
39
+ def ticker_24hr(raw_data: dict) -> TickerDailyDict:
40
+ """Преобразует сырой ответ, в котором содержатся данные о тикере за последние 24 часа в унифицированный формат.
41
+
42
+ Параметры:
43
+ raw_data (dict): Сырой ответ с биржи.
44
+
45
+ Возвращает:
46
+ TickerDailyDict: Словарь, где ключ - тикер, а значение - статистика за последние 24 часа.
47
+ """
48
+ return {
49
+ item["symbol"]: TickerDailyItem(
50
+ p=round(float(item["price24hPcnt"]) * 100, 2),
51
+ v=float(item["volume24h"]),
52
+ q=float(item["turnover24h"]),
53
+ )
54
+ for item in raw_data["result"]["list"]
55
+ }
56
+
57
+ @staticmethod
58
+ def open_interest(raw_data: dict) -> OpenInterestDict:
59
+ """Преобразует сырой ответ, в котором содержатся данные об открытом интересе, в унифицированный формат.
60
+
61
+ Параметры:
62
+ raw_data (dict): Сырой ответ с биржи.
63
+
64
+ Возвращает:
65
+ OpenInterestDict: Словарь, где ключ - тикер, а значение - агрегированные данные открытого интереса.
66
+ """
67
+ return {
68
+ item["symbol"]: OpenInterestItem(
69
+ t=raw_data["time"],
70
+ v=float(item["openInterest"]),
71
+ )
72
+ for item in raw_data["result"]["list"]
73
+ }
74
+
75
+ @staticmethod
76
+ def funding_rate(raw_data: dict) -> dict[str, float]:
77
+ """Преобразует сырой ответ, в котором содержатся данные о ставках финансирования, в унифицированный формат.
78
+
79
+ Параметры:
80
+ raw_data (dict): Сырой ответ с биржи.
81
+
82
+ Возвращает:
83
+ dict[str, float]: Словарь, где ключ - тикер, а значение - ставка финансирования.
84
+ """
85
+ return {
86
+ item["symbol"]: float(item["fundingRate"]) * 100
87
+ for item in raw_data["result"]["list"]
88
+ if item["fundingRate"]
89
+ }
90
+
91
+ @staticmethod
92
+ def last_price(raw_data: dict) -> dict[str, float]:
93
+ """Преобразует сырой ответ, в котором содержатся данные о последней цене, в унифицированный формат.
94
+
95
+ Параметры:
96
+ raw_data (dict): Сырой ответ с биржи.
97
+
98
+ Возвращает:
99
+ dict[str, float]: Словарь, где ключ - тикер, а значение - последняя цена.
100
+ """
101
+ return {item["symbol"]: float(item["lastPrice"]) for item in raw_data["result"]["list"]}
102
+
103
+ @staticmethod
104
+ def klines(raw_data: dict) -> list[KlineDict]:
105
+ """Преобразует сырой ответ, в котором содержатся данные о свечах, в унифицированный формат.
106
+
107
+ Параметры:
108
+ raw_data (dict): Сырой ответ с биржи.
109
+
110
+ Возвращает:
111
+ list[KlineDict]: Список словарей, где каждый словарь содержит данные о свече.
112
+ """
113
+ return [
114
+ KlineDict(
115
+ s=raw_data["result"]["symbol"],
116
+ t=int(kline[0]),
117
+ o=float(kline[1]),
118
+ h=float(kline[2]),
119
+ l=float(kline[3]),
120
+ c=float(kline[4]),
121
+ v=float(kline[5]),
122
+ q=float(kline[6]),
123
+ T=None,
124
+ x=None,
125
+ )
126
+ for kline in sorted(
127
+ raw_data["result"]["list"],
128
+ key=lambda x: int(x[0]),
129
+ )
130
+ ]
131
+
132
+ @staticmethod
133
+ def Klines_message(raw_msg: Any) -> list[KlineDict]:
134
+ """Преобразует вебсокет-сообщение с данными о свечах в унифицированный формат.
135
+
136
+ Параметры:
137
+ raw_msg (`Any`): Сырое сообщение из вебсокета Bybit.
138
+
139
+ Возвращает:
140
+ `list[KlineDict]`: Список свечей в унифицированном формате.
141
+ """
142
+ symbol = raw_msg["topic"].split(".")[-1]
143
+ return [
144
+ KlineDict(
145
+ s=symbol,
146
+ t=kline["start"],
147
+ o=float(kline["open"]),
148
+ h=float(kline["high"]),
149
+ l=float(kline["low"]),
150
+ c=float(kline["close"]),
151
+ v=float(kline["volume"]),
152
+ q=float(kline["turnover"]),
153
+ T=kline["end"],
154
+ x=kline["confirm"],
155
+ )
156
+ for kline in sorted(
157
+ raw_msg["data"],
158
+ key=lambda x: int(x["start"]),
159
+ )
160
+ ]
161
+
162
+ @staticmethod
163
+ def trades_message(raw_msg: Any) -> list[TradeDict]:
164
+ """Преобразует вебсокет-сообщение с данными о сделках в унифицированный формат.
165
+
166
+ Параметры:
167
+ raw_msg (`Any`): Сырое сообщение из вебсокета Bybit.
168
+
169
+ Возвращает:
170
+ `list[TradeDict]`: Список сделок в унифицированном формате.
171
+ """
172
+ return [
173
+ TradeDict(
174
+ t=trade["T"],
175
+ s=trade["s"],
176
+ S=trade["S"].upper(),
177
+ p=float(trade["p"]),
178
+ v=float(trade["v"]),
179
+ )
180
+ for trade in sorted(
181
+ raw_msg["data"],
182
+ key=lambda x: int(x["T"]),
183
+ )
184
+ ]
185
+
186
+ @staticmethod
187
+ def liquidations_message(raw_msg: Any) -> list[LiquidationDict]:
188
+ """Преобразует вебсокет-сообщение с данными о ликвидациях в унифицированный формат.
189
+
190
+ Параметры:
191
+ raw_msg (`Any`): Сырое сообщение из вебсокета Bybit.
192
+
193
+ Возвращает:
194
+ `list[LiquidationDict]`: Список ликвидаций в унифицированном формате.
195
+ """
196
+ return [
197
+ LiquidationDict(
198
+ t=liquidation["T"],
199
+ s=liquidation["s"],
200
+ S=liquidation["S"].upper(),
201
+ v=float(liquidation["v"]),
202
+ p=float(liquidation["p"]),
203
+ )
204
+ for liquidation in sorted(
205
+ raw_msg["data"],
206
+ key=lambda x: int(x["T"]),
207
+ )
208
+ ]