unicex 0.16.7__py3-none-any.whl → 0.17.1__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 +5 -4
- unicex/aster/__init__.py +27 -0
- unicex/aster/adapter.py +173 -0
- unicex/aster/client.py +794 -0
- unicex/aster/exchange_info.py +44 -0
- unicex/aster/uni_client.py +184 -0
- unicex/aster/uni_websocket_manager.py +286 -0
- unicex/aster/user_websocket.py +191 -0
- unicex/aster/websocket_manager.py +403 -0
- unicex/binance/uni_client.py +2 -2
- unicex/enums.py +18 -0
- unicex/mapper.py +8 -0
- {unicex-0.16.7.dist-info → unicex-0.17.1.dist-info}/METADATA +2 -1
- {unicex-0.16.7.dist-info → unicex-0.17.1.dist-info}/RECORD +17 -9
- {unicex-0.16.7.dist-info → unicex-0.17.1.dist-info}/WHEEL +0 -0
- {unicex-0.16.7.dist-info → unicex-0.17.1.dist-info}/licenses/LICENSE +0 -0
- {unicex-0.16.7.dist-info → unicex-0.17.1.dist-info}/top_level.txt +0 -0
unicex/aster/client.py
ADDED
|
@@ -0,0 +1,794 @@
|
|
|
1
|
+
__all__ = ["Client"]
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import time
|
|
5
|
+
from typing import Any, Literal
|
|
6
|
+
|
|
7
|
+
from unicex._base import BaseClient
|
|
8
|
+
from unicex.exceptions import NotAuthorized
|
|
9
|
+
from unicex.types import NumberLike, RequestMethod
|
|
10
|
+
from unicex.utils import dict_to_query_string, filter_params, generate_hmac_sha256_signature
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Client(BaseClient):
|
|
14
|
+
"""Клиент для работы с Aster API."""
|
|
15
|
+
|
|
16
|
+
_BASE_FUTURES_URL: str = "https://fapi.asterdex.com"
|
|
17
|
+
"""Базовый URL для REST API Aster Futures."""
|
|
18
|
+
|
|
19
|
+
_RECV_WINDOW: int = 5000
|
|
20
|
+
"""Стандартный интервал времени для получения ответа от сервера."""
|
|
21
|
+
|
|
22
|
+
def _get_headers(self, method: RequestMethod) -> dict[str, str]:
|
|
23
|
+
"""Возвращает заголовки для запросов к Aster API."""
|
|
24
|
+
headers = {"Accept": "application/json"}
|
|
25
|
+
if self._api_key: # type: ignore[attr-defined]
|
|
26
|
+
headers["X-MBX-APIKEY"] = self._api_key # type: ignore[attr-defined]
|
|
27
|
+
if method in {"POST", "PUT", "DELETE"}:
|
|
28
|
+
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
|
29
|
+
return headers
|
|
30
|
+
|
|
31
|
+
def _prepare_payload(
|
|
32
|
+
self,
|
|
33
|
+
*,
|
|
34
|
+
method: RequestMethod,
|
|
35
|
+
signed: bool,
|
|
36
|
+
params: dict[str, Any] | None,
|
|
37
|
+
) -> tuple[dict[str, Any], dict[str, Any]]:
|
|
38
|
+
"""Подготавливает параметры запроса."""
|
|
39
|
+
params = filter_params(params) if params else {}
|
|
40
|
+
headers = self._get_headers(method)
|
|
41
|
+
|
|
42
|
+
if not signed:
|
|
43
|
+
return {"params": params}, headers
|
|
44
|
+
|
|
45
|
+
if not self.is_authorized():
|
|
46
|
+
raise NotAuthorized("Api key and api secret is required to private endpoints")
|
|
47
|
+
|
|
48
|
+
payload = {**params}
|
|
49
|
+
payload["timestamp"] = int(time.time() * 1000)
|
|
50
|
+
payload["recvWindow"] = self._RECV_WINDOW
|
|
51
|
+
|
|
52
|
+
# Подпись формируем по query string без параметра signature.
|
|
53
|
+
query_string = dict_to_query_string(payload)
|
|
54
|
+
payload["signature"] = generate_hmac_sha256_signature(
|
|
55
|
+
self._api_secret, # type: ignore[attr-defined]
|
|
56
|
+
query_string,
|
|
57
|
+
"hex",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return payload, headers
|
|
61
|
+
|
|
62
|
+
async def _make_request(
|
|
63
|
+
self,
|
|
64
|
+
method: RequestMethod,
|
|
65
|
+
url: str,
|
|
66
|
+
signed: bool = False,
|
|
67
|
+
*,
|
|
68
|
+
params: dict[str, Any] | None = None,
|
|
69
|
+
) -> Any:
|
|
70
|
+
"""Выполняет HTTP-запрос к эндпоинтам Aster API."""
|
|
71
|
+
payload, headers = self._prepare_payload(method=method, signed=signed, params=params)
|
|
72
|
+
|
|
73
|
+
if not signed:
|
|
74
|
+
return await super()._make_request(method=method, url=url, headers=headers, **payload)
|
|
75
|
+
|
|
76
|
+
return await super()._make_request(
|
|
77
|
+
method=method,
|
|
78
|
+
url=url,
|
|
79
|
+
params=payload,
|
|
80
|
+
headers=headers,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
async def request(
|
|
84
|
+
self, method: RequestMethod, url: str, params: dict, data: dict, signed: bool
|
|
85
|
+
) -> dict:
|
|
86
|
+
"""Выполняет запрос к произвольному endpoint Aster API.
|
|
87
|
+
|
|
88
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation
|
|
89
|
+
"""
|
|
90
|
+
return await self._make_request(method=method, url=url, params=params, signed=signed)
|
|
91
|
+
|
|
92
|
+
# topic: futures market data endpoints
|
|
93
|
+
|
|
94
|
+
async def futures_ping(self) -> dict:
|
|
95
|
+
"""Проверка подключения к REST API.
|
|
96
|
+
|
|
97
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#test-connectivity
|
|
98
|
+
"""
|
|
99
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/ping"
|
|
100
|
+
|
|
101
|
+
return await self._make_request("GET", url)
|
|
102
|
+
|
|
103
|
+
async def futures_server_time(self) -> dict:
|
|
104
|
+
"""Получение серверного времени.
|
|
105
|
+
|
|
106
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#check-server-time
|
|
107
|
+
"""
|
|
108
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/time"
|
|
109
|
+
|
|
110
|
+
return await self._make_request("GET", url)
|
|
111
|
+
|
|
112
|
+
async def futures_exchange_info(self) -> dict:
|
|
113
|
+
"""Получение информации о символах рынка и текущих правилах биржевой торговли.
|
|
114
|
+
|
|
115
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#exchange-information
|
|
116
|
+
"""
|
|
117
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/exchangeInfo"
|
|
118
|
+
|
|
119
|
+
return await self._make_request("GET", url)
|
|
120
|
+
|
|
121
|
+
async def futures_depth(self, symbol: str, limit: int | None = None) -> dict:
|
|
122
|
+
"""Получение книги ордеров.
|
|
123
|
+
|
|
124
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#order-book
|
|
125
|
+
"""
|
|
126
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/depth"
|
|
127
|
+
params = {"symbol": symbol, "limit": limit}
|
|
128
|
+
|
|
129
|
+
return await self._make_request("GET", url, params=params)
|
|
130
|
+
|
|
131
|
+
async def futures_trades(self, symbol: str, limit: int | None = None) -> list[dict]:
|
|
132
|
+
"""Получение последних сделок.
|
|
133
|
+
|
|
134
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#recent-trades-list
|
|
135
|
+
"""
|
|
136
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/trades"
|
|
137
|
+
params = {"symbol": symbol, "limit": limit}
|
|
138
|
+
|
|
139
|
+
return await self._make_request("GET", url, params=params)
|
|
140
|
+
|
|
141
|
+
async def futures_historical_trades(
|
|
142
|
+
self, symbol: str, limit: int | None = None, from_id: int | None = None
|
|
143
|
+
) -> list[dict]:
|
|
144
|
+
"""Получение исторических сделок.
|
|
145
|
+
|
|
146
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#old-trades-lookup-market_data
|
|
147
|
+
"""
|
|
148
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/historicalTrades"
|
|
149
|
+
params = {"symbol": symbol, "limit": limit, "fromId": from_id}
|
|
150
|
+
|
|
151
|
+
return await self._make_request("GET", url, params=params)
|
|
152
|
+
|
|
153
|
+
async def futures_agg_trades(
|
|
154
|
+
self,
|
|
155
|
+
symbol: str,
|
|
156
|
+
from_id: int | None = None,
|
|
157
|
+
start_time: int | None = None,
|
|
158
|
+
end_time: int | None = None,
|
|
159
|
+
limit: int | None = None,
|
|
160
|
+
) -> list[dict]:
|
|
161
|
+
"""Получение агрегированных сделок на фьючерсах.
|
|
162
|
+
|
|
163
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#compressed-aggregate-trades-list
|
|
164
|
+
"""
|
|
165
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/aggTrades"
|
|
166
|
+
params = {
|
|
167
|
+
"symbol": symbol,
|
|
168
|
+
"fromId": from_id,
|
|
169
|
+
"startTime": start_time,
|
|
170
|
+
"endTime": end_time,
|
|
171
|
+
"limit": limit,
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return await self._make_request("GET", url, params=params)
|
|
175
|
+
|
|
176
|
+
async def futures_klines(
|
|
177
|
+
self,
|
|
178
|
+
symbol: str,
|
|
179
|
+
interval: str,
|
|
180
|
+
start_time: int | None = None,
|
|
181
|
+
end_time: int | None = None,
|
|
182
|
+
limit: int | None = None,
|
|
183
|
+
) -> list[list]:
|
|
184
|
+
"""Получение исторических свечей.
|
|
185
|
+
|
|
186
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#kline-candlestick-data
|
|
187
|
+
"""
|
|
188
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/klines"
|
|
189
|
+
params = {
|
|
190
|
+
"symbol": symbol,
|
|
191
|
+
"interval": interval,
|
|
192
|
+
"startTime": start_time,
|
|
193
|
+
"endTime": end_time,
|
|
194
|
+
"limit": limit,
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return await self._make_request("GET", url, params=params)
|
|
198
|
+
|
|
199
|
+
async def futures_index_price_klines(
|
|
200
|
+
self,
|
|
201
|
+
pair: str,
|
|
202
|
+
interval: str,
|
|
203
|
+
start_time: int | None = None,
|
|
204
|
+
end_time: int | None = None,
|
|
205
|
+
limit: int | None = None,
|
|
206
|
+
) -> list[list]:
|
|
207
|
+
"""Получение свечей по индексу цены.
|
|
208
|
+
|
|
209
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#index-price-kline-candlestick-data
|
|
210
|
+
"""
|
|
211
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/indexPriceKlines"
|
|
212
|
+
params = {
|
|
213
|
+
"pair": pair,
|
|
214
|
+
"interval": interval,
|
|
215
|
+
"startTime": start_time,
|
|
216
|
+
"endTime": end_time,
|
|
217
|
+
"limit": limit,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return await self._make_request("GET", url, params=params)
|
|
221
|
+
|
|
222
|
+
async def futures_mark_price_klines(
|
|
223
|
+
self,
|
|
224
|
+
symbol: str,
|
|
225
|
+
interval: str,
|
|
226
|
+
start_time: int | None = None,
|
|
227
|
+
end_time: int | None = None,
|
|
228
|
+
limit: int | None = None,
|
|
229
|
+
) -> list[list]:
|
|
230
|
+
"""Получение свечей по марк-цене.
|
|
231
|
+
|
|
232
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#mark-price-kline-candlestick-data
|
|
233
|
+
"""
|
|
234
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/markPriceKlines"
|
|
235
|
+
params = {
|
|
236
|
+
"symbol": symbol,
|
|
237
|
+
"interval": interval,
|
|
238
|
+
"startTime": start_time,
|
|
239
|
+
"endTime": end_time,
|
|
240
|
+
"limit": limit,
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return await self._make_request("GET", url, params=params)
|
|
244
|
+
|
|
245
|
+
async def futures_mark_price(self, symbol: str | None = None) -> dict | list[dict]:
|
|
246
|
+
"""Получение ставки финансирования и цены маркировки.
|
|
247
|
+
|
|
248
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#mark-price
|
|
249
|
+
"""
|
|
250
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/premiumIndex"
|
|
251
|
+
params = {"symbol": symbol}
|
|
252
|
+
|
|
253
|
+
return await self._make_request("GET", url, params=params)
|
|
254
|
+
|
|
255
|
+
async def futures_funding_rate(
|
|
256
|
+
self,
|
|
257
|
+
symbol: str | None = None,
|
|
258
|
+
start_time: int | None = None,
|
|
259
|
+
end_time: int | None = None,
|
|
260
|
+
limit: int | None = None,
|
|
261
|
+
) -> list[dict]:
|
|
262
|
+
"""Получение истории ставок финансирования.
|
|
263
|
+
|
|
264
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#get-funding-rate-history
|
|
265
|
+
"""
|
|
266
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/fundingRate"
|
|
267
|
+
params = {
|
|
268
|
+
"symbol": symbol,
|
|
269
|
+
"startTime": start_time,
|
|
270
|
+
"endTime": end_time,
|
|
271
|
+
"limit": limit,
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return await self._make_request("GET", url, params=params)
|
|
275
|
+
|
|
276
|
+
async def futures_ticker_24hr(self, symbol: str | None = None) -> dict | list[dict]:
|
|
277
|
+
"""Получение статистики изменения цен и объема за 24 часа.
|
|
278
|
+
|
|
279
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#id-24hr-ticker-price-change-statistics
|
|
280
|
+
"""
|
|
281
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/ticker/24hr"
|
|
282
|
+
params = {"symbol": symbol}
|
|
283
|
+
|
|
284
|
+
return await self._make_request("GET", url, params=params)
|
|
285
|
+
|
|
286
|
+
async def futures_ticker_price(self, symbol: str | None = None) -> dict | list[dict]:
|
|
287
|
+
"""Получение последней цены тикера(ов).
|
|
288
|
+
|
|
289
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#symbol-price-ticker
|
|
290
|
+
"""
|
|
291
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/ticker/price"
|
|
292
|
+
params = {"symbol": symbol}
|
|
293
|
+
|
|
294
|
+
return await self._make_request("GET", url, params=params)
|
|
295
|
+
|
|
296
|
+
async def futures_ticker_book_ticker(self, symbol: str | None = None) -> dict | list[dict]:
|
|
297
|
+
"""Получение лучших цен bid/ask в книге ордеров.
|
|
298
|
+
|
|
299
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#symbol-order-book-ticker
|
|
300
|
+
"""
|
|
301
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/ticker/bookTicker"
|
|
302
|
+
params = {"symbol": symbol}
|
|
303
|
+
|
|
304
|
+
return await self._make_request("GET", url, params=params)
|
|
305
|
+
|
|
306
|
+
# topic: futures account/trade endpoints
|
|
307
|
+
|
|
308
|
+
async def futures_position_mode(self, dual_side_position: Literal["true", "false"]) -> dict:
|
|
309
|
+
"""Изменение режима позиции.
|
|
310
|
+
|
|
311
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#change-position-mode-trade
|
|
312
|
+
"""
|
|
313
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/positionSide/dual"
|
|
314
|
+
params = {"dualSidePosition": dual_side_position}
|
|
315
|
+
|
|
316
|
+
return await self._make_request("POST", url, True, params=params)
|
|
317
|
+
|
|
318
|
+
async def futures_position_mode_get(self) -> dict:
|
|
319
|
+
"""Получение текущего режима позиции.
|
|
320
|
+
|
|
321
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#get-current-position-mode-user_data
|
|
322
|
+
"""
|
|
323
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/positionSide/dual"
|
|
324
|
+
|
|
325
|
+
return await self._make_request("GET", url, True)
|
|
326
|
+
|
|
327
|
+
async def futures_multi_asset_mode(self, multi_assets_margin: Literal["true", "false"]) -> dict:
|
|
328
|
+
"""Изменение режима мультиактивной маржи.
|
|
329
|
+
|
|
330
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#change-multi-assets-mode-trade
|
|
331
|
+
"""
|
|
332
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/multiAssetsMargin"
|
|
333
|
+
params = {"multiAssetsMargin": multi_assets_margin}
|
|
334
|
+
|
|
335
|
+
return await self._make_request("POST", url, True, params=params)
|
|
336
|
+
|
|
337
|
+
async def futures_multi_asset_mode_get(self) -> dict:
|
|
338
|
+
"""Получение режима мультиактивной маржи.
|
|
339
|
+
|
|
340
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#get-current-multi-assets-mode-user_data
|
|
341
|
+
"""
|
|
342
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/multiAssetsMargin"
|
|
343
|
+
|
|
344
|
+
return await self._make_request("GET", url, True)
|
|
345
|
+
|
|
346
|
+
async def futures_order_create(
|
|
347
|
+
self,
|
|
348
|
+
symbol: str,
|
|
349
|
+
side: Literal["BUY", "SELL"],
|
|
350
|
+
type: Literal[
|
|
351
|
+
"LIMIT",
|
|
352
|
+
"MARKET",
|
|
353
|
+
"STOP",
|
|
354
|
+
"STOP_MARKET",
|
|
355
|
+
"TAKE_PROFIT",
|
|
356
|
+
"TAKE_PROFIT_MARKET",
|
|
357
|
+
"TRAILING_STOP_MARKET",
|
|
358
|
+
],
|
|
359
|
+
position_side: Literal["BOTH", "LONG", "SHORT"] | None = None,
|
|
360
|
+
time_in_force: str | None = None,
|
|
361
|
+
quantity: NumberLike | None = None,
|
|
362
|
+
reduce_only: Literal["true", "false"] | None = None,
|
|
363
|
+
price: NumberLike | None = None,
|
|
364
|
+
new_client_order_id: str | None = None,
|
|
365
|
+
stop_price: NumberLike | None = None,
|
|
366
|
+
close_position: Literal["true", "false"] | None = None,
|
|
367
|
+
activation_price: NumberLike | None = None,
|
|
368
|
+
callback_rate: NumberLike | None = None,
|
|
369
|
+
working_type: Literal["MARK_PRICE", "CONTRACT_PRICE"] | None = None,
|
|
370
|
+
price_protect: Literal["TRUE", "FALSE"] | None = None,
|
|
371
|
+
new_order_resp_type: str | None = None,
|
|
372
|
+
) -> dict:
|
|
373
|
+
"""Создание нового ордера на фьючерсах.
|
|
374
|
+
|
|
375
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#new-order-trade
|
|
376
|
+
"""
|
|
377
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/order"
|
|
378
|
+
params = {
|
|
379
|
+
"symbol": symbol,
|
|
380
|
+
"side": side,
|
|
381
|
+
"type": type,
|
|
382
|
+
"positionSide": position_side,
|
|
383
|
+
"timeInForce": time_in_force,
|
|
384
|
+
"quantity": quantity,
|
|
385
|
+
"reduceOnly": reduce_only,
|
|
386
|
+
"price": price,
|
|
387
|
+
"newClientOrderId": new_client_order_id,
|
|
388
|
+
"stopPrice": stop_price,
|
|
389
|
+
"closePosition": close_position,
|
|
390
|
+
"activationPrice": activation_price,
|
|
391
|
+
"callbackRate": callback_rate,
|
|
392
|
+
"workingType": working_type,
|
|
393
|
+
"priceProtect": price_protect,
|
|
394
|
+
"newOrderRespType": new_order_resp_type,
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return await self._make_request("POST", url, True, params=params)
|
|
398
|
+
|
|
399
|
+
async def futures_batch_orders_create(self, orders: list[dict]) -> list[dict]:
|
|
400
|
+
"""Создание множественных ордеров одновременно на фьючерсах.
|
|
401
|
+
|
|
402
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#place-multiple-orders-trade
|
|
403
|
+
"""
|
|
404
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/batchOrders"
|
|
405
|
+
params = {
|
|
406
|
+
"batchOrders": json.dumps(orders, separators=(",", ":")),
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return await self._make_request("POST", url, signed=True, params=params)
|
|
410
|
+
|
|
411
|
+
async def futures_order_get(
|
|
412
|
+
self,
|
|
413
|
+
symbol: str,
|
|
414
|
+
order_id: int | None = None,
|
|
415
|
+
orig_client_order_id: str | None = None,
|
|
416
|
+
) -> dict:
|
|
417
|
+
"""Получение информации об ордере на фьючерсах.
|
|
418
|
+
|
|
419
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#query-order-user_data
|
|
420
|
+
"""
|
|
421
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/order"
|
|
422
|
+
params = {
|
|
423
|
+
"symbol": symbol,
|
|
424
|
+
"orderId": order_id,
|
|
425
|
+
"origClientOrderId": orig_client_order_id,
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return await self._make_request("GET", url, True, params=params)
|
|
429
|
+
|
|
430
|
+
async def futures_order_cancel(
|
|
431
|
+
self, symbol: str, order_id: int | None = None, orig_client_order_id: str | None = None
|
|
432
|
+
) -> dict:
|
|
433
|
+
"""Отмена активного ордера на фьючерсном рынке.
|
|
434
|
+
|
|
435
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#cancel-order-trade
|
|
436
|
+
"""
|
|
437
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/order"
|
|
438
|
+
params = {
|
|
439
|
+
"symbol": symbol,
|
|
440
|
+
"orderId": order_id,
|
|
441
|
+
"origClientOrderId": orig_client_order_id,
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return await self._make_request("DELETE", url, True, params=params)
|
|
445
|
+
|
|
446
|
+
async def futures_orders_cancel_all(self, symbol: str) -> dict:
|
|
447
|
+
"""Отмена всех активных ордеров на фьючерсах.
|
|
448
|
+
|
|
449
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#cancel-all-open-orders-trade
|
|
450
|
+
"""
|
|
451
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/allOpenOrders"
|
|
452
|
+
params = {"symbol": symbol}
|
|
453
|
+
|
|
454
|
+
return await self._make_request("DELETE", url, True, params=params)
|
|
455
|
+
|
|
456
|
+
async def futures_batch_orders_cancel(
|
|
457
|
+
self,
|
|
458
|
+
symbol: str,
|
|
459
|
+
order_id_list: list[int] | None = None,
|
|
460
|
+
orig_client_order_id_list: list[str] | None = None,
|
|
461
|
+
) -> list[dict]:
|
|
462
|
+
"""Отмена множественных ордеров на фьючерсах.
|
|
463
|
+
|
|
464
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#cancel-multiple-orders-trade
|
|
465
|
+
"""
|
|
466
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/batchOrders"
|
|
467
|
+
params = {"symbol": symbol}
|
|
468
|
+
|
|
469
|
+
if order_id_list:
|
|
470
|
+
params["orderIdList"] = json.dumps(order_id_list, separators=(",", ":"))
|
|
471
|
+
|
|
472
|
+
if orig_client_order_id_list:
|
|
473
|
+
params["origClientOrderIdList"] = json.dumps(
|
|
474
|
+
orig_client_order_id_list, separators=(",", ":")
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
return await self._make_request("DELETE", url, signed=True, params=params)
|
|
478
|
+
|
|
479
|
+
async def futures_countdown_cancel_all(
|
|
480
|
+
self,
|
|
481
|
+
symbol: str,
|
|
482
|
+
countdown_time: int,
|
|
483
|
+
) -> dict:
|
|
484
|
+
"""Автоотмена всех активных ордеров через указанное время.
|
|
485
|
+
|
|
486
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#auto-cancel-all-open-orders-trade
|
|
487
|
+
"""
|
|
488
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/countdownCancelAll"
|
|
489
|
+
params = {
|
|
490
|
+
"symbol": symbol,
|
|
491
|
+
"countdownTime": countdown_time,
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return await self._make_request("POST", url, True, params=params)
|
|
495
|
+
|
|
496
|
+
async def futures_order_open(
|
|
497
|
+
self,
|
|
498
|
+
symbol: str,
|
|
499
|
+
order_id: int | None = None,
|
|
500
|
+
orig_client_order_id: str | None = None,
|
|
501
|
+
) -> dict:
|
|
502
|
+
"""Получение активного ордера.
|
|
503
|
+
|
|
504
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#query-current-open-order-user_data
|
|
505
|
+
"""
|
|
506
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/openOrder"
|
|
507
|
+
params = {
|
|
508
|
+
"symbol": symbol,
|
|
509
|
+
"orderId": order_id,
|
|
510
|
+
"origClientOrderId": orig_client_order_id,
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return await self._make_request("GET", url, True, params=params)
|
|
514
|
+
|
|
515
|
+
async def futures_orders_open(self, symbol: str | None = None) -> list[dict]:
|
|
516
|
+
"""Получение всех активных ордеров на фьючерсах.
|
|
517
|
+
|
|
518
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#current-all-open-orders-user_data
|
|
519
|
+
"""
|
|
520
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/openOrders"
|
|
521
|
+
params = {"symbol": symbol}
|
|
522
|
+
|
|
523
|
+
return await self._make_request("GET", url, True, params=params)
|
|
524
|
+
|
|
525
|
+
async def futures_orders_all(
|
|
526
|
+
self,
|
|
527
|
+
symbol: str,
|
|
528
|
+
order_id: int | None = None,
|
|
529
|
+
start_time: int | None = None,
|
|
530
|
+
end_time: int | None = None,
|
|
531
|
+
limit: int | None = None,
|
|
532
|
+
) -> list[dict]:
|
|
533
|
+
"""Получение всех ордеров на фьючерсах.
|
|
534
|
+
|
|
535
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#all-orders-user_data
|
|
536
|
+
"""
|
|
537
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/allOrders"
|
|
538
|
+
params = {
|
|
539
|
+
"symbol": symbol,
|
|
540
|
+
"orderId": order_id,
|
|
541
|
+
"startTime": start_time,
|
|
542
|
+
"endTime": end_time,
|
|
543
|
+
"limit": limit,
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return await self._make_request("GET", url, True, params=params)
|
|
547
|
+
|
|
548
|
+
async def futures_balance(self) -> list[dict]:
|
|
549
|
+
"""Получение баланса фьючерсного аккаунта.
|
|
550
|
+
|
|
551
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#futures-account-balance-v2-user_data
|
|
552
|
+
"""
|
|
553
|
+
url = self._BASE_FUTURES_URL + "/fapi/v2/balance"
|
|
554
|
+
|
|
555
|
+
return await self._make_request("GET", url, True)
|
|
556
|
+
|
|
557
|
+
async def futures_account(self) -> dict:
|
|
558
|
+
"""Получение информации об аккаунте фьючерсов.
|
|
559
|
+
|
|
560
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#account-information-v4-user_data
|
|
561
|
+
"""
|
|
562
|
+
url = self._BASE_FUTURES_URL + "/fapi/v4/account"
|
|
563
|
+
|
|
564
|
+
return await self._make_request("GET", url, True)
|
|
565
|
+
|
|
566
|
+
async def futures_leverage_change(self, symbol: str, leverage: int) -> dict:
|
|
567
|
+
"""Изменение кредитного плеча на фьючерсах.
|
|
568
|
+
|
|
569
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#change-initial-leverage-trade
|
|
570
|
+
"""
|
|
571
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/leverage"
|
|
572
|
+
params = {"symbol": symbol, "leverage": leverage}
|
|
573
|
+
|
|
574
|
+
return await self._make_request("POST", url, True, params=params)
|
|
575
|
+
|
|
576
|
+
async def futures_margin_type_change(self, symbol: str, margin_type: str) -> dict:
|
|
577
|
+
"""Изменение типа маржи на фьючерсах.
|
|
578
|
+
|
|
579
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#change-margin-type-trade
|
|
580
|
+
"""
|
|
581
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/marginType"
|
|
582
|
+
params = {"symbol": symbol, "marginType": margin_type}
|
|
583
|
+
|
|
584
|
+
return await self._make_request("POST", url, True, params=params)
|
|
585
|
+
|
|
586
|
+
async def futures_position_margin_modify(
|
|
587
|
+
self,
|
|
588
|
+
symbol: str,
|
|
589
|
+
position_side: str | None,
|
|
590
|
+
amount: NumberLike,
|
|
591
|
+
type: int,
|
|
592
|
+
) -> dict:
|
|
593
|
+
"""Изменение изолированной маржи позиции.
|
|
594
|
+
|
|
595
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#modify-isolated-position-margin-trade
|
|
596
|
+
"""
|
|
597
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/positionMargin"
|
|
598
|
+
params = {
|
|
599
|
+
"symbol": symbol,
|
|
600
|
+
"positionSide": position_side,
|
|
601
|
+
"amount": amount,
|
|
602
|
+
"type": type,
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return await self._make_request("POST", url, True, params=params)
|
|
606
|
+
|
|
607
|
+
async def futures_position_margin_history(
|
|
608
|
+
self,
|
|
609
|
+
symbol: str,
|
|
610
|
+
type: int | None = None,
|
|
611
|
+
start_time: int | None = None,
|
|
612
|
+
end_time: int | None = None,
|
|
613
|
+
limit: int | None = None,
|
|
614
|
+
) -> list[dict]:
|
|
615
|
+
"""Получение истории изменений маржи позиции.
|
|
616
|
+
|
|
617
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#get-position-margin-change-history-trade
|
|
618
|
+
"""
|
|
619
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/positionMargin/history"
|
|
620
|
+
params = {
|
|
621
|
+
"symbol": symbol,
|
|
622
|
+
"type": type,
|
|
623
|
+
"startTime": start_time,
|
|
624
|
+
"endTime": end_time,
|
|
625
|
+
"limit": limit,
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
return await self._make_request("GET", url, True, params=params)
|
|
629
|
+
|
|
630
|
+
async def futures_position_info(self, symbol: str | None = None) -> list[dict]:
|
|
631
|
+
"""Получение информации о позициях на фьючерсах.
|
|
632
|
+
|
|
633
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#position-information-v2-user_data
|
|
634
|
+
"""
|
|
635
|
+
url = self._BASE_FUTURES_URL + "/fapi/v2/positionRisk"
|
|
636
|
+
params = {"symbol": symbol}
|
|
637
|
+
|
|
638
|
+
return await self._make_request("GET", url, True, params=params)
|
|
639
|
+
|
|
640
|
+
async def futures_my_trades(
|
|
641
|
+
self,
|
|
642
|
+
symbol: str,
|
|
643
|
+
start_time: int | None = None,
|
|
644
|
+
end_time: int | None = None,
|
|
645
|
+
from_id: int | None = None,
|
|
646
|
+
limit: int | None = None,
|
|
647
|
+
) -> list[dict]:
|
|
648
|
+
"""Получение истории торгов на фьючерсах.
|
|
649
|
+
|
|
650
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#account-trade-list-user_data
|
|
651
|
+
"""
|
|
652
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/userTrades"
|
|
653
|
+
params = {
|
|
654
|
+
"symbol": symbol,
|
|
655
|
+
"startTime": start_time,
|
|
656
|
+
"endTime": end_time,
|
|
657
|
+
"fromId": from_id,
|
|
658
|
+
"limit": limit,
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
return await self._make_request("GET", url, True, params=params)
|
|
662
|
+
|
|
663
|
+
async def futures_income(
|
|
664
|
+
self,
|
|
665
|
+
symbol: str | None = None,
|
|
666
|
+
income_type: str | None = None,
|
|
667
|
+
start_time: int | None = None,
|
|
668
|
+
end_time: int | None = None,
|
|
669
|
+
limit: int | None = None,
|
|
670
|
+
) -> list[dict]:
|
|
671
|
+
"""Получение истории доходов на фьючерсах.
|
|
672
|
+
|
|
673
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#get-income-historyuser_data
|
|
674
|
+
"""
|
|
675
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/income"
|
|
676
|
+
params = {
|
|
677
|
+
"symbol": symbol,
|
|
678
|
+
"incomeType": income_type,
|
|
679
|
+
"startTime": start_time,
|
|
680
|
+
"endTime": end_time,
|
|
681
|
+
"limit": limit,
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
return await self._make_request("GET", url, True, params=params)
|
|
685
|
+
|
|
686
|
+
async def futures_leverage_brackets(self, symbol: str | None = None) -> dict | list[dict]:
|
|
687
|
+
"""Получение лимитов по плечу и нотионалу.
|
|
688
|
+
|
|
689
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#notional-and-leverage-brackets-user_data
|
|
690
|
+
"""
|
|
691
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/leverageBracket"
|
|
692
|
+
params = {"symbol": symbol}
|
|
693
|
+
|
|
694
|
+
return await self._make_request("GET", url, True, params=params)
|
|
695
|
+
|
|
696
|
+
async def futures_adl_quantile(self, symbol: str | None = None) -> list[dict]:
|
|
697
|
+
"""Получение информации об автоматической ликвидации.
|
|
698
|
+
|
|
699
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#position-adl-quantile-estimation-user_data
|
|
700
|
+
"""
|
|
701
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/adlQuantile"
|
|
702
|
+
params = {"symbol": symbol}
|
|
703
|
+
|
|
704
|
+
return await self._make_request("GET", url, True, params=params)
|
|
705
|
+
|
|
706
|
+
async def futures_force_orders(
|
|
707
|
+
self,
|
|
708
|
+
symbol: str | None = None,
|
|
709
|
+
auto_close_type: str | None = None,
|
|
710
|
+
start_time: int | None = None,
|
|
711
|
+
end_time: int | None = None,
|
|
712
|
+
limit: int | None = None,
|
|
713
|
+
) -> list[dict]:
|
|
714
|
+
"""Получение истории принудительных ордеров пользователя.
|
|
715
|
+
|
|
716
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#users-force-orders-user_data
|
|
717
|
+
"""
|
|
718
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/forceOrders"
|
|
719
|
+
params = {
|
|
720
|
+
"symbol": symbol,
|
|
721
|
+
"autoCloseType": auto_close_type,
|
|
722
|
+
"startTime": start_time,
|
|
723
|
+
"endTime": end_time,
|
|
724
|
+
"limit": limit,
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
return await self._make_request("GET", url, True, params=params)
|
|
728
|
+
|
|
729
|
+
async def futures_commission_rate(self, symbol: str) -> dict:
|
|
730
|
+
"""Получение комиссионных ставок на фьючерсах.
|
|
731
|
+
|
|
732
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#user-commission-rate-user_data
|
|
733
|
+
"""
|
|
734
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/commissionRate"
|
|
735
|
+
params = {"symbol": symbol}
|
|
736
|
+
|
|
737
|
+
return await self._make_request("GET", url, True, params=params)
|
|
738
|
+
|
|
739
|
+
# topic: futures user data streams
|
|
740
|
+
|
|
741
|
+
async def futures_listen_key(self) -> dict:
|
|
742
|
+
"""Создание ключа прослушивания для подключения к пользовательскому вебсокету.
|
|
743
|
+
|
|
744
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#start-user-data-stream-user_stream
|
|
745
|
+
"""
|
|
746
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/listenKey"
|
|
747
|
+
|
|
748
|
+
return await super()._make_request("POST", url, headers=self._get_headers("POST"))
|
|
749
|
+
|
|
750
|
+
async def futures_renew_listen_key(self) -> dict:
|
|
751
|
+
"""Обновление ключа прослушивания для подключения к пользовательскому вебсокету.
|
|
752
|
+
|
|
753
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#keepalive-user-data-stream-user_stream
|
|
754
|
+
"""
|
|
755
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/listenKey"
|
|
756
|
+
|
|
757
|
+
return await super()._make_request("PUT", url, headers=self._get_headers("PUT"))
|
|
758
|
+
|
|
759
|
+
async def futures_close_listen_key(self) -> dict:
|
|
760
|
+
"""Закрытие ключа прослушивания для подключения к пользовательскому вебсокету.
|
|
761
|
+
|
|
762
|
+
https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation#close-user-data-stream-user_stream
|
|
763
|
+
"""
|
|
764
|
+
url = self._BASE_FUTURES_URL + "/fapi/v1/listenKey"
|
|
765
|
+
|
|
766
|
+
return await super()._make_request("DELETE", url, headers=self._get_headers("DELETE"))
|
|
767
|
+
|
|
768
|
+
async def open_interest(self) -> dict:
|
|
769
|
+
"""Секретный эндпоинт откопанный в недрах фронтенда asterdex.com разработчиком @RushanWork.
|
|
770
|
+
|
|
771
|
+
Формат возвращаемых данных:
|
|
772
|
+
```python
|
|
773
|
+
{'code': '000000',
|
|
774
|
+
'message': None,
|
|
775
|
+
'messageDetail': None,
|
|
776
|
+
'data': [
|
|
777
|
+
{
|
|
778
|
+
'symbol': 'TRUTHUSDT',
|
|
779
|
+
'baseAsset': 'TRUTH',
|
|
780
|
+
'quoteAsset': 'USDT',
|
|
781
|
+
'lastPrice': 0.0126301,
|
|
782
|
+
'highPrice': 0.0138825,
|
|
783
|
+
'lowPrice': 0.012459,
|
|
784
|
+
'baseVolume': 2011775,
|
|
785
|
+
'quoteVolume': 26613.48,
|
|
786
|
+
'openInterest': 85333.69964392 // В USDT
|
|
787
|
+
}, ...
|
|
788
|
+
]
|
|
789
|
+
]
|
|
790
|
+
```
|
|
791
|
+
"""
|
|
792
|
+
url = "https://www.asterdex.com/bapi/future/v1/public/future/aster/ticker/pair"
|
|
793
|
+
|
|
794
|
+
return await super()._make_request("GET", url, headers=self._get_headers("GET"))
|