trd-utils 0.0.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.
Potentially problematic release.
This version of trd-utils might be problematic. Click here for more details.
- trd_utils/__init__.py +3 -0
- trd_utils/bx_ultra/__init__.py +6 -0
- trd_utils/bx_ultra/bx_types.py +719 -0
- trd_utils/bx_ultra/bx_ultra_client.py +436 -0
- trd_utils/bx_ultra/common_utils.py +51 -0
- trd_utils/cipher/__init__.py +44 -0
- trd_utils/html_utils/__init__.py +26 -0
- trd_utils/html_utils/html_formats.py +72 -0
- trd_utils/tradingview/__init__.py +8 -0
- trd_utils/tradingview/tradingview_client.py +130 -0
- trd_utils/tradingview/tradingview_types.py +185 -0
- trd_utils/types_helper/__init__.py +4 -0
- trd_utils/types_helper/base_model.py +150 -0
- trd_utils-0.0.1.dist-info/LICENSE +21 -0
- trd_utils-0.0.1.dist-info/METADATA +28 -0
- trd_utils-0.0.1.dist-info/RECORD +17 -0
- trd_utils-0.0.1.dist-info/WHEEL +4 -0
trd_utils/__init__.py
ADDED
|
@@ -0,0 +1,719 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
from ..types_helper import BaseModel
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
|
|
5
|
+
default_quantize = Decimal("1.00")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BxApiResponse(BaseModel):
|
|
9
|
+
code: int = None
|
|
10
|
+
timestamp: int = None
|
|
11
|
+
msg: str = None
|
|
12
|
+
|
|
13
|
+
def __str__(self):
|
|
14
|
+
return f"code: {self.code}; timestamp: {self.timestamp}"
|
|
15
|
+
|
|
16
|
+
def __repr__(self):
|
|
17
|
+
return f"code: {self.code}; timestamp: {self.timestamp}"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CoinQuotationInfo(BaseModel):
|
|
21
|
+
name: str = None
|
|
22
|
+
coin_type: int = None
|
|
23
|
+
valuation_coin_name: str = None
|
|
24
|
+
coin_name: str = None
|
|
25
|
+
icon_name: str = None
|
|
26
|
+
slug: str = None
|
|
27
|
+
quotation_id: int = None
|
|
28
|
+
open: Decimal = None
|
|
29
|
+
close: Decimal = None
|
|
30
|
+
weight: int = None
|
|
31
|
+
favorite_flag: Any = None # unknown
|
|
32
|
+
precision: int = None
|
|
33
|
+
coin_precision: int = None
|
|
34
|
+
valuation_precision: int = None
|
|
35
|
+
market_status: Any = None # unknown
|
|
36
|
+
trader_scale: Decimal = None
|
|
37
|
+
coin_id: int = None
|
|
38
|
+
valuation_coin_id: int = None
|
|
39
|
+
status: Any = None # unknown
|
|
40
|
+
open_time: Any = None # unknown
|
|
41
|
+
open_price: Any = None # unknown
|
|
42
|
+
high24: Optional[Decimal] = None
|
|
43
|
+
low24: Optional[Decimal] = None
|
|
44
|
+
volume24: Optional[Decimal] = None
|
|
45
|
+
amount24: Optional[Decimal] = None
|
|
46
|
+
market_val: Optional[Decimal] = None
|
|
47
|
+
full_name: str = None
|
|
48
|
+
biz_type: int = None
|
|
49
|
+
|
|
50
|
+
def __str__(self):
|
|
51
|
+
return f"{self.coin_name}/{self.valuation_coin_name}; price: {self.close}; vol: {self.market_val}"
|
|
52
|
+
|
|
53
|
+
def __repr__(self):
|
|
54
|
+
return f"{self.coin_name}/{self.valuation_coin_name}; price: {self.close}; vol: {self.market_val}"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
###########################################################
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class ZoneModuleInfo(BaseModel):
|
|
61
|
+
id: int = None
|
|
62
|
+
name: str = None
|
|
63
|
+
quotation_list: list[CoinQuotationInfo] = None
|
|
64
|
+
zone_name: str = None
|
|
65
|
+
weight: int = None
|
|
66
|
+
biz_type: int = None
|
|
67
|
+
|
|
68
|
+
def __str__(self):
|
|
69
|
+
return f"{self.name} ({self.zone_name})"
|
|
70
|
+
|
|
71
|
+
def __repr__(self):
|
|
72
|
+
return f"{self.name} ({self.zone_name})"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ZoneModuleListResult(BaseModel):
|
|
76
|
+
zone_module_list: list[ZoneModuleInfo] = None
|
|
77
|
+
biz_type: int = None
|
|
78
|
+
need_channel_type: list[int] = None
|
|
79
|
+
icon_url_prefix: str = None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class ZoneModuleListResponse(BxApiResponse):
|
|
83
|
+
data: ZoneModuleListResult = None
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
###########################################################
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class UserFavoriteQuotationResult(BaseModel):
|
|
90
|
+
usdt_margin_list: list[CoinQuotationInfo] = None
|
|
91
|
+
coin_margin_list: list[CoinQuotationInfo] = None
|
|
92
|
+
swap_list: list[CoinQuotationInfo] = None
|
|
93
|
+
biz_type: int = None
|
|
94
|
+
icon_url_prefix: str = None
|
|
95
|
+
recommend: bool = None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class UserFavoriteQuotationResponse(BxApiResponse):
|
|
99
|
+
data: UserFavoriteQuotationResult = None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
###########################################################
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class QuotationRankBizItem(BaseModel):
|
|
106
|
+
quotation_list: list[CoinQuotationInfo] = None
|
|
107
|
+
biz_type: int = None
|
|
108
|
+
biz_name: str = None
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class QuotationRankItem(BaseModel):
|
|
112
|
+
rank_type: int = None
|
|
113
|
+
rank_name: str = None
|
|
114
|
+
rank_biz_list: list[QuotationRankBizItem] = None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class QuotationRankResult(BaseModel):
|
|
118
|
+
rank_list: list[QuotationRankItem] = None
|
|
119
|
+
icon_prefix: str = None
|
|
120
|
+
icon_url_prefix: str = None
|
|
121
|
+
order_flag: int = None
|
|
122
|
+
show_favorite: bool = None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class QuotationRankResponse(BxApiResponse):
|
|
126
|
+
data: QuotationRankResult = None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
###########################################################
|
|
130
|
+
|
|
131
|
+
# region HotSearch types
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class HotSearchItem(BaseModel):
|
|
135
|
+
symbol: str = None
|
|
136
|
+
coin_name: str = None
|
|
137
|
+
val_coin_name: str = None
|
|
138
|
+
weight: int = None
|
|
139
|
+
|
|
140
|
+
def __str__(self):
|
|
141
|
+
return f"{self.coin_name} ({self.symbol})"
|
|
142
|
+
|
|
143
|
+
def __repr__(self):
|
|
144
|
+
return f"{self.coin_name} ({self.symbol})"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class HotSearchResult(BaseModel):
|
|
148
|
+
result: list[HotSearchItem] = None
|
|
149
|
+
hint_ab_test: bool = None
|
|
150
|
+
page_id: int = None
|
|
151
|
+
total: int = None
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class HotSearchResponse(BxApiResponse):
|
|
155
|
+
data: HotSearchResult = None
|
|
156
|
+
|
|
157
|
+
def __str__(self):
|
|
158
|
+
if not self.data:
|
|
159
|
+
return "HotSearchResponse: No data"
|
|
160
|
+
|
|
161
|
+
str_result = "HotSearchResponse: \n"
|
|
162
|
+
for current_item in self.data.result:
|
|
163
|
+
str_result += f" - {current_item}\n"
|
|
164
|
+
|
|
165
|
+
return str_result
|
|
166
|
+
|
|
167
|
+
def __repr__(self):
|
|
168
|
+
return self.__str__()
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# endregion
|
|
172
|
+
|
|
173
|
+
###########################################################
|
|
174
|
+
|
|
175
|
+
# region HomePage types
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class CoinModuleInfoBase(BaseModel):
|
|
179
|
+
name: str = None
|
|
180
|
+
coin_name: str = None
|
|
181
|
+
icon_name: str = None
|
|
182
|
+
valuation_coin_name: str = None
|
|
183
|
+
open: Decimal = None
|
|
184
|
+
close: Decimal = None
|
|
185
|
+
precision: int = None
|
|
186
|
+
biz_type: int = None
|
|
187
|
+
market_val: Decimal = None
|
|
188
|
+
status: int = None
|
|
189
|
+
open_time: int = None
|
|
190
|
+
open_price: Decimal = None
|
|
191
|
+
full_name: str = None
|
|
192
|
+
amount24: Decimal = None
|
|
193
|
+
global_first_publish: bool = None
|
|
194
|
+
st_tag: int = None
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class HomePageModuleIncreaseRankData(CoinModuleInfoBase):
|
|
198
|
+
pass
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class HomePageModuleIncreaseRank(BaseModel):
|
|
202
|
+
item_name: str = None
|
|
203
|
+
sub_module_type: int = None
|
|
204
|
+
data: list[HomePageModuleIncreaseRankData] = None
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class HomePageModuleHotZoneData(CoinModuleInfoBase):
|
|
208
|
+
zone_desc: str = None
|
|
209
|
+
zone_name: str = None
|
|
210
|
+
zone_id: int = None
|
|
211
|
+
zone_price_rate: Decimal = None
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class HomePageModuleHotZone(BaseModel):
|
|
215
|
+
data: list[HomePageModuleHotZoneData] = None
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class HomePageModuleRecentHotData(CoinModuleInfoBase):
|
|
219
|
+
pass
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class HomePageModuleRecentHot(BaseModel):
|
|
223
|
+
data: list[HomePageModuleRecentHotData] = None
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class HomePageModuleGlobalDebutData(CoinModuleInfoBase):
|
|
227
|
+
pass
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class HomePageModuleGlobalDebut(BaseModel):
|
|
231
|
+
data: list[HomePageModuleGlobalDebutData] = None
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class HomePageModuleMainMarketData(CoinModuleInfoBase):
|
|
235
|
+
pass
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class HomePageModuleMainMarket(BaseModel):
|
|
239
|
+
data: list[HomePageModuleMainMarketData] = None
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class HomePageModulePreOnlineData(CoinModuleInfoBase):
|
|
243
|
+
pass
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class HomePageModulePreOnline(BaseModel):
|
|
247
|
+
data: list[HomePageModulePreOnlineData] = None
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class HomePageModuleBannerData(BaseModel):
|
|
251
|
+
banner_title: str = None
|
|
252
|
+
banner_img: str = None
|
|
253
|
+
banner_jump_url: str = None
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
class HomePageModuleBanner(BaseModel):
|
|
257
|
+
data: list[HomePageModuleBannerData] = None
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class HomePageModuleInfo(BaseModel):
|
|
261
|
+
module_type: int = None
|
|
262
|
+
module_name: str = None
|
|
263
|
+
module_desc: str = None
|
|
264
|
+
item_list: list = None
|
|
265
|
+
|
|
266
|
+
def _check_module_name(
|
|
267
|
+
self, j_data: dict, module_name: str, module_type: int
|
|
268
|
+
) -> bool:
|
|
269
|
+
return (
|
|
270
|
+
self.module_name == module_name
|
|
271
|
+
or j_data.get("moduleName", None) == module_name
|
|
272
|
+
or self.module_type == module_type
|
|
273
|
+
or j_data.get("moduleType", None) == module_type
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
def _get_item_list_type(self, j_data: dict = None) -> type:
|
|
277
|
+
if not j_data:
|
|
278
|
+
# for more safety
|
|
279
|
+
j_data = {}
|
|
280
|
+
|
|
281
|
+
if self._check_module_name(j_data, "PRE_ONLINE", 1):
|
|
282
|
+
return list[HomePageModulePreOnline]
|
|
283
|
+
|
|
284
|
+
elif self._check_module_name(j_data, "MAIN_MARKET", 2):
|
|
285
|
+
return list[HomePageModuleMainMarket]
|
|
286
|
+
|
|
287
|
+
elif self._check_module_name(j_data, "RECENT_HOT", 3):
|
|
288
|
+
return list[HomePageModuleRecentHot]
|
|
289
|
+
|
|
290
|
+
elif self._check_module_name(j_data, "HOT_ZONE", 5):
|
|
291
|
+
return list[HomePageModuleHotZone]
|
|
292
|
+
|
|
293
|
+
elif self._check_module_name(j_data, "INCREASE_RANK", 6):
|
|
294
|
+
return list[HomePageModuleIncreaseRank]
|
|
295
|
+
|
|
296
|
+
elif self._check_module_name(j_data, "BANNER", 7):
|
|
297
|
+
return list[HomePageModuleBanner]
|
|
298
|
+
|
|
299
|
+
elif self._check_module_name(j_data, "GLOBAL_DEBUT", 8):
|
|
300
|
+
return list[HomePageModuleGlobalDebut]
|
|
301
|
+
|
|
302
|
+
return None
|
|
303
|
+
|
|
304
|
+
def __str__(self):
|
|
305
|
+
return (
|
|
306
|
+
f"{self.module_name} ({self.module_type}): {self.module_desc};"
|
|
307
|
+
+ f" {len(self.item_list)} items"
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
def __repr__(self):
|
|
311
|
+
return (
|
|
312
|
+
f"{self.module_name} ({self.module_type}): {self.module_desc};"
|
|
313
|
+
+ f" {len(self.item_list)} items"
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class HomePageResult(BaseModel):
|
|
318
|
+
icon_prefix: str = None
|
|
319
|
+
green_amount_img_prefix: str = None
|
|
320
|
+
red_amount_img_prefix: str = None
|
|
321
|
+
module_list: list[HomePageModuleInfo] = None
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class HomePageResponse(BxApiResponse):
|
|
325
|
+
data: HomePageResult = None
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
# endregion
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
###########################################################
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
class ZenDeskABStatusResult(BaseModel):
|
|
335
|
+
ab_status: int = None
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
class ZenDeskABStatusResponse(BxApiResponse):
|
|
339
|
+
data: ZenDeskABStatusResult = None
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
###########################################################
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class HintListResult(BaseModel):
|
|
346
|
+
hints: list = None # unknown
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
class HintListResponse(BxApiResponse):
|
|
350
|
+
data: HintListResult = None
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
###########################################################
|
|
354
|
+
|
|
355
|
+
#region CopyTrading types
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class CopyTradingSymbolConfigInfo(BaseModel):
|
|
359
|
+
price_precision: int = None
|
|
360
|
+
quantity_precision: int = None
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
class CopyTraderPositionInfo(BaseModel):
|
|
364
|
+
avg_price: Decimal = None
|
|
365
|
+
coin_name: str = None
|
|
366
|
+
leverage: Decimal = None
|
|
367
|
+
liquidated_price: Decimal = None
|
|
368
|
+
margin: Decimal = None
|
|
369
|
+
mark_price: Decimal = None
|
|
370
|
+
position_earning_rate: Decimal = None
|
|
371
|
+
position_no: int = None
|
|
372
|
+
position_side: str = None
|
|
373
|
+
position_side_and_symbol: str = None
|
|
374
|
+
symbol: str = None
|
|
375
|
+
symbol_config: CopyTradingSymbolConfigInfo = None
|
|
376
|
+
unrealized_pnl: Decimal = None
|
|
377
|
+
valuation_coin_name: str = None
|
|
378
|
+
volume: Decimal = None
|
|
379
|
+
search_result: Optional[bool] = None
|
|
380
|
+
short_position_rate: Decimal = None
|
|
381
|
+
total: int = None
|
|
382
|
+
|
|
383
|
+
def __str__(self):
|
|
384
|
+
return (
|
|
385
|
+
f"{self.coin_name} / {self.valuation_coin_name} {self.position_side} "
|
|
386
|
+
+ f"{self.leverage.quantize(default_quantize)}x "
|
|
387
|
+
+ f"vol: {self.volume.quantize(default_quantize)}; "
|
|
388
|
+
+ f"price: {self.avg_price.quantize(default_quantize)}; "
|
|
389
|
+
+ f"margin: {self.margin.quantize(default_quantize)}; "
|
|
390
|
+
+ f"pnl: {self.unrealized_pnl.quantize(default_quantize)}; "
|
|
391
|
+
+ f"ROI: {(self.position_earning_rate * 100).quantize(default_quantize)}%"
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
def __repr__(self):
|
|
395
|
+
return self.__str__()
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
class CopyTraderTradePositionsResult(BaseModel):
|
|
399
|
+
hide: int = None
|
|
400
|
+
long_position_rate: Decimal = None
|
|
401
|
+
page_id: int = None
|
|
402
|
+
positions: list[CopyTraderPositionInfo] = None
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
class CopyTraderTradePositionsResponse(BxApiResponse):
|
|
406
|
+
data: CopyTraderTradePositionsResult = None
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
class SearchCopyTraderCondition(BaseModel):
|
|
410
|
+
key: str = "exchangeId"
|
|
411
|
+
selected: int = 2
|
|
412
|
+
type: str = "singleSelect"
|
|
413
|
+
|
|
414
|
+
def to_dict(self):
|
|
415
|
+
return {
|
|
416
|
+
"key": self.key,
|
|
417
|
+
"selected": f"{self.selected}",
|
|
418
|
+
"type": self.type,
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
class SearchedTraderChartItem(BaseModel):
|
|
422
|
+
cumulative_pnl_rate: Decimal = None
|
|
423
|
+
|
|
424
|
+
class SearchedTraderExchangeVoInfo(BaseModel):
|
|
425
|
+
account_enum: str = None
|
|
426
|
+
desc: str = None
|
|
427
|
+
exchange_id: int = None
|
|
428
|
+
exchange_name: str = None
|
|
429
|
+
icon: str = None
|
|
430
|
+
|
|
431
|
+
class SearchTraderInfoRankStat(BaseModel):
|
|
432
|
+
api_identity: int = None
|
|
433
|
+
avg_hold_time: str = None
|
|
434
|
+
avg_loss_amount: str = None
|
|
435
|
+
avg_loss_rate: str = None
|
|
436
|
+
avg_profit_amount: str = None
|
|
437
|
+
avg_profit_rate: str = None
|
|
438
|
+
being_invite: bool = None
|
|
439
|
+
chart: list[SearchedTraderChartItem] = None # unknown; list
|
|
440
|
+
copier_status: int = None
|
|
441
|
+
dis_play_name: str = None
|
|
442
|
+
equity: str = None
|
|
443
|
+
exchange_vo: Any = None # unknown
|
|
444
|
+
expand: int = None
|
|
445
|
+
follower_earning: str = None
|
|
446
|
+
follower_full: bool = None
|
|
447
|
+
icon: str = None
|
|
448
|
+
is_pro: bool = None
|
|
449
|
+
is_relation: bool = None
|
|
450
|
+
last_trade_time: str = None
|
|
451
|
+
latest30_days_median_lever_times: str = None
|
|
452
|
+
latest30_days_median_margin: str = None
|
|
453
|
+
loss_count: int = None
|
|
454
|
+
max_draw_down: str = None
|
|
455
|
+
pnl_rate: str = None
|
|
456
|
+
profit_count: int = None
|
|
457
|
+
recent7_day_follower_num_change: int = None
|
|
458
|
+
recent30_day_follower_num_change: int = None
|
|
459
|
+
recent90_day_follower_num_change: int = None
|
|
460
|
+
recent180_day_follower_num_change: int = None
|
|
461
|
+
risk_level7_days: str = None
|
|
462
|
+
risk_level30_days: str = None
|
|
463
|
+
risk_level90_days: str = None
|
|
464
|
+
risk_level180_days: str = None
|
|
465
|
+
risk_status: int = None
|
|
466
|
+
str_acc_follower_num: str = None
|
|
467
|
+
str_follower_num: str = None
|
|
468
|
+
str_recent7_days_rate: str = None
|
|
469
|
+
str_recent30_days_rate: str = None
|
|
470
|
+
str_recent90_days_rate: str = None
|
|
471
|
+
str_recent180_days_rate: str = None
|
|
472
|
+
str_recent180_days_rate: str = None
|
|
473
|
+
str_total_earnings_rate: str = None
|
|
474
|
+
total_earnings: str = None
|
|
475
|
+
total_transactions: int = None
|
|
476
|
+
trade_days: str = None
|
|
477
|
+
update_time: str = None
|
|
478
|
+
valid: int = None
|
|
479
|
+
vst_copier_status: int = None
|
|
480
|
+
weekly_trade_frequency: str = None
|
|
481
|
+
winRate: str = None
|
|
482
|
+
|
|
483
|
+
class SearchedTraderInfo(BaseModel):
|
|
484
|
+
avatar: str = None
|
|
485
|
+
be_trader: bool = None
|
|
486
|
+
channel: str = None
|
|
487
|
+
flag: str = None
|
|
488
|
+
ip_country: str = None
|
|
489
|
+
nation: str = None
|
|
490
|
+
nick_name: str = None
|
|
491
|
+
register_date: str = None
|
|
492
|
+
register_ip_country: str = None
|
|
493
|
+
short_uid: int = None
|
|
494
|
+
team_id: int = None
|
|
495
|
+
uid: int = None
|
|
496
|
+
|
|
497
|
+
class SearchedTraderAccountGradeVoInfo(BaseModel):
|
|
498
|
+
api_identity: int = None
|
|
499
|
+
label: int = None
|
|
500
|
+
trader_grade: int = None
|
|
501
|
+
uid: int = None
|
|
502
|
+
|
|
503
|
+
class SearchTraderInfoContainer(BaseModel):
|
|
504
|
+
content: str = None
|
|
505
|
+
has_new: bool = None
|
|
506
|
+
labels: list = None # unknown
|
|
507
|
+
rank_stat: SearchTraderInfoRankStat = None # unknown
|
|
508
|
+
trader: SearchedTraderInfo = None # unknown
|
|
509
|
+
trader_account_grade_vo: SearchedTraderAccountGradeVoInfo = None # unknown
|
|
510
|
+
trader_public_recommend_status: Any = None # unknown
|
|
511
|
+
|
|
512
|
+
def get_nick_name(self) -> str:
|
|
513
|
+
if self.trader:
|
|
514
|
+
return self.trader.nick_name
|
|
515
|
+
|
|
516
|
+
return
|
|
517
|
+
|
|
518
|
+
def get_uid(self) -> int:
|
|
519
|
+
if self.trader:
|
|
520
|
+
return self.trader.uid
|
|
521
|
+
|
|
522
|
+
return
|
|
523
|
+
|
|
524
|
+
def get_api_identity(self) -> int:
|
|
525
|
+
if self.trader_account_grade_vo:
|
|
526
|
+
return self.trader_account_grade_vo.api_identity
|
|
527
|
+
|
|
528
|
+
if self.rank_stat:
|
|
529
|
+
return self.rank_stat.api_identity
|
|
530
|
+
|
|
531
|
+
# TODO: later on add support for more cases
|
|
532
|
+
return None
|
|
533
|
+
|
|
534
|
+
def __str__(self):
|
|
535
|
+
if not self.trader:
|
|
536
|
+
return "No trader info"
|
|
537
|
+
|
|
538
|
+
return f"uid: {self.trader.uid}; name: {self.trader.nick_name}; country: {self.trader.nation}"
|
|
539
|
+
|
|
540
|
+
def __repr__(self):
|
|
541
|
+
return self.__str__()
|
|
542
|
+
|
|
543
|
+
class SearchCopyTradersResult(BaseModel):
|
|
544
|
+
expand_display: Any = None # unknown
|
|
545
|
+
fold_display: Any = None # unknown
|
|
546
|
+
page_id: int = None
|
|
547
|
+
rank_desc: str = None
|
|
548
|
+
rank_short_desc: str = None
|
|
549
|
+
rank_statistic_days: int = None
|
|
550
|
+
rank_tags: Any = None # unknown
|
|
551
|
+
rank_title: str = None
|
|
552
|
+
rank_type: str = None
|
|
553
|
+
result: list[SearchTraderInfoContainer] = None # unknown
|
|
554
|
+
search_result: bool = None
|
|
555
|
+
total: int = None
|
|
556
|
+
|
|
557
|
+
class SearchCopyTradersResponse(BxApiResponse):
|
|
558
|
+
data: SearchCopyTradersResult = None
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
#endregion
|
|
562
|
+
|
|
563
|
+
###########################################################
|
|
564
|
+
|
|
565
|
+
# region Account Assets types
|
|
566
|
+
|
|
567
|
+
class TotalAssetsInfo(BaseModel):
|
|
568
|
+
amount: Any = None # unknown
|
|
569
|
+
currency_amount: Decimal = None
|
|
570
|
+
sign: str = None
|
|
571
|
+
|
|
572
|
+
def __str__(self):
|
|
573
|
+
return f"{self.currency_amount.quantize(default_quantize)} {self.sign}"
|
|
574
|
+
|
|
575
|
+
def __repr__(self):
|
|
576
|
+
return self.__str__()
|
|
577
|
+
|
|
578
|
+
class AccountOverviewItem(BaseModel):
|
|
579
|
+
account_name: str = None
|
|
580
|
+
account_type: int = None
|
|
581
|
+
total: TotalAssetsInfo = None # unknown
|
|
582
|
+
schema: str = None
|
|
583
|
+
order: int = None
|
|
584
|
+
|
|
585
|
+
def __str__(self):
|
|
586
|
+
return f"{self.account_name} ({self.account_type}): {self.total}"
|
|
587
|
+
|
|
588
|
+
class AssetsInfoResult(BaseModel):
|
|
589
|
+
total: TotalAssetsInfo = None
|
|
590
|
+
account_overviews: list[AccountOverviewItem] = None
|
|
591
|
+
recharge: int = None
|
|
592
|
+
withdraw: int = None
|
|
593
|
+
transfer: int = None
|
|
594
|
+
exchange: int = None
|
|
595
|
+
fault_flag: int = None
|
|
596
|
+
fault_accounts: Any = None # unknown
|
|
597
|
+
|
|
598
|
+
class AssetsInfoResponse(BxApiResponse):
|
|
599
|
+
data: AssetsInfoResult = None
|
|
600
|
+
|
|
601
|
+
# endregion
|
|
602
|
+
|
|
603
|
+
###########################################################
|
|
604
|
+
|
|
605
|
+
# region Contracts types
|
|
606
|
+
|
|
607
|
+
class BasicCoinInfo(BaseModel):
|
|
608
|
+
name: str = None
|
|
609
|
+
|
|
610
|
+
def __str__(self):
|
|
611
|
+
return f"{self.name} CoinInfo"
|
|
612
|
+
|
|
613
|
+
def __repr__(self):
|
|
614
|
+
return self.__str__()
|
|
615
|
+
|
|
616
|
+
class QuotationCoinVOInfo(BaseModel):
|
|
617
|
+
id: int = None
|
|
618
|
+
coin: BasicCoinInfo = None
|
|
619
|
+
valuation_coin: BasicCoinInfo = None
|
|
620
|
+
precision: int = None
|
|
621
|
+
name: str = None
|
|
622
|
+
market_status: int = None
|
|
623
|
+
|
|
624
|
+
class OrderDebitInfo(BaseModel):
|
|
625
|
+
lend_coin: BasicCoinInfo = None
|
|
626
|
+
amount: Decimal = None
|
|
627
|
+
|
|
628
|
+
class OrderOpenTradeInfo(BaseModel):
|
|
629
|
+
traded_amount: Decimal = None
|
|
630
|
+
traded_cash_amount: Decimal = None
|
|
631
|
+
|
|
632
|
+
class ContractOrderStatus(BaseModel):
|
|
633
|
+
code: int = None
|
|
634
|
+
value: str = None
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
class ContractTakeProfitInfo(BaseModel):
|
|
638
|
+
id: int = None
|
|
639
|
+
|
|
640
|
+
# this is id of the contract that this take-profit info belongs to.
|
|
641
|
+
order_no: int = None
|
|
642
|
+
margin_coin_name: str = None
|
|
643
|
+
type: int = None
|
|
644
|
+
margin: Decimal = None
|
|
645
|
+
stop_rate: Decimal = None
|
|
646
|
+
stop_price: Decimal = None
|
|
647
|
+
close_style: int = None
|
|
648
|
+
all_close: bool = None
|
|
649
|
+
|
|
650
|
+
class ContractStopLossInfo(BaseModel):
|
|
651
|
+
pass
|
|
652
|
+
|
|
653
|
+
class ProfitLossInfoContainer(BaseModel):
|
|
654
|
+
loss_nums: int = None
|
|
655
|
+
profit_nums: int = None
|
|
656
|
+
profit_margin: Decimal = None
|
|
657
|
+
loss_margin: Decimal = None
|
|
658
|
+
profit_config: ContractTakeProfitInfo = None
|
|
659
|
+
loss_config: ContractStopLossInfo = None
|
|
660
|
+
|
|
661
|
+
class ContractOrderInfo(BaseModel):
|
|
662
|
+
order_no: int = None
|
|
663
|
+
quotation_coin_vo: QuotationCoinVOInfo = None
|
|
664
|
+
margin: Decimal = None
|
|
665
|
+
margin_coin_name: str = None
|
|
666
|
+
lever_times: Decimal = None
|
|
667
|
+
display_lever_times: Decimal = None
|
|
668
|
+
amount: Decimal = None # margin * lever_times
|
|
669
|
+
display_price: Decimal = None
|
|
670
|
+
display_close_price: Decimal = None
|
|
671
|
+
order_type: int = None
|
|
672
|
+
close_type: int = None
|
|
673
|
+
status: ContractOrderStatus = None
|
|
674
|
+
open_date: str = None
|
|
675
|
+
fees: Decimal = None
|
|
676
|
+
lever_fee: Decimal = None
|
|
677
|
+
name: str = None
|
|
678
|
+
order_create_type: int = None
|
|
679
|
+
hide_price: bool = None
|
|
680
|
+
fee_rate: Decimal = None
|
|
681
|
+
hide: int = None
|
|
682
|
+
liquidation_desc: str = None
|
|
683
|
+
contract_account_mode: int = None
|
|
684
|
+
current_price: Decimal = None
|
|
685
|
+
sys_force_price: Decimal = None
|
|
686
|
+
fund_type: int = None
|
|
687
|
+
interest: Decimal = None
|
|
688
|
+
order_open_trade: OrderOpenTradeInfo = None
|
|
689
|
+
order_debit: OrderDebitInfo = None
|
|
690
|
+
open_rate: Decimal = None
|
|
691
|
+
close_rate: Decimal = None
|
|
692
|
+
market_status: int = None
|
|
693
|
+
create_time: str = None
|
|
694
|
+
coupon_amount: Decimal = None
|
|
695
|
+
stop_profit_modify_time: str = None
|
|
696
|
+
stop_loss_modify_time: str = None
|
|
697
|
+
show_adjust_margin: int = None
|
|
698
|
+
trailing_stop: Decimal = None
|
|
699
|
+
trailing_close_price: Decimal = None
|
|
700
|
+
stop_rate: Decimal = None
|
|
701
|
+
profit_loss_info: ProfitLossInfoContainer = None
|
|
702
|
+
configs: Any = None # just dictionaries of take-profit and stop-loss configs.
|
|
703
|
+
stop_offset_rate: Decimal = None
|
|
704
|
+
|
|
705
|
+
class MarginStatInfo(BaseModel):
|
|
706
|
+
name: str = None
|
|
707
|
+
margin_coin_name: str = None
|
|
708
|
+
margin_type: int = None
|
|
709
|
+
|
|
710
|
+
# total count of open contract orders in this margin-type.
|
|
711
|
+
total: int = None
|
|
712
|
+
|
|
713
|
+
class ContractsListResult(BaseModel):
|
|
714
|
+
orders: list[ContractOrderInfo] = None
|
|
715
|
+
page_id: int = None
|
|
716
|
+
margin_stats: list[MarginStatInfo] = None
|
|
717
|
+
|
|
718
|
+
class ContractsListResponse(BxApiResponse):
|
|
719
|
+
data: ContractsListResult = None
|