unicex 0.4.0__py3-none-any.whl → 0.7.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/__init__.py +56 -124
- unicex/_abc/__init__.py +2 -0
- unicex/_abc/exchange_info.py +176 -0
- unicex/_abc/uni_client.py +2 -2
- unicex/_base/client.py +2 -2
- unicex/binance/__init__.py +12 -0
- unicex/binance/adapter.py +1 -1
- unicex/binance/exchange_info.py +12 -0
- unicex/bitget/__init__.py +14 -4
- unicex/bitget/adapter.py +1 -1
- unicex/bitget/exchange_info.py +12 -0
- unicex/bitget/uni_websocket_manager.py +1 -1
- unicex/bybit/__init__.py +12 -0
- unicex/bybit/adapter.py +1 -1
- unicex/bybit/exchange_info.py +12 -0
- unicex/enums.py +16 -5
- unicex/extra.py +49 -0
- unicex/gateio/__init__.py +12 -0
- unicex/gateio/adapter.py +2 -2
- unicex/gateio/exchange_info.py +12 -0
- unicex/hyperliquid/__init__.py +12 -0
- unicex/hyperliquid/adapter.py +140 -30
- unicex/hyperliquid/client.py +2208 -125
- unicex/hyperliquid/exchange_info.py +100 -0
- unicex/hyperliquid/uni_client.py +176 -22
- unicex/mapper.py +35 -33
- unicex/mexc/__init__.py +12 -0
- unicex/mexc/adapter.py +28 -11
- unicex/mexc/exchange_info.py +32 -0
- unicex/mexc/uni_client.py +6 -0
- unicex/okx/__init__.py +12 -0
- unicex/okx/adapter.py +23 -7
- unicex/okx/exchange_info.py +50 -0
- unicex/okx/uni_client.py +2 -2
- unicex/types.py +31 -0
- unicex-0.7.0.dist-info/METADATA +192 -0
- unicex-0.7.0.dist-info/RECORD +75 -0
- unicex/bitrue/__init__.py +0 -15
- unicex/bitrue/adapter.py +0 -8
- unicex/bitrue/client.py +0 -128
- unicex/bitrue/uni_client.py +0 -151
- unicex/bitrue/uni_websocket_manager.py +0 -269
- unicex/bitrue/user_websocket.py +0 -7
- unicex/bitrue/websocket_manager.py +0 -11
- unicex/bitunix/__init__.py +0 -15
- unicex/bitunix/adapter.py +0 -8
- unicex/bitunix/client.py +0 -8
- unicex/bitunix/uni_client.py +0 -151
- unicex/bitunix/uni_websocket_manager.py +0 -269
- unicex/bitunix/user_websocket.py +0 -7
- unicex/bitunix/websocket_manager.py +0 -11
- unicex/btse/__init__.py +0 -15
- unicex/btse/adapter.py +0 -8
- unicex/btse/client.py +0 -123
- unicex/btse/uni_client.py +0 -151
- unicex/btse/uni_websocket_manager.py +0 -269
- unicex/btse/user_websocket.py +0 -7
- unicex/btse/websocket_manager.py +0 -11
- unicex/kcex/__init__.py +0 -15
- unicex/kcex/adapter.py +0 -8
- unicex/kcex/client.py +0 -8
- unicex/kcex/uni_client.py +0 -151
- unicex/kcex/uni_websocket_manager.py +0 -269
- unicex/kcex/user_websocket.py +0 -7
- unicex/kcex/websocket_manager.py +0 -11
- unicex/kraken/__init__.py +0 -15
- unicex/kraken/adapter.py +0 -8
- unicex/kraken/client.py +0 -165
- unicex/kraken/uni_client.py +0 -151
- unicex/kraken/uni_websocket_manager.py +0 -269
- unicex/kraken/user_websocket.py +0 -7
- unicex/kraken/websocket_manager.py +0 -11
- unicex/kucoin/__init__.py +0 -15
- unicex/kucoin/adapter.py +0 -8
- unicex/kucoin/client.py +0 -120
- unicex/kucoin/uni_client.py +0 -151
- unicex/kucoin/uni_websocket_manager.py +0 -269
- unicex/kucoin/user_websocket.py +0 -7
- unicex/kucoin/websocket_manager.py +0 -11
- unicex/weex/__init__.py +0 -15
- unicex/weex/adapter.py +0 -8
- unicex/weex/client.py +0 -8
- unicex/weex/uni_client.py +0 -151
- unicex/weex/uni_websocket_manager.py +0 -269
- unicex/weex/user_websocket.py +0 -7
- unicex/weex/websocket_manager.py +0 -11
- unicex/xt/__init__.py +0 -15
- unicex/xt/adapter.py +0 -8
- unicex/xt/client.py +0 -8
- unicex/xt/uni_client.py +0 -151
- unicex/xt/uni_websocket_manager.py +0 -269
- unicex/xt/user_websocket.py +0 -7
- unicex/xt/websocket_manager.py +0 -11
- unicex-0.4.0.dist-info/METADATA +0 -170
- unicex-0.4.0.dist-info/RECORD +0 -123
- {unicex-0.4.0.dist-info → unicex-0.7.0.dist-info}/WHEEL +0 -0
- {unicex-0.4.0.dist-info → unicex-0.7.0.dist-info}/licenses/LICENSE +0 -0
- {unicex-0.4.0.dist-info → unicex-0.7.0.dist-info}/top_level.txt +0 -0
unicex/enums.py
CHANGED
|
@@ -26,18 +26,13 @@ class Exchange(StrEnum):
|
|
|
26
26
|
|
|
27
27
|
BINANCE = "BINANCE"
|
|
28
28
|
BITGET = "BITGET"
|
|
29
|
-
BITRUE = "BITRUE"
|
|
30
29
|
BITUNIX = "BITUNIX"
|
|
31
|
-
BTSE = "BTSE"
|
|
32
30
|
BYBIT = "BYBIT"
|
|
33
31
|
GATEIO = "GATEIO"
|
|
34
32
|
HYPERLIQUID = "HYPERLIQUID"
|
|
35
33
|
KCEX = "KCEX"
|
|
36
|
-
KRAKEN = "KRAKEN"
|
|
37
|
-
KUCOIN = "KUCOIN"
|
|
38
34
|
MEXC = "MEXC"
|
|
39
35
|
OKX = "OKX"
|
|
40
|
-
WEEX = "WEEX"
|
|
41
36
|
XT = "XT"
|
|
42
37
|
|
|
43
38
|
def __add__(self, market_type: "MarketType") -> tuple["Exchange", "MarketType"]:
|
|
@@ -227,6 +222,22 @@ class Timeframe(StrEnum):
|
|
|
227
222
|
Timeframe.WEEK_1: "7d",
|
|
228
223
|
Timeframe.MONTH_1: "30d",
|
|
229
224
|
},
|
|
225
|
+
Exchange.HYPERLIQUID: {
|
|
226
|
+
Timeframe.MIN_1: "1m",
|
|
227
|
+
Timeframe.MIN_3: "3m",
|
|
228
|
+
Timeframe.MIN_5: "5m",
|
|
229
|
+
Timeframe.MIN_15: "15m",
|
|
230
|
+
Timeframe.MIN_30: "30m",
|
|
231
|
+
Timeframe.HOUR_1: "1h",
|
|
232
|
+
Timeframe.HOUR_2: "2h",
|
|
233
|
+
Timeframe.HOUR_4: "4h",
|
|
234
|
+
Timeframe.HOUR_8: "8h",
|
|
235
|
+
Timeframe.HOUR_12: "12h",
|
|
236
|
+
Timeframe.DAY_1: "1d",
|
|
237
|
+
Timeframe.DAY_3: "3d",
|
|
238
|
+
Timeframe.WEEK_1: "1w",
|
|
239
|
+
Timeframe.MONTH_1: "1M",
|
|
240
|
+
},
|
|
230
241
|
}
|
|
231
242
|
|
|
232
243
|
def to_exchange_format(self, exchange: Exchange, market_type: MarketType | None = None) -> str:
|
unicex/extra.py
CHANGED
|
@@ -7,9 +7,11 @@ __all__ = [
|
|
|
7
7
|
"generate_ex_link",
|
|
8
8
|
"generate_tv_link",
|
|
9
9
|
"generate_cg_link",
|
|
10
|
+
"make_humanreadable",
|
|
10
11
|
]
|
|
11
12
|
|
|
12
13
|
import time
|
|
14
|
+
from typing import Literal
|
|
13
15
|
|
|
14
16
|
from .enums import Exchange, MarketType
|
|
15
17
|
from .exceptions import NotSupported
|
|
@@ -205,3 +207,50 @@ def generate_cg_link(exchange: Exchange, market_type: MarketType, symbol: str) -
|
|
|
205
207
|
return f"{base_url}/SPOT_{exchange.upper()}_{symbol.replace('USDT', '-USDT')}"
|
|
206
208
|
# Для остальных бирж ссылки нет → возвращаем заглушку
|
|
207
209
|
return base_url
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def make_humanreadable(value: float, locale: Literal["ru", "en"] = "ru") -> str:
|
|
213
|
+
"""Функция превращает большие числа в удобочитаемый вид.
|
|
214
|
+
|
|
215
|
+
Принимает:
|
|
216
|
+
value (float): число для преобразования
|
|
217
|
+
locale (Literal["ru", "en"]): язык для форматирования числа
|
|
218
|
+
|
|
219
|
+
Возвращает:
|
|
220
|
+
str: Человеческое представление числа
|
|
221
|
+
"""
|
|
222
|
+
suffixes = {
|
|
223
|
+
"ru": {
|
|
224
|
+
1_000: "тыс.",
|
|
225
|
+
1_000_000: "млн.",
|
|
226
|
+
1_000_000_000: "млрд.",
|
|
227
|
+
1_000_000_000_000: "трлн.",
|
|
228
|
+
1_000_000_000_000_000: "квдрлн.",
|
|
229
|
+
1_000_000_000_000_000_000: "квнтлн.",
|
|
230
|
+
},
|
|
231
|
+
"en": {
|
|
232
|
+
1_000: "K",
|
|
233
|
+
1_000_000: "M",
|
|
234
|
+
1_000_000_000: "B",
|
|
235
|
+
1_000_000_000_000: "T",
|
|
236
|
+
1_000_000_000_000_000: "Qa", # Quadrillion
|
|
237
|
+
1_000_000_000_000_000_000: "Qi", # Quintillion
|
|
238
|
+
},
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
selected_suffixes = suffixes[locale]
|
|
242
|
+
|
|
243
|
+
for divisor in sorted(selected_suffixes.keys(), reverse=True):
|
|
244
|
+
if abs(value) >= divisor:
|
|
245
|
+
number = value / divisor
|
|
246
|
+
if locale == "ru":
|
|
247
|
+
return (
|
|
248
|
+
f"{number:,.2f}".replace(",", " ").replace(".", ",")
|
|
249
|
+
+ f" {selected_suffixes[divisor]}"
|
|
250
|
+
)
|
|
251
|
+
return f"{number:,.2f} {selected_suffixes[divisor]}"
|
|
252
|
+
|
|
253
|
+
# Форматирование "малых" чисел
|
|
254
|
+
if locale == "ru":
|
|
255
|
+
return f"{value:,.2f}".replace(",", " ").replace(".", ",")
|
|
256
|
+
return f"{value:,.2f}"
|
unicex/gateio/__init__.py
CHANGED
|
@@ -6,10 +6,22 @@ __all__ = [
|
|
|
6
6
|
"UserWebsocket",
|
|
7
7
|
"WebsocketManager",
|
|
8
8
|
"UniWebsocketManager",
|
|
9
|
+
"ExchangeInfo",
|
|
9
10
|
]
|
|
10
11
|
|
|
11
12
|
from .client import Client
|
|
13
|
+
from .exchange_info import ExchangeInfo
|
|
12
14
|
from .uni_client import UniClient
|
|
13
15
|
from .uni_websocket_manager import UniWebsocketManager
|
|
14
16
|
from .user_websocket import UserWebsocket
|
|
15
17
|
from .websocket_manager import WebsocketManager
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def load_exchange_info() -> None:
|
|
21
|
+
"""Загружает информацию о бирже Gateio."""
|
|
22
|
+
await ExchangeInfo.load_exchange_info()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def start_exchange_info(parse_interval_seconds: int = 60 * 60) -> None:
|
|
26
|
+
"""Запускает процесс обновления информации о бирже Gateio."""
|
|
27
|
+
await ExchangeInfo.start(parse_interval_seconds)
|
unicex/gateio/adapter.py
CHANGED
|
@@ -32,7 +32,7 @@ class Adapter:
|
|
|
32
32
|
return [
|
|
33
33
|
item["currency_pair"]
|
|
34
34
|
for item in raw_data
|
|
35
|
-
if
|
|
35
|
+
if item["currency_pair"].endswith("USDT") or not only_usdt
|
|
36
36
|
]
|
|
37
37
|
|
|
38
38
|
@staticmethod
|
|
@@ -49,7 +49,7 @@ class Adapter:
|
|
|
49
49
|
return [
|
|
50
50
|
item["contract"]
|
|
51
51
|
for item in raw_data
|
|
52
|
-
if
|
|
52
|
+
if item["contract"].endswith("USDT") or not only_usdt
|
|
53
53
|
]
|
|
54
54
|
|
|
55
55
|
@staticmethod
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
__all__ = ["ExchangeInfo"]
|
|
2
|
+
|
|
3
|
+
from unicex._abc import IExchangeInfo
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ExchangeInfo(IExchangeInfo):
|
|
7
|
+
"""Предзагружает информацию о тикерах для биржи Gateio."""
|
|
8
|
+
|
|
9
|
+
@classmethod
|
|
10
|
+
async def _load_exchange_info(cls) -> None:
|
|
11
|
+
"""Загружает информацию о бирже."""
|
|
12
|
+
...
|
unicex/hyperliquid/__init__.py
CHANGED
|
@@ -6,10 +6,22 @@ __all__ = [
|
|
|
6
6
|
"UserWebsocket",
|
|
7
7
|
"WebsocketManager",
|
|
8
8
|
"UniWebsocketManager",
|
|
9
|
+
"ExchangeInfo",
|
|
9
10
|
]
|
|
10
11
|
|
|
11
12
|
from .client import Client
|
|
13
|
+
from .exchange_info import ExchangeInfo
|
|
12
14
|
from .uni_client import UniClient
|
|
13
15
|
from .uni_websocket_manager import UniWebsocketManager
|
|
14
16
|
from .user_websocket import UserWebsocket
|
|
15
17
|
from .websocket_manager import WebsocketManager
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def load_exchange_info() -> None:
|
|
21
|
+
"""Загружает информацию о бирже Hyperliquid."""
|
|
22
|
+
await ExchangeInfo.load_exchange_info()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def start_exchange_info(parse_interval_seconds: int = 60 * 60) -> None:
|
|
26
|
+
"""Запускает процесс обновления информации о бирже Hyperliquid."""
|
|
27
|
+
await ExchangeInfo.start(parse_interval_seconds)
|
unicex/hyperliquid/adapter.py
CHANGED
|
@@ -3,80 +3,119 @@ __all__ = ["Adapter"]
|
|
|
3
3
|
import time
|
|
4
4
|
|
|
5
5
|
from unicex.types import (
|
|
6
|
+
KlineDict,
|
|
6
7
|
OpenInterestDict,
|
|
7
8
|
OpenInterestItem,
|
|
8
9
|
TickerDailyDict,
|
|
9
10
|
TickerDailyItem,
|
|
10
11
|
)
|
|
11
|
-
from unicex.utils import catch_adapter_errors, decorate_all_methods
|
|
12
12
|
|
|
13
|
+
# from unicex.utils import catch_adapter_errors, decorate_all_methods
|
|
14
|
+
from .exchange_info import ExchangeInfo
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
|
|
17
|
+
# @decorate_all_methods(catch_adapter_errors)
|
|
15
18
|
class Adapter:
|
|
16
19
|
"""Адаптер для унификации данных с Hyperliquid API."""
|
|
17
20
|
|
|
18
21
|
@staticmethod
|
|
19
|
-
def tickers(raw_data:
|
|
22
|
+
def tickers(raw_data: dict, resolve_symbols: bool) -> list[str]:
|
|
20
23
|
"""Преобразует данные Hyperliquid в список спотовых тикеров.
|
|
21
24
|
|
|
22
25
|
Параметры:
|
|
23
|
-
raw_data (
|
|
26
|
+
raw_data (dict): Сырой ответ с биржи.
|
|
27
|
+
resolve_symbols (bool): Если True, тикеры маппятся из вида "@123" в "BTC".
|
|
24
28
|
|
|
25
29
|
Возвращает:
|
|
26
|
-
list[str]: Список тикеров (например, "
|
|
30
|
+
list[str]: Список тикеров (например, "@123").
|
|
27
31
|
"""
|
|
28
|
-
|
|
32
|
+
if resolve_symbols:
|
|
33
|
+
return [ExchangeInfo.resolve_spot_symbol(item["name"]) for item in raw_data["universe"]]
|
|
34
|
+
else:
|
|
35
|
+
return [item["name"] for item in raw_data["universe"]]
|
|
29
36
|
|
|
30
37
|
@staticmethod
|
|
31
|
-
def futures_tickers(raw_data:
|
|
38
|
+
def futures_tickers(raw_data: dict) -> list[str]:
|
|
32
39
|
"""Преобразует данные Hyperliquid в список фьючерсных тикеров.
|
|
33
40
|
|
|
34
41
|
Параметры:
|
|
35
|
-
raw_data (
|
|
42
|
+
raw_data (dict): Сырой ответ с биржи.
|
|
36
43
|
|
|
37
44
|
Возвращает:
|
|
38
|
-
list[str]: Список
|
|
45
|
+
list[str]: Список тикеров (например, "@123").
|
|
39
46
|
"""
|
|
40
|
-
|
|
41
|
-
return [item["name"] for item in universe]
|
|
47
|
+
return [item["name"] for item in raw_data["universe"]]
|
|
42
48
|
|
|
43
49
|
@staticmethod
|
|
44
|
-
def last_price(raw_data:
|
|
50
|
+
def last_price(raw_data: dict, resolve_symbols: bool) -> dict[str, float]:
|
|
45
51
|
"""Преобразует данные о последних ценах (spot) в унифицированный формат.
|
|
46
52
|
|
|
47
53
|
Параметры:
|
|
48
|
-
raw_data (
|
|
54
|
+
raw_data (dict): Сырой ответ с биржи.
|
|
55
|
+
resolve_symbols (bool): Если True, тикеры маппятся из вида "@123" в "BTC".
|
|
49
56
|
|
|
50
57
|
Возвращает:
|
|
51
58
|
dict[str, float]: Словарь тикеров и последних цен.
|
|
52
59
|
"""
|
|
53
|
-
|
|
60
|
+
if resolve_symbols:
|
|
61
|
+
return {
|
|
62
|
+
ExchangeInfo.resolve_spot_symbol(token): float(price)
|
|
63
|
+
for token, price in raw_data.items()
|
|
64
|
+
if token.startswith("@")
|
|
65
|
+
}
|
|
66
|
+
else:
|
|
67
|
+
return {
|
|
68
|
+
token: float(price) for token, price in raw_data.items() if token.startswith("@")
|
|
69
|
+
}
|
|
54
70
|
|
|
55
71
|
@staticmethod
|
|
56
|
-
def futures_last_price(raw_data:
|
|
72
|
+
def futures_last_price(raw_data: dict) -> dict[str, float]:
|
|
57
73
|
"""Преобразует данные о последних ценах (futures) в унифицированный формат.
|
|
58
74
|
|
|
59
75
|
Параметры:
|
|
60
|
-
raw_data (
|
|
76
|
+
raw_data (dict): Сырой ответ с биржи.
|
|
61
77
|
|
|
62
78
|
Возвращает:
|
|
63
79
|
dict[str, float]: Словарь тикеров и последних цен.
|
|
64
80
|
"""
|
|
65
|
-
|
|
66
|
-
metrics = raw_data[1]
|
|
67
|
-
return {universe[i]["name"]: float(item["markPx"]) for i, item in enumerate(metrics)}
|
|
81
|
+
return {k: v for k, v in raw_data.items() if not k.startswith("@")}
|
|
68
82
|
|
|
69
83
|
@staticmethod
|
|
70
|
-
def ticker_24hr(raw_data: list) -> TickerDailyDict:
|
|
84
|
+
def ticker_24hr(raw_data: list, resolve_symbols: bool) -> TickerDailyDict:
|
|
71
85
|
"""Преобразует 24-часовую статистику (spot) в унифицированный формат.
|
|
72
86
|
|
|
73
87
|
Параметры:
|
|
74
88
|
raw_data (list): Сырой ответ с биржи.
|
|
89
|
+
resolve_symbols (bool): Если True, тикеры маппятся из вида "@123" в "BTC".
|
|
75
90
|
|
|
76
91
|
Возвращает:
|
|
77
92
|
TickerDailyDict: Словарь тикеров и их статистики.
|
|
78
93
|
"""
|
|
79
|
-
|
|
94
|
+
metrics = raw_data[1]
|
|
95
|
+
result: TickerDailyDict = {}
|
|
96
|
+
|
|
97
|
+
for item in metrics:
|
|
98
|
+
try:
|
|
99
|
+
coin = item["coin"]
|
|
100
|
+
|
|
101
|
+
if resolve_symbols:
|
|
102
|
+
coin = ExchangeInfo.resolve_spot_symbol(coin) or coin
|
|
103
|
+
|
|
104
|
+
prev_day_px = float(item.get("prevDayPx") or "0")
|
|
105
|
+
mid_px = float(item.get("midPx") or "0")
|
|
106
|
+
mark_px = float(item.get("markPx") or "0")
|
|
107
|
+
day_ntl_vlm = float(item.get("dayNtlVlm") or "0")
|
|
108
|
+
|
|
109
|
+
p = ((mark_px - prev_day_px) / prev_day_px * 100) if prev_day_px else 0.0
|
|
110
|
+
v = (day_ntl_vlm / mid_px) if mid_px else 0.0
|
|
111
|
+
q = day_ntl_vlm
|
|
112
|
+
|
|
113
|
+
result[coin] = TickerDailyItem(p=p, v=v, q=q)
|
|
114
|
+
|
|
115
|
+
except (KeyError, TypeError, ValueError):
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
return result
|
|
80
119
|
|
|
81
120
|
@staticmethod
|
|
82
121
|
def futures_ticker_24hr(raw_data: list) -> TickerDailyDict:
|
|
@@ -90,16 +129,87 @@ class Adapter:
|
|
|
90
129
|
"""
|
|
91
130
|
universe = raw_data[0]["universe"]
|
|
92
131
|
metrics = raw_data[1]
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
132
|
+
|
|
133
|
+
result: TickerDailyDict = {}
|
|
134
|
+
|
|
135
|
+
for i, item in enumerate(metrics):
|
|
136
|
+
try:
|
|
137
|
+
prev_day_px = float(item.get("prevDayPx", 0) or "0")
|
|
138
|
+
oracle_px = float(item.get("oraclePx", 0) or "0")
|
|
139
|
+
mark_px = float(item.get("markPx", 0) or "0")
|
|
140
|
+
day_ntl_vlm = float(item.get("dayNtlVlm", 0) or "0")
|
|
141
|
+
|
|
142
|
+
p = ((mark_px - prev_day_px) / prev_day_px * 100) if prev_day_px else 0.0
|
|
143
|
+
v = (day_ntl_vlm / oracle_px) if oracle_px else 0.0
|
|
144
|
+
q = day_ntl_vlm
|
|
145
|
+
|
|
146
|
+
result[universe[i]["name"]] = TickerDailyItem(p=p, v=v, q=q)
|
|
147
|
+
except (KeyError, TypeError, ValueError):
|
|
148
|
+
continue
|
|
149
|
+
|
|
150
|
+
return result
|
|
151
|
+
|
|
152
|
+
@staticmethod
|
|
153
|
+
def klines(raw_data: list[dict], resolve_symbols: bool) -> list[KlineDict]:
|
|
154
|
+
"""Преобразует сырой ответ, в котором содержатся данные о свечах, в унифицированный формат.
|
|
155
|
+
|
|
156
|
+
Параметры:
|
|
157
|
+
raw_data (list[dict]): Сырой ответ с биржи.
|
|
158
|
+
resolve_symbols (bool): Если True, тикер маппится из вида "@123" в "BTC".
|
|
159
|
+
|
|
160
|
+
Возвращает:
|
|
161
|
+
list[KlineDict]: Список словарей, где каждый словарь содержит данные о свече.
|
|
162
|
+
"""
|
|
163
|
+
return [
|
|
164
|
+
KlineDict(
|
|
165
|
+
s=kline["s"]
|
|
166
|
+
if not resolve_symbols
|
|
167
|
+
else ExchangeInfo.resolve_spot_symbol(kline["s"]),
|
|
168
|
+
t=kline["t"],
|
|
169
|
+
o=float(kline["o"]),
|
|
170
|
+
h=float(kline["h"]),
|
|
171
|
+
l=float(kline["l"]),
|
|
172
|
+
c=float(kline["c"]),
|
|
173
|
+
v=float(kline["v"]),
|
|
174
|
+
q=float(kline["v"]) * float(kline["c"]),
|
|
175
|
+
T=kline["T"],
|
|
176
|
+
x=None,
|
|
100
177
|
)
|
|
101
|
-
for
|
|
102
|
-
|
|
178
|
+
for kline in sorted(
|
|
179
|
+
raw_data,
|
|
180
|
+
key=lambda x: int(x["t"]),
|
|
181
|
+
)
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
@staticmethod
|
|
185
|
+
def futures_klines(raw_data: list[dict]) -> list[KlineDict]:
|
|
186
|
+
"""Преобразует сырой ответ, в котором содержатся данные о свечах, в унифицированный формат.
|
|
187
|
+
|
|
188
|
+
Параметры:
|
|
189
|
+
raw_data (list[dict]): Сырой ответ с биржи.
|
|
190
|
+
symbol (str): Символ тикера.
|
|
191
|
+
|
|
192
|
+
Возвращает:
|
|
193
|
+
list[KlineDict]: Список словарей, где каждый словарь содержит данные о свече.
|
|
194
|
+
"""
|
|
195
|
+
return [
|
|
196
|
+
KlineDict(
|
|
197
|
+
s=kline["s"],
|
|
198
|
+
t=kline["t"],
|
|
199
|
+
o=float(kline["o"]),
|
|
200
|
+
h=float(kline["h"]),
|
|
201
|
+
l=float(kline["l"]),
|
|
202
|
+
c=float(kline["c"]),
|
|
203
|
+
v=float(kline["v"]),
|
|
204
|
+
q=float(kline["v"]) * float(kline["c"]),
|
|
205
|
+
T=kline["T"],
|
|
206
|
+
x=None,
|
|
207
|
+
)
|
|
208
|
+
for kline in sorted(
|
|
209
|
+
raw_data,
|
|
210
|
+
key=lambda x: int(x["t"]),
|
|
211
|
+
)
|
|
212
|
+
]
|
|
103
213
|
|
|
104
214
|
@staticmethod
|
|
105
215
|
def funding_rate(raw_data: list) -> dict[str, float]:
|