unicex 0.13.17__py3-none-any.whl → 0.16.5__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/__init__.py +36 -2
- unicex/_abc/exchange_info.py +1 -1
- unicex/_abc/uni_client.py +31 -1
- unicex/_abc/uni_websocket_manager.py +1 -1
- unicex/_base/client.py +7 -0
- unicex/_base/websocket.py +31 -9
- unicex/binance/adapter.py +7 -16
- unicex/binance/client.py +25 -25
- unicex/binance/uni_websocket_manager.py +6 -2
- unicex/bingx/__init__.py +27 -0
- unicex/bingx/adapter.py +284 -0
- unicex/bingx/client.py +521 -0
- unicex/bingx/exchange_info.py +22 -0
- unicex/bingx/uni_client.py +191 -0
- unicex/bingx/uni_websocket_manager.py +283 -0
- unicex/bingx/user_websocket.py +7 -0
- unicex/bingx/websocket_manager.py +118 -0
- unicex/bitget/adapter.py +2 -2
- unicex/bitget/client.py +64 -64
- unicex/bitget/uni_websocket_manager.py +27 -6
- unicex/bitget/websocket_manager.py +2 -4
- unicex/bybit/adapter.py +1 -0
- unicex/bybit/client.py +4 -4
- unicex/bybit/exchange_info.py +1 -1
- unicex/bybit/uni_websocket_manager.py +33 -4
- unicex/bybit/websocket_manager.py +8 -24
- unicex/enums.py +19 -3
- unicex/extra.py +37 -35
- unicex/gate/adapter.py +113 -0
- unicex/gate/client.py +9 -9
- unicex/gate/uni_client.py +1 -3
- unicex/gate/uni_websocket_manager.py +47 -9
- unicex/hyperliquid/adapter.py +1 -0
- unicex/hyperliquid/client.py +12 -12
- unicex/hyperliquid/uni_client.py +4 -7
- unicex/hyperliquid/uni_websocket_manager.py +6 -2
- unicex/kucoin/__init__.py +27 -0
- unicex/kucoin/adapter.py +181 -0
- unicex/kucoin/client.py +135 -0
- unicex/kucoin/exchange_info.py +50 -0
- unicex/kucoin/uni_client.py +208 -0
- unicex/kucoin/uni_websocket_manager.py +273 -0
- unicex/kucoin/user_websocket.py +7 -0
- unicex/kucoin/websocket_manager.py +11 -0
- unicex/mapper.py +62 -21
- unicex/mexc/adapter.py +104 -0
- unicex/mexc/client.py +7 -7
- unicex/mexc/uni_client.py +1 -3
- unicex/mexc/uni_websocket_manager.py +31 -9
- unicex/mexc/websocket_manager.py +27 -6
- unicex/okx/adapter.py +51 -0
- unicex/okx/client.py +15 -15
- unicex/okx/exchange_info.py +2 -2
- unicex/okx/uni_websocket_manager.py +50 -9
- unicex/okx/websocket_manager.py +119 -166
- unicex/types.py +14 -10
- unicex/utils.py +44 -1
- {unicex-0.13.17.dist-info → unicex-0.16.5.dist-info}/METADATA +7 -5
- unicex-0.16.5.dist-info/RECORD +109 -0
- unicex-0.13.17.dist-info/RECORD +0 -93
- {unicex-0.13.17.dist-info → unicex-0.16.5.dist-info}/WHEEL +0 -0
- {unicex-0.13.17.dist-info → unicex-0.16.5.dist-info}/licenses/LICENSE +0 -0
- {unicex-0.13.17.dist-info → unicex-0.16.5.dist-info}/top_level.txt +0 -0
unicex/__init__.py
CHANGED
|
@@ -18,7 +18,6 @@ __all__ = [
|
|
|
18
18
|
"TickerDailyItem",
|
|
19
19
|
"KlineDict",
|
|
20
20
|
"TradeDict",
|
|
21
|
-
"AggTradeDict",
|
|
22
21
|
"RequestMethod",
|
|
23
22
|
"LoggerLike",
|
|
24
23
|
"OpenInterestDict",
|
|
@@ -81,6 +80,20 @@ __all__ = [
|
|
|
81
80
|
"GateioWebsocketManager",
|
|
82
81
|
"GateioUserWebsocket",
|
|
83
82
|
"GateioExchangeInfo",
|
|
83
|
+
# Kucoin
|
|
84
|
+
"KucoinClient",
|
|
85
|
+
"KucoinUniClient",
|
|
86
|
+
"KucoinUniWebsocketManager",
|
|
87
|
+
"KucoinWebsocketManager",
|
|
88
|
+
"KucoinUserWebsocket",
|
|
89
|
+
"KucoinExchangeInfo",
|
|
90
|
+
# BingX
|
|
91
|
+
"BingXClient",
|
|
92
|
+
"BingXUniClient",
|
|
93
|
+
"BingXUniWebsocketManager",
|
|
94
|
+
"BingXWebsocketManager",
|
|
95
|
+
"BingXUserWebsocket",
|
|
96
|
+
"BingXExchangeInfo",
|
|
84
97
|
]
|
|
85
98
|
|
|
86
99
|
# ruff: noqa
|
|
@@ -98,7 +111,6 @@ from .types import (
|
|
|
98
111
|
TickerDailyItem,
|
|
99
112
|
KlineDict,
|
|
100
113
|
TradeDict,
|
|
101
|
-
AggTradeDict,
|
|
102
114
|
RequestMethod,
|
|
103
115
|
LoggerLike,
|
|
104
116
|
OpenInterestDict,
|
|
@@ -173,6 +185,24 @@ from .okx import (
|
|
|
173
185
|
ExchangeInfo as OkxExchangeInfo,
|
|
174
186
|
)
|
|
175
187
|
|
|
188
|
+
from .kucoin import (
|
|
189
|
+
Client as KucoinClient,
|
|
190
|
+
UniClient as KucoinUniClient,
|
|
191
|
+
UniWebsocketManager as KucoinUniWebsocketManager,
|
|
192
|
+
UserWebsocket as KucoinUserWebsocket,
|
|
193
|
+
WebsocketManager as KucoinWebsocketManager,
|
|
194
|
+
ExchangeInfo as KucoinExchangeInfo,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
from .bingx import (
|
|
198
|
+
Client as BingXClient,
|
|
199
|
+
UniClient as BingXUniClient,
|
|
200
|
+
UniWebsocketManager as BingXUniWebsocketManager,
|
|
201
|
+
UserWebsocket as BingXUserWebsocket,
|
|
202
|
+
WebsocketManager as BingXWebsocketManager,
|
|
203
|
+
ExchangeInfo as BingXExchangeInfo,
|
|
204
|
+
)
|
|
205
|
+
|
|
176
206
|
|
|
177
207
|
async def load_exchanges_info() -> None:
|
|
178
208
|
"""Единожды загружает информацию о тикерах на всех биржах."""
|
|
@@ -184,6 +214,8 @@ async def load_exchanges_info() -> None:
|
|
|
184
214
|
HyperliquidExchangeInfo.load_exchange_info(),
|
|
185
215
|
MexcExchangeInfo.load_exchange_info(),
|
|
186
216
|
OkxExchangeInfo.load_exchange_info(),
|
|
217
|
+
KucoinExchangeInfo.load_exchange_info(),
|
|
218
|
+
BingXExchangeInfo.load_exchange_info(),
|
|
187
219
|
)
|
|
188
220
|
|
|
189
221
|
|
|
@@ -197,4 +229,6 @@ async def start_exchanges_info(parse_interval_seconds: int = 60 * 60) -> None:
|
|
|
197
229
|
HyperliquidExchangeInfo.start(parse_interval_seconds),
|
|
198
230
|
MexcExchangeInfo.start(parse_interval_seconds),
|
|
199
231
|
OkxExchangeInfo.start(parse_interval_seconds),
|
|
232
|
+
KucoinExchangeInfo.start(parse_interval_seconds),
|
|
233
|
+
BingXExchangeInfo.start(parse_interval_seconds),
|
|
200
234
|
)
|
unicex/_abc/exchange_info.py
CHANGED
|
@@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class IExchangeInfo(ABC):
|
|
20
|
-
"""Интерфейс
|
|
20
|
+
"""Интерфейс класса, который обновляет информацию о правилах торговли на бирже."""
|
|
21
21
|
|
|
22
22
|
_loaded: bool
|
|
23
23
|
"""Флаг, указывающий, была ли информация о бирже загружена."""
|
unicex/_abc/uni_client.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
__all__ = ["IUniClient"]
|
|
2
2
|
|
|
3
|
+
import time
|
|
3
4
|
from abc import ABC, abstractmethod
|
|
4
5
|
from typing import Generic, Self, TypeVar, overload
|
|
5
6
|
|
|
@@ -14,7 +15,7 @@ TClient = TypeVar("TClient", bound="BaseClient")
|
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class IUniClient(ABC, Generic[TClient]):
|
|
17
|
-
"""Интерфейс для
|
|
18
|
+
"""Интерфейс для унифицированного клиента."""
|
|
18
19
|
|
|
19
20
|
def __init__(
|
|
20
21
|
self,
|
|
@@ -175,6 +176,35 @@ class IUniClient(ABC, Generic[TClient]):
|
|
|
175
176
|
tickers = await self.tickers(only_usdt)
|
|
176
177
|
return batched_list(tickers, batch_size)
|
|
177
178
|
|
|
179
|
+
@staticmethod
|
|
180
|
+
def limit_to_start_and_end_time(
|
|
181
|
+
interval: Timeframe, limit: int, use_milliseconds: bool = True
|
|
182
|
+
) -> tuple[int, int]:
|
|
183
|
+
"""Преобразует `limit` в `start_time` и `end_time`.
|
|
184
|
+
|
|
185
|
+
Параметры:
|
|
186
|
+
interval (`Timeframe`): Интервал времени.
|
|
187
|
+
limit (`int`): Количество элементов.
|
|
188
|
+
use_milliseconds (`bool`): Использовать миллисекунды.
|
|
189
|
+
|
|
190
|
+
Нужен, потому что на некоторых биржах параметр `limit` не принимается напрямую.
|
|
191
|
+
"""
|
|
192
|
+
end_time = int(time.time())
|
|
193
|
+
start_time = end_time - (limit * interval.to_seconds) # type: ignore[reportOptionalOperand]
|
|
194
|
+
if use_milliseconds:
|
|
195
|
+
start_time *= 1000
|
|
196
|
+
end_time *= 1000
|
|
197
|
+
return start_time, end_time
|
|
198
|
+
|
|
199
|
+
@staticmethod
|
|
200
|
+
def to_seconds(value: int | None) -> int | None:
|
|
201
|
+
"""Преобразует значение из миллисекунд в секунды для передачи в API."""
|
|
202
|
+
if value is None:
|
|
203
|
+
return None
|
|
204
|
+
if value >= 1_000_000_000_000:
|
|
205
|
+
return value // 1000
|
|
206
|
+
return value
|
|
207
|
+
|
|
178
208
|
@abstractmethod
|
|
179
209
|
async def futures_tickers(self, only_usdt: bool = True) -> list[str]:
|
|
180
210
|
"""Возвращает список тикеров.
|
|
@@ -16,7 +16,7 @@ type CallbackType = Callable[[Any], Awaitable[None]]
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class IUniWebsocketManager(ABC):
|
|
19
|
-
"""Интерфейс менеджера
|
|
19
|
+
"""Интерфейс менеджера унифицированных вебсокетов."""
|
|
20
20
|
|
|
21
21
|
def __init__(
|
|
22
22
|
self, client: BaseClient | IUniClient | None = None, logger: LoggerLike | None = None
|
unicex/_base/client.py
CHANGED
|
@@ -203,6 +203,9 @@ class BaseClient:
|
|
|
203
203
|
response_json=response_json,
|
|
204
204
|
) from None
|
|
205
205
|
|
|
206
|
+
# Валидирование ответа в конерктной реализации клиента
|
|
207
|
+
self._validate_response(response_json)
|
|
208
|
+
|
|
206
209
|
# Логирование ответа
|
|
207
210
|
try:
|
|
208
211
|
self._logger.debug(
|
|
@@ -212,3 +215,7 @@ class BaseClient:
|
|
|
212
215
|
self._logger.error(f"Error while logging response: {e}")
|
|
213
216
|
|
|
214
217
|
return response_json
|
|
218
|
+
|
|
219
|
+
def _validate_response(self, response_json: dict[str, Any]) -> None:
|
|
220
|
+
"""Проверка ответа API на ошибки биржи. Переопределяется в клиентах конкретных бирж."""
|
|
221
|
+
return None
|
unicex/_base/websocket.py
CHANGED
|
@@ -3,7 +3,7 @@ __all__ = ["Websocket"]
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import time
|
|
5
5
|
from collections.abc import Awaitable, Callable
|
|
6
|
-
from typing import Any, Protocol
|
|
6
|
+
from typing import Any, Literal, Protocol
|
|
7
7
|
|
|
8
8
|
import orjson
|
|
9
9
|
import websockets
|
|
@@ -23,12 +23,12 @@ class Websocket:
|
|
|
23
23
|
class _DecoderProtocol(Protocol):
|
|
24
24
|
"""Протокол декодирования сообщений."""
|
|
25
25
|
|
|
26
|
-
def decode(self, message: Any) -> dict: ...
|
|
26
|
+
def decode(self, message: Any) -> dict | Literal["ping"]: ...
|
|
27
27
|
|
|
28
28
|
class _JsonDecoder:
|
|
29
29
|
"""Протокол декодирования сообщений в формате JSON."""
|
|
30
30
|
|
|
31
|
-
def decode(self, message: Any) -> dict:
|
|
31
|
+
def decode(self, message: Any) -> dict | Literal["ping"]:
|
|
32
32
|
return orjson.loads(message)
|
|
33
33
|
|
|
34
34
|
def __init__(
|
|
@@ -103,6 +103,11 @@ class Websocket:
|
|
|
103
103
|
await asyncio.sleep(self._reconnect_timeout)
|
|
104
104
|
await self.start()
|
|
105
105
|
|
|
106
|
+
@property
|
|
107
|
+
def running(self) -> bool:
|
|
108
|
+
"""Возвращает статус вебсокета."""
|
|
109
|
+
return self._running
|
|
110
|
+
|
|
106
111
|
async def _connect(self) -> None:
|
|
107
112
|
"""Подключается к вебсокету и настраивает соединение."""
|
|
108
113
|
self._logger.debug(f"Establishing connection with {self._url}")
|
|
@@ -114,7 +119,7 @@ class Websocket:
|
|
|
114
119
|
# Цикл получения сообщений
|
|
115
120
|
while self._running:
|
|
116
121
|
message = await conn.recv()
|
|
117
|
-
await self._handle_message(message)
|
|
122
|
+
await self._handle_message(message, conn)
|
|
118
123
|
|
|
119
124
|
except websockets.exceptions.ConnectionClosed as e:
|
|
120
125
|
self._logger.error(f"Websocket connection was closed unexpectedly: {e}")
|
|
@@ -128,7 +133,7 @@ class Websocket:
|
|
|
128
133
|
else:
|
|
129
134
|
return # Выходим из итератора, если вебсокет уже выключен
|
|
130
135
|
|
|
131
|
-
async def _handle_message(self, message: str | bytes) -> None:
|
|
136
|
+
async def _handle_message(self, message: str | bytes, conn: ClientConnection) -> None:
|
|
132
137
|
"""Обрабатывает входящее сообщение вебсокета."""
|
|
133
138
|
try:
|
|
134
139
|
# Обновленяем время последнего сообщения
|
|
@@ -136,17 +141,22 @@ class Websocket:
|
|
|
136
141
|
|
|
137
142
|
# Ложим сообщение в очередь, предварительно его сериализуя
|
|
138
143
|
decoded_message = self._decoder.decode(message)
|
|
139
|
-
await self._queue.put(decoded_message)
|
|
140
144
|
|
|
141
|
-
# Проверяем
|
|
142
|
-
|
|
145
|
+
# Проверяем - вдруг декордер вернул "ping"
|
|
146
|
+
if decoded_message == "ping":
|
|
147
|
+
await self._send_pong(conn)
|
|
148
|
+
else:
|
|
149
|
+
await self._queue.put(decoded_message)
|
|
150
|
+
|
|
151
|
+
# Проверяем размер очереди сообщений и выбрасываем ошибку, если он превышает максимальный размер
|
|
152
|
+
self._check_queue_size()
|
|
143
153
|
except QueueOverflowError:
|
|
144
154
|
self._logger.error("Message queue is overflow")
|
|
145
155
|
except orjson.JSONDecodeError as e:
|
|
146
156
|
if message in ["ping", "pong"]:
|
|
147
157
|
self._logger.debug(f"Received ping message: {message}")
|
|
148
158
|
else:
|
|
149
|
-
self._logger.error(f"Failed to decode
|
|
159
|
+
self._logger.error(f"Failed to decode message: {message}, error: {e}")
|
|
150
160
|
except Exception as e:
|
|
151
161
|
self._logger.error(f"Unexpected error: {e}")
|
|
152
162
|
|
|
@@ -256,6 +266,18 @@ class Websocket:
|
|
|
256
266
|
return
|
|
257
267
|
await asyncio.sleep(1)
|
|
258
268
|
|
|
269
|
+
async def _send_pong(self, conn: ClientConnection) -> None:
|
|
270
|
+
"""Отправляет pong сообщение."""
|
|
271
|
+
if self._pong_message:
|
|
272
|
+
if isinstance(self._pong_message, Callable):
|
|
273
|
+
pong_message = self._pong_message()
|
|
274
|
+
else:
|
|
275
|
+
pong_message = self._pong_message
|
|
276
|
+
await conn.send(pong_message)
|
|
277
|
+
else:
|
|
278
|
+
await conn.pong()
|
|
279
|
+
self._logger.debug("Sent pong message")
|
|
280
|
+
|
|
259
281
|
def __repr__(self) -> str:
|
|
260
282
|
"""Репрезентация вебсокета."""
|
|
261
283
|
return f"<Websocket(url={self._url[:15]}...)>"
|
unicex/binance/adapter.py
CHANGED
|
@@ -2,7 +2,6 @@ __all__ = ["Adapter"]
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
from unicex.types import (
|
|
5
|
-
AggTradeDict,
|
|
6
5
|
KlineDict,
|
|
7
6
|
OpenInterestItem,
|
|
8
7
|
TickerDailyDict,
|
|
@@ -62,18 +61,6 @@ class Adapter:
|
|
|
62
61
|
"""
|
|
63
62
|
return {item["symbol"]: float(item["price"]) for item in raw_data}
|
|
64
63
|
|
|
65
|
-
@staticmethod
|
|
66
|
-
def futures_last_price(raw_data: list[dict]) -> dict[str, float]:
|
|
67
|
-
"""Преобразует сырой ответ, в котором содержатся данные о тикере за последние 24 часа в унифицированный формат.
|
|
68
|
-
|
|
69
|
-
Параметры:
|
|
70
|
-
raw_data (list[dict]): Сырой ответ с биржи.
|
|
71
|
-
|
|
72
|
-
Возвращает:
|
|
73
|
-
dict[str, float]: Словарь, где ключ - тикер, а значение - последняя цена.
|
|
74
|
-
"""
|
|
75
|
-
return Adapter.last_price(raw_data)
|
|
76
|
-
|
|
77
64
|
@staticmethod
|
|
78
65
|
def klines(raw_data: list[list], symbol: str) -> list[KlineDict]:
|
|
79
66
|
"""Преобразует сырой ответ, в котором содержатся данные о котировках тикеров в унифицированный формат.
|
|
@@ -127,7 +114,11 @@ class Adapter:
|
|
|
127
114
|
Возвращает:
|
|
128
115
|
OpenInterestItem: Словарь со временем и объемом открытого интереса в монетах.
|
|
129
116
|
"""
|
|
130
|
-
return OpenInterestItem(
|
|
117
|
+
return OpenInterestItem(
|
|
118
|
+
t=raw_data["time"],
|
|
119
|
+
v=float(raw_data["openInterest"]),
|
|
120
|
+
u="coins",
|
|
121
|
+
)
|
|
131
122
|
|
|
132
123
|
@staticmethod
|
|
133
124
|
def klines_message(raw_msg: dict) -> list[KlineDict]:
|
|
@@ -158,7 +149,7 @@ class Adapter:
|
|
|
158
149
|
]
|
|
159
150
|
|
|
160
151
|
@staticmethod
|
|
161
|
-
def aggtrades_message(raw_msg: dict) -> list[
|
|
152
|
+
def aggtrades_message(raw_msg: dict) -> list[TradeDict]:
|
|
162
153
|
"""Преобразует сырое сообщение с вебсокета, в котором содержится информация о
|
|
163
154
|
аггрегированных сделке/сделках в унифицированный вид.
|
|
164
155
|
|
|
@@ -170,7 +161,7 @@ class Adapter:
|
|
|
170
161
|
"""
|
|
171
162
|
msg = raw_msg.get("data", raw_msg)
|
|
172
163
|
return [
|
|
173
|
-
|
|
164
|
+
TradeDict(
|
|
174
165
|
t=int(msg["T"]),
|
|
175
166
|
s=str(msg["s"]),
|
|
176
167
|
S="SELL" if bool(msg["m"]) else "BUY",
|
unicex/binance/client.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
from unicex._base import BaseClient
|
|
9
9
|
from unicex.exceptions import NotAuthorized
|
|
10
|
-
from unicex.types import RequestMethod
|
|
10
|
+
from unicex.types import NumberLike, RequestMethod
|
|
11
11
|
from unicex.utils import dict_to_query_string, filter_params, generate_hmac_sha256_signature
|
|
12
12
|
|
|
13
13
|
|
|
@@ -367,13 +367,13 @@ class Client(BaseClient):
|
|
|
367
367
|
symbol: str,
|
|
368
368
|
side: str,
|
|
369
369
|
type: str,
|
|
370
|
-
quantity:
|
|
371
|
-
quote_order_qty:
|
|
372
|
-
price:
|
|
373
|
-
stop_price:
|
|
370
|
+
quantity: NumberLike | None = None,
|
|
371
|
+
quote_order_qty: NumberLike | None = None,
|
|
372
|
+
price: NumberLike | None = None,
|
|
373
|
+
stop_price: NumberLike | None = None,
|
|
374
374
|
time_in_force: str | None = None,
|
|
375
375
|
new_client_order_id: str | None = None,
|
|
376
|
-
iceberg_qty:
|
|
376
|
+
iceberg_qty: NumberLike | None = None,
|
|
377
377
|
new_order_resp_type: str | None = None,
|
|
378
378
|
self_trade_prevention_mode: str | None = None,
|
|
379
379
|
) -> dict:
|
|
@@ -405,13 +405,13 @@ class Client(BaseClient):
|
|
|
405
405
|
symbol: str,
|
|
406
406
|
side: str,
|
|
407
407
|
type: str,
|
|
408
|
-
quantity:
|
|
409
|
-
quote_order_qty:
|
|
410
|
-
price:
|
|
411
|
-
stop_price:
|
|
408
|
+
quantity: NumberLike | None = None,
|
|
409
|
+
quote_order_qty: NumberLike | None = None,
|
|
410
|
+
price: NumberLike | None = None,
|
|
411
|
+
stop_price: NumberLike | None = None,
|
|
412
412
|
time_in_force: str | None = None,
|
|
413
413
|
new_client_order_id: str | None = None,
|
|
414
|
-
iceberg_qty:
|
|
414
|
+
iceberg_qty: NumberLike | None = None,
|
|
415
415
|
new_order_resp_type: str | None = None,
|
|
416
416
|
self_trade_prevention_mode: str | None = None,
|
|
417
417
|
) -> dict:
|
|
@@ -482,26 +482,26 @@ class Client(BaseClient):
|
|
|
482
482
|
self,
|
|
483
483
|
symbol: str,
|
|
484
484
|
side: str,
|
|
485
|
-
quantity:
|
|
485
|
+
quantity: NumberLike,
|
|
486
486
|
list_client_order_id: str | None = None,
|
|
487
487
|
# ABOVE ORDER
|
|
488
488
|
above_type: str = "TAKE_PROFIT_LIMIT",
|
|
489
489
|
above_client_order_id: str | None = None,
|
|
490
|
-
above_price:
|
|
491
|
-
above_stop_price:
|
|
490
|
+
above_price: NumberLike | None = None,
|
|
491
|
+
above_stop_price: NumberLike | None = None,
|
|
492
492
|
above_trailing_delta: int | None = None,
|
|
493
493
|
above_time_in_force: str | None = None,
|
|
494
|
-
above_iceberg_qty:
|
|
494
|
+
above_iceberg_qty: NumberLike | None = None,
|
|
495
495
|
above_strategy_id: int | None = None,
|
|
496
496
|
above_strategy_type: int | None = None,
|
|
497
497
|
# BELOW ORDER
|
|
498
498
|
below_type: str = "STOP_LOSS_LIMIT",
|
|
499
499
|
below_client_order_id: str | None = None,
|
|
500
|
-
below_price:
|
|
501
|
-
below_stop_price:
|
|
500
|
+
below_price: NumberLike | None = None,
|
|
501
|
+
below_stop_price: NumberLike | None = None,
|
|
502
502
|
below_trailing_delta: int | None = None,
|
|
503
503
|
below_time_in_force: str | None = None,
|
|
504
|
-
below_iceberg_qty:
|
|
504
|
+
below_iceberg_qty: NumberLike | None = None,
|
|
505
505
|
below_strategy_id: int | None = None,
|
|
506
506
|
below_strategy_type: int | None = None,
|
|
507
507
|
# EXTRA
|
|
@@ -1126,13 +1126,13 @@ class Client(BaseClient):
|
|
|
1126
1126
|
symbol: str,
|
|
1127
1127
|
side: str,
|
|
1128
1128
|
type: str,
|
|
1129
|
-
quantity:
|
|
1129
|
+
quantity: NumberLike | None = None,
|
|
1130
1130
|
reduce_only: bool | None = None,
|
|
1131
|
-
price:
|
|
1131
|
+
price: NumberLike | None = None,
|
|
1132
1132
|
new_client_order_id: str | None = None,
|
|
1133
|
-
stop_price:
|
|
1133
|
+
stop_price: NumberLike | None = None,
|
|
1134
1134
|
close_position: bool | None = None,
|
|
1135
|
-
activation_price:
|
|
1135
|
+
activation_price: NumberLike | None = None,
|
|
1136
1136
|
callback_rate: float | None = None,
|
|
1137
1137
|
time_in_force: str | None = None,
|
|
1138
1138
|
working_type: str | None = None,
|
|
@@ -1176,8 +1176,8 @@ class Client(BaseClient):
|
|
|
1176
1176
|
orig_client_order_id: str | None = None,
|
|
1177
1177
|
symbol: str | None = None,
|
|
1178
1178
|
side: str | None = None,
|
|
1179
|
-
quantity:
|
|
1180
|
-
price:
|
|
1179
|
+
quantity: NumberLike | None = None,
|
|
1180
|
+
price: NumberLike | None = None,
|
|
1181
1181
|
price_match: str | None = None,
|
|
1182
1182
|
) -> dict:
|
|
1183
1183
|
"""Изменение ордера на фьючерсах.
|
|
@@ -1356,7 +1356,7 @@ class Client(BaseClient):
|
|
|
1356
1356
|
self,
|
|
1357
1357
|
symbol: str,
|
|
1358
1358
|
position_side: str,
|
|
1359
|
-
amount:
|
|
1359
|
+
amount: NumberLike,
|
|
1360
1360
|
type: int,
|
|
1361
1361
|
) -> dict:
|
|
1362
1362
|
"""Изменение изолированной маржи позиции.
|
|
@@ -20,16 +20,20 @@ class UniWebsocketManager(IUniWebsocketManager):
|
|
|
20
20
|
"""Реализация менеджера асинхронных унифицированных вебсокетов для биржи Binance."""
|
|
21
21
|
|
|
22
22
|
def __init__(
|
|
23
|
-
self,
|
|
23
|
+
self,
|
|
24
|
+
client: Client | UniClient | None = None,
|
|
25
|
+
logger: LoggerLike | None = None,
|
|
26
|
+
**ws_kwargs: Any,
|
|
24
27
|
) -> None:
|
|
25
28
|
"""Инициализирует унифицированный менеджер вебсокетов.
|
|
26
29
|
|
|
27
30
|
Параметры:
|
|
28
31
|
client (`Client | UniClient | None`): Клиент Binance или унифицированный клиент. Нужен для подключения к приватным топикам.
|
|
29
32
|
logger (`LoggerLike | None`): Логгер для записи логов.
|
|
33
|
+
ws_kwargs (`dict[str, Any]`): Дополнительные параметры инициализации, которые будут переданы WebsocketManager/Websocket.
|
|
30
34
|
"""
|
|
31
35
|
super().__init__(client=client, logger=logger)
|
|
32
|
-
self._websocket_manager = WebsocketManager(self._client) # type: ignore
|
|
36
|
+
self._websocket_manager = WebsocketManager(self._client, **ws_kwargs) # type: ignore
|
|
33
37
|
self._adapter = Adapter()
|
|
34
38
|
|
|
35
39
|
def klines(
|
unicex/bingx/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Пакет, содержащий реализации клиентов и менеджеров для работы с биржей BingX."""
|
|
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
|
+
"""Загружает информацию о бирже BingX."""
|
|
22
|
+
await ExchangeInfo.load_exchange_info()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def start_exchange_info(parse_interval_seconds: int = 60 * 60) -> None:
|
|
26
|
+
"""Запускает процесс обновления информации о бирже BingX."""
|
|
27
|
+
await ExchangeInfo.start(parse_interval_seconds)
|