ccxt 3.1.60__py2.py3-none-any.whl → 4.0.3__py2.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.
ccxt/xt.py DELETED
@@ -1,4419 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
- # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
-
6
- from ccxt.base.exchange import Exchange
7
- from ccxt.abstract.xt import ImplicitAPI
8
- import hashlib
9
- from typing import Optional
10
- from typing import List
11
- from ccxt.base.errors import ExchangeError
12
- from ccxt.base.errors import PermissionDenied
13
- from ccxt.base.errors import BadRequest
14
- from ccxt.base.errors import BadSymbol
15
- from ccxt.base.errors import InsufficientFunds
16
- from ccxt.base.errors import InvalidOrder
17
- from ccxt.base.errors import NotSupported
18
- from ccxt.base.errors import NetworkError
19
- from ccxt.base.errors import RateLimitExceeded
20
- from ccxt.base.errors import OnMaintenance
21
- from ccxt.base.errors import RequestTimeout
22
- from ccxt.base.errors import AuthenticationError
23
- from ccxt.base.decimal_to_precision import TICK_SIZE
24
- from ccxt.base.precise import Precise
25
-
26
-
27
- class xt(Exchange, ImplicitAPI):
28
-
29
- def describe(self):
30
- return self.deep_extend(super(xt, self).describe(), {
31
- 'id': 'xt',
32
- 'name': 'XT',
33
- 'countries': ['SC'], # Seychelles
34
- # spot api ratelimits are None, 10/s/ip, 50/s/ip, 100/s/ip or 200/s/ip
35
- # futures 3 requests per second => 1000ms / (100 * 3.33) = 3.003(get assets -> fetchMarkets & fetchCurrencies)
36
- # futures 10 requests per second => 1000ms / (100 * 1) = 10(all other)
37
- # futures 1000 times per minute for each single IP -> Otherwise account locked for 10min
38
- 'rateLimit': 100,
39
- 'version': 'v4',
40
- 'certified': True,
41
- 'pro': False,
42
- 'has': {
43
- 'CORS': False,
44
- 'spot': True,
45
- 'margin': True,
46
- 'swap': True,
47
- 'future': True,
48
- 'option': False,
49
- 'addMargin': True,
50
- 'borrowMargin': False,
51
- 'cancelAllOrders': True,
52
- 'cancelOrder': True,
53
- 'cancelOrders': True,
54
- 'createDepositAddress': False,
55
- 'createOrder': True,
56
- 'createPostOnlyOrder': False,
57
- 'createReduceOnlyOrder': True,
58
- 'editOrder': False,
59
- 'fetchAccounts': False,
60
- 'fetchBalance': True,
61
- 'fetchBidsAsks': True,
62
- 'fetchBorrowInterest': False,
63
- 'fetchBorrowRate': False,
64
- 'fetchBorrowRateHistories': False,
65
- 'fetchBorrowRateHistory': False,
66
- 'fetchBorrowRatesPerSymbol': False,
67
- 'fetchCanceledOrders': True,
68
- 'fetchClosedOrders': True,
69
- 'fetchCurrencies': True,
70
- 'fetchDeposit': False,
71
- 'fetchDepositAddress': True,
72
- 'fetchDeposits': True,
73
- 'fetchDepositWithdrawals': False,
74
- 'fetchDepositWithdrawFee': False,
75
- 'fetchDepositWithdrawFees': False,
76
- 'fetchFundingHistory': True,
77
- 'fetchFundingRate': True,
78
- 'fetchFundingRateHistory': True,
79
- 'fetchFundingRates': False,
80
- 'fetchIndexOHLCV': False,
81
- 'fetchL3OrderBook': False,
82
- 'fetchLedger': True,
83
- 'fetchLedgerEntry': False,
84
- 'fetchLeverage': False,
85
- 'fetchLeverageTiers': True,
86
- 'fetchMarketLeverageTiers': True,
87
- 'fetchMarkets': True,
88
- 'fetchMarkOHLCV': False,
89
- 'fetchMyTrades': True,
90
- 'fetchOHLCV': True,
91
- 'fetchOpenInterest': False,
92
- 'fetchOpenInterestHistory': False,
93
- 'fetchOpenOrders': True,
94
- 'fetchOrder': True,
95
- 'fetchOrderBook': True,
96
- 'fetchOrderBooks': False,
97
- 'fetchOrders': True,
98
- 'fetchOrdersByStatus': True,
99
- 'fetchOrderTrades': False,
100
- 'fetchPosition': True,
101
- 'fetchPositions': True,
102
- 'fetchPremiumIndexOHLCV': False,
103
- 'fetchSettlementHistory': False,
104
- 'fetchStatus': False,
105
- 'fetchTicker': True,
106
- 'fetchTickers': True,
107
- 'fetchTime': True,
108
- 'fetchTrades': True,
109
- 'fetchTradingFee': False,
110
- 'fetchTradingFees': False,
111
- 'fetchTradingLimits': False,
112
- 'fetchTransactionFee': False,
113
- 'fetchTransactionFees': False,
114
- 'fetchTransactions': False,
115
- 'fetchTransfer': False,
116
- 'fetchTransfers': False,
117
- 'fetchWithdrawal': False,
118
- 'fetchWithdrawals': True,
119
- 'fetchWithdrawalWhitelist': False,
120
- 'reduceMargin': True,
121
- 'repayMargin': False,
122
- 'setLeverage': True,
123
- 'setMargin': False,
124
- 'setMarginMode': False,
125
- 'setPositionMode': False,
126
- 'signIn': False,
127
- 'transfer': True,
128
- 'withdraw': True,
129
- },
130
- 'precisionMode': TICK_SIZE,
131
- 'urls': {
132
- 'logo': 'https://user-images.githubusercontent.com/14319357/232636712-466df2fc-560a-4ca4-aab2-b1d954a58e24.jpg',
133
- 'api': {
134
- 'spot': 'https://sapi.xt.com',
135
- 'linear': 'https://fapi.xt.com',
136
- 'inverse': 'https://dapi.xt.com',
137
- 'user': 'https://api.xt.com',
138
- },
139
- 'www': 'https://xt.com',
140
- 'referral': 'https://www.xt.com/en/accounts/register?ref=9PTM9VW',
141
- 'doc': [
142
- 'https://doc.xt.com/',
143
- 'https://github.com/xtpub/api-doc',
144
- ],
145
- 'fees': 'https://www.xt.com/en/rate',
146
- },
147
- 'api': {
148
- 'public': {
149
- 'spot': {
150
- 'get': {
151
- 'currencies': 1,
152
- 'depth': 0.05,
153
- 'kline': 0.1,
154
- 'symbol': 1, # 0.1 for a single symbol
155
- 'ticker': 1, # 0.1 for a single symbol
156
- 'ticker/book': 1, # 0.1 for a single symbol
157
- 'ticker/price': 1, # 0.1 for a single symbol
158
- 'ticker/24h': 1, # 0.1 for a single symbol
159
- 'time': 1,
160
- 'trade/history': 0.1,
161
- 'trade/recent': 0.1,
162
- 'wallet/support/currency': 1,
163
- },
164
- },
165
- 'linear': {
166
- 'get': {
167
- 'future/market/v1/public/contract/risk-balance': 1,
168
- 'future/market/v1/public/contract/open-interest': 1,
169
- 'future/market/v1/public/leverage/bracket/detail': 1,
170
- 'future/market/v1/public/leverage/bracket/list': 1,
171
- 'future/market/v1/public/q/agg-ticker': 1,
172
- 'future/market/v1/public/q/agg-tickers': 1,
173
- 'future/market/v1/public/q/deal': 1,
174
- 'future/market/v1/public/q/depth': 1,
175
- 'future/market/v1/public/q/funding-rate': 1,
176
- 'future/market/v1/public/q/funding-rate-record': 1,
177
- 'future/market/v1/public/q/index-price': 1,
178
- 'future/market/v1/public/q/kline': 1,
179
- 'future/market/v1/public/q/mark-price': 1,
180
- 'future/market/v1/public/q/symbol-index-price': 1,
181
- 'future/market/v1/public/q/symbol-mark-price': 1,
182
- 'future/market/v1/public/q/ticker': 1,
183
- 'future/market/v1/public/q/tickers': 1,
184
- 'future/market/v1/public/symbol/coins': 3.33,
185
- 'future/market/v1/public/symbol/detail': 3.33,
186
- 'future/market/v1/public/symbol/list': 1,
187
- },
188
- },
189
- 'inverse': {
190
- 'get': {
191
- 'future/market/v1/public/contract/risk-balance': 1,
192
- 'future/market/v1/public/contract/open-interest': 1,
193
- 'future/market/v1/public/leverage/bracket/detail': 1,
194
- 'future/market/v1/public/leverage/bracket/list': 1,
195
- 'future/market/v1/public/q/agg-ticker': 1,
196
- 'future/market/v1/public/q/agg-tickers': 1,
197
- 'future/market/v1/public/q/deal': 1,
198
- 'future/market/v1/public/q/depth': 1,
199
- 'future/market/v1/public/q/funding-rate': 1,
200
- 'future/market/v1/public/q/funding-rate-record': 1,
201
- 'future/market/v1/public/q/index-price': 1,
202
- 'future/market/v1/public/q/kline': 1,
203
- 'future/market/v1/public/q/mark-price': 1,
204
- 'future/market/v1/public/q/symbol-index-price': 1,
205
- 'future/market/v1/public/q/symbol-mark-price': 1,
206
- 'future/market/v1/public/q/ticker': 1,
207
- 'future/market/v1/public/q/tickers': 1,
208
- 'future/market/v1/public/symbol/coins': 3.33,
209
- 'future/market/v1/public/symbol/detail': 3.33,
210
- 'future/market/v1/public/symbol/list': 1,
211
- },
212
- },
213
- },
214
- 'private': {
215
- 'spot': {
216
- 'get': {
217
- 'balance': 1,
218
- 'balances': 1,
219
- 'batch-order': 1,
220
- 'deposit/address': 1,
221
- 'deposit/history': 1,
222
- 'history-order': 1,
223
- 'open-order': 1,
224
- 'order': 1,
225
- 'order/{orderId}': 1,
226
- 'trade': 1,
227
- 'withdraw/history': 1,
228
- },
229
- 'post': {
230
- 'order': 0.2,
231
- 'withdraw': 1,
232
- 'balance/transfer': 1,
233
- 'balance/account/transfer': 1,
234
- },
235
- 'delete': {
236
- 'batch-order': 1,
237
- 'open-order': 1,
238
- 'order/{orderId}': 1,
239
- },
240
- },
241
- 'linear': {
242
- 'get': {
243
- 'future/trade/v1/entrust/plan-detail': 1,
244
- 'future/trade/v1/entrust/plan-list': 1,
245
- 'future/trade/v1/entrust/plan-list-history': 1,
246
- 'future/trade/v1/entrust/profit-detail': 1,
247
- 'future/trade/v1/entrust/profit-list': 1,
248
- 'future/trade/v1/order/detail': 1,
249
- 'future/trade/v1/order/list': 1,
250
- 'future/trade/v1/order/list-history': 1,
251
- 'future/trade/v1/order/trade-list': 1,
252
- 'future/user/v1/account/info': 1,
253
- 'future/user/v1/balance/bills': 1,
254
- 'future/user/v1/balance/detail': 1,
255
- 'future/user/v1/balance/funding-rate-list': 1,
256
- 'future/user/v1/balance/list': 1,
257
- 'future/user/v1/position/adl': 1,
258
- 'future/user/v1/position/list': 1,
259
- 'future/user/v1/user/collection/list': 1,
260
- 'future/user/v1/user/listen-key': 1,
261
- },
262
- 'post': {
263
- 'future/trade/v1/entrust/cancel-all-plan': 1,
264
- 'future/trade/v1/entrust/cancel-all-profit-stop': 1,
265
- 'future/trade/v1/entrust/cancel-plan': 1,
266
- 'future/trade/v1/entrust/cancel-profit-stop': 1,
267
- 'future/trade/v1/entrust/create-plan': 1,
268
- 'future/trade/v1/entrust/create-profit': 1,
269
- 'future/trade/v1/entrust/update-profit-stop': 1,
270
- 'future/trade/v1/order/cancel': 1,
271
- 'future/trade/v1/order/cancel-all': 1,
272
- 'future/trade/v1/order/create': 1,
273
- 'future/trade/v1/order/create-batch': 1,
274
- 'future/user/v1/account/open': 1,
275
- 'future/user/v1/position/adjust-leverage': 1,
276
- 'future/user/v1/position/auto-margin': 1,
277
- 'future/user/v1/position/close-all': 1,
278
- 'future/user/v1/position/margin': 1,
279
- 'future/user/v1/user/collection/add': 1,
280
- 'future/user/v1/user/collection/cancel': 1,
281
- },
282
- },
283
- 'inverse': {
284
- 'get': {
285
- 'future/trade/v1/entrust/plan-detail': 1,
286
- 'future/trade/v1/entrust/plan-list': 1,
287
- 'future/trade/v1/entrust/plan-list-history': 1,
288
- 'future/trade/v1/entrust/profit-detail': 1,
289
- 'future/trade/v1/entrust/profit-list': 1,
290
- 'future/trade/v1/order/detail': 1,
291
- 'future/trade/v1/order/list': 1,
292
- 'future/trade/v1/order/list-history': 1,
293
- 'future/trade/v1/order/trade-list': 1,
294
- 'future/user/v1/account/info': 1,
295
- 'future/user/v1/balance/bills': 1,
296
- 'future/user/v1/balance/detail': 1,
297
- 'future/user/v1/balance/funding-rate-list': 1,
298
- 'future/user/v1/balance/list': 1,
299
- 'future/user/v1/position/adl': 1,
300
- 'future/user/v1/position/list': 1,
301
- 'future/user/v1/user/collection/list': 1,
302
- 'future/user/v1/user/listen-key': 1,
303
- },
304
- 'post': {
305
- 'future/trade/v1/entrust/cancel-all-plan': 1,
306
- 'future/trade/v1/entrust/cancel-all-profit-stop': 1,
307
- 'future/trade/v1/entrust/cancel-plan': 1,
308
- 'future/trade/v1/entrust/cancel-profit-stop': 1,
309
- 'future/trade/v1/entrust/create-plan': 1,
310
- 'future/trade/v1/entrust/create-profit': 1,
311
- 'future/trade/v1/entrust/update-profit-stop': 1,
312
- 'future/trade/v1/order/cancel': 1,
313
- 'future/trade/v1/order/cancel-all': 1,
314
- 'future/trade/v1/order/create': 1,
315
- 'future/trade/v1/order/create-batch': 1,
316
- 'future/user/v1/account/open': 1,
317
- 'future/user/v1/position/adjust-leverage': 1,
318
- 'future/user/v1/position/auto-margin': 1,
319
- 'future/user/v1/position/close-all': 1,
320
- 'future/user/v1/position/margin': 1,
321
- 'future/user/v1/user/collection/add': 1,
322
- 'future/user/v1/user/collection/cancel': 1,
323
- },
324
- },
325
- 'user': {
326
- 'get': {
327
- 'user/account': 1,
328
- 'user/account/api-key': 1,
329
- },
330
- 'post': {
331
- 'user/account': 1,
332
- 'user/account/api-key': 1,
333
- },
334
- 'put': {
335
- 'user/account/api-key': 1,
336
- },
337
- 'delete': {
338
- 'user/account/{apikeyId}': 1,
339
- },
340
- },
341
- },
342
- },
343
- 'fees': {
344
- 'spot': {
345
- 'tierBased': True,
346
- 'percentage': True,
347
- 'maker': self.parse_number('0.002'),
348
- 'taker': self.parse_number('0.002'),
349
- 'tiers': {
350
- 'maker': [
351
- [self.parse_number('0'), self.parse_number('0.002')],
352
- [self.parse_number('5000'), self.parse_number('0.0018')],
353
- [self.parse_number('10000'), self.parse_number('0.0016')],
354
- [self.parse_number('20000'), self.parse_number('0.0014')],
355
- [self.parse_number('50000'), self.parse_number('0.0012')],
356
- [self.parse_number('150000'), self.parse_number('0.0010')],
357
- [self.parse_number('300000'), self.parse_number('0.0008')],
358
- [self.parse_number('600000'), self.parse_number('0.0007')],
359
- [self.parse_number('1200000'), self.parse_number('0.0006')],
360
- [self.parse_number('2500000'), self.parse_number('0.0005')],
361
- [self.parse_number('6000000'), self.parse_number('0.0004')],
362
- [self.parse_number('15000000'), self.parse_number('0.0003')],
363
- [self.parse_number('30000000'), self.parse_number('0.0002')],
364
- ],
365
- 'taker': [
366
- [self.parse_number('0'), self.parse_number('0.002')],
367
- [self.parse_number('5000'), self.parse_number('0.0018')],
368
- [self.parse_number('10000'), self.parse_number('0.0016')],
369
- [self.parse_number('20000'), self.parse_number('0.0014')],
370
- [self.parse_number('50000'), self.parse_number('0.0012')],
371
- [self.parse_number('150000'), self.parse_number('0.0010')],
372
- [self.parse_number('300000'), self.parse_number('0.0008')],
373
- [self.parse_number('600000'), self.parse_number('0.0007')],
374
- [self.parse_number('1200000'), self.parse_number('0.0006')],
375
- [self.parse_number('2500000'), self.parse_number('0.0005')],
376
- [self.parse_number('6000000'), self.parse_number('0.0004')],
377
- [self.parse_number('15000000'), self.parse_number('0.0003')],
378
- [self.parse_number('30000000'), self.parse_number('0.0002')],
379
- ],
380
- },
381
- },
382
- 'contract': {
383
- 'tierBased': True,
384
- 'percentage': True,
385
- 'maker': self.parse_number('0.0004'),
386
- 'taker': self.parse_number('0.0006'),
387
- 'tiers': {
388
- 'maker': [
389
- [self.parse_number('0'), self.parse_number('0.0004')],
390
- [self.parse_number('200000'), self.parse_number('0.00038')],
391
- [self.parse_number('1000000'), self.parse_number('0.00036')],
392
- [self.parse_number('5000000'), self.parse_number('0.00034')],
393
- [self.parse_number('10000000'), self.parse_number('0.00032')],
394
- [self.parse_number('15000000'), self.parse_number('0.00028')],
395
- [self.parse_number('30000000'), self.parse_number('0.00024')],
396
- [self.parse_number('50000000'), self.parse_number('0.0002')],
397
- [self.parse_number('100000000'), self.parse_number('0.00016')],
398
- [self.parse_number('300000000'), self.parse_number('0.00012')],
399
- [self.parse_number('500000000'), self.parse_number('0.00008')],
400
- ],
401
- 'taker': [
402
- [self.parse_number('0'), self.parse_number('0.0006')],
403
- [self.parse_number('200000'), self.parse_number('0.000588')],
404
- [self.parse_number('1000000'), self.parse_number('0.00057')],
405
- [self.parse_number('5000000'), self.parse_number('0.00054')],
406
- [self.parse_number('10000000'), self.parse_number('0.00051')],
407
- [self.parse_number('15000000'), self.parse_number('0.00048')],
408
- [self.parse_number('30000000'), self.parse_number('0.00045')],
409
- [self.parse_number('50000000'), self.parse_number('0.00045')],
410
- [self.parse_number('100000000'), self.parse_number('0.00036')],
411
- [self.parse_number('300000000'), self.parse_number('0.00033')],
412
- [self.parse_number('500000000'), self.parse_number('0.0003')],
413
- ],
414
- },
415
- },
416
- },
417
- 'exceptions': {
418
- 'exact': {
419
- '400': NetworkError, # {"returnCode":1,"msgInfo":"failure","error":{"code":"400","msg":"Connection refused: /10.0.26.71:8080"},"result":null}
420
- '404': ExchangeError, # interface does not exist
421
- '429': RateLimitExceeded, # The request is too frequent, please control the request rate according to the speed limit requirement
422
- '500': ExchangeError, # Service exception
423
- '502': ExchangeError, # Gateway exception
424
- '503': OnMaintenance, # Service unavailable, please try again later
425
- 'AUTH_001': AuthenticationError, # missing request header xt-validate-appkey
426
- 'AUTH_002': AuthenticationError, # missing request header xt-validate-timestamp
427
- 'AUTH_003': AuthenticationError, # missing request header xt-validate-recvwindow
428
- 'AUTH_004': AuthenticationError, # bad request header xt-validate-recvwindow
429
- 'AUTH_005': AuthenticationError, # missing request header xt-validate-algorithms
430
- 'AUTH_006': AuthenticationError, # bad request header xt-validate-algorithms
431
- 'AUTH_007': AuthenticationError, # missing request header xt-validate-signature
432
- 'AUTH_101': AuthenticationError, # ApiKey does not exist
433
- 'AUTH_102': AuthenticationError, # ApiKey is not activated
434
- 'AUTH_103': AuthenticationError, # Signature error, {"rc":1,"mc":"AUTH_103","ma":[],"result":null}
435
- 'AUTH_104': AuthenticationError, # Unbound IP request
436
- 'AUTH_105': AuthenticationError, # outdated message
437
- 'AUTH_106': PermissionDenied, # Exceeded apikey permission
438
- 'SYMBOL_001': BadSymbol, # Symbol not exist
439
- 'SYMBOL_002': BadSymbol, # Symbol offline
440
- 'SYMBOL_003': BadSymbol, # Symbol suspend trading
441
- 'SYMBOL_004': BadSymbol, # Symbol country disallow trading
442
- 'SYMBOL_005': BadSymbol, # The symbol does not support trading via API
443
- 'ORDER_001': InvalidOrder, # Platform rejection
444
- 'ORDER_002': InsufficientFunds, # insufficient funds
445
- 'ORDER_003': InvalidOrder, # Trading Pair Suspended
446
- 'ORDER_004': InvalidOrder, # no transaction
447
- 'ORDER_005': InvalidOrder, # Order not exist
448
- 'ORDER_006': InvalidOrder, # Too many open orders
449
- 'ORDER_007': PermissionDenied, # The sub-account has no transaction authority
450
- 'ORDER_F0101': InvalidOrder, # Trigger Price Filter - Min
451
- 'ORDER_F0102': InvalidOrder, # Trigger Price Filter - Max
452
- 'ORDER_F0103': InvalidOrder, # Trigger Price Filter - Step Value
453
- 'ORDER_F0201': InvalidOrder, # Trigger Quantity Filter - Min
454
- 'ORDER_F0202': InvalidOrder, # Trigger Quantity Filter - Max
455
- 'ORDER_F0203': InvalidOrder, # Trigger Quantity Filter - Step Value
456
- 'ORDER_F0301': InvalidOrder, # Trigger QUOTE_QTY Filter - Min Value
457
- 'ORDER_F0401': InvalidOrder, # Trigger PROTECTION_ONLINE Filter
458
- 'ORDER_F0501': InvalidOrder, # Trigger PROTECTION_LIMIT Filter - Buy Max Deviation
459
- 'ORDER_F0502': InvalidOrder, # Trigger PROTECTION_LIMIT Filter - Sell Max Deviation
460
- 'ORDER_F0601': InvalidOrder, # Trigger PROTECTION_MARKET Filter
461
- 'COMMON_001': ExchangeError, # The user does not exist
462
- 'COMMON_002': ExchangeError, # System busy, please try it later
463
- 'COMMON_003': BadRequest, # Operation failed, please try it later
464
- 'CURRENCY_001': BadRequest, # Information of currency is abnormal
465
- 'DEPOSIT_001': BadRequest, # Deposit is not open
466
- 'DEPOSIT_002': PermissionDenied, # The current account security level is low, please bind any two security verifications in mobile phone/email/Google Authenticator before deposit
467
- 'DEPOSIT_003': BadRequest, # The format of address is incorrect, please enter again
468
- 'DEPOSIT_004': BadRequest, # The address is already exists, please enter again
469
- 'DEPOSIT_005': BadRequest, # Can not find the address of offline wallet
470
- 'DEPOSIT_006': BadRequest, # No deposit address, please try it later
471
- 'DEPOSIT_007': BadRequest, # Address is being generated, please try it later
472
- 'DEPOSIT_008': BadRequest, # Deposit is not available
473
- 'WITHDRAW_001': BadRequest, # Withdraw is not open
474
- 'WITHDRAW_002': BadRequest, # The withdrawal address is invalid
475
- 'WITHDRAW_003': PermissionDenied, # The current account security level is low, please bind any two security verifications in mobile phone/email/Google Authenticator before withdraw
476
- 'WITHDRAW_004': BadRequest, # The withdrawal address is not added
477
- 'WITHDRAW_005': BadRequest, # The withdrawal address cannot be empty
478
- 'WITHDRAW_006': BadRequest, # Memo cannot be empty
479
- 'WITHDRAW_008': PermissionDenied, # Risk control is triggered, withdraw of self currency is not currently supported
480
- 'WITHDRAW_009': PermissionDenied, # Withdraw failed, some hasattr(self, assets) withdraw are restricted by T+1 withdraw
481
- 'WITHDRAW_010': BadRequest, # The precision of withdrawal is invalid
482
- 'WITHDRAW_011': InsufficientFunds, # free balance is not enough
483
- 'WITHDRAW_012': PermissionDenied, # Withdraw failed, your remaining withdrawal limit today is not enough
484
- 'WITHDRAW_013': PermissionDenied, # Withdraw failed, your remaining withdrawal limit today is not enough, the withdrawal amount can be increased by completing a higher level of real-name authentication
485
- 'WITHDRAW_014': BadRequest, # This withdrawal address cannot be used in the internal transfer function, please cancel the internal transfer function before submitting
486
- 'WITHDRAW_015': BadRequest, # The withdrawal amount is not enough to deduct the handling fee
487
- 'WITHDRAW_016': BadRequest, # This withdrawal address is already exists
488
- 'WITHDRAW_017': BadRequest, # This withdrawal has been processed and cannot be canceled
489
- 'WITHDRAW_018': BadRequest, # Memo must be a number
490
- 'WITHDRAW_019': BadRequest, # Memo is incorrect, please enter again
491
- 'WITHDRAW_020': PermissionDenied, # Your withdrawal amount has reached the upper limit for today, please try it tomorrow
492
- 'WITHDRAW_021': PermissionDenied, # Your withdrawal amount has reached the upper limit for today, you can only withdraw up to {0} self time
493
- 'WITHDRAW_022': BadRequest, # Withdrawal amount must be greater than {0}
494
- 'WITHDRAW_023': BadRequest, # Withdrawal amount must be less than {0}
495
- 'WITHDRAW_024': BadRequest, # Withdraw is not supported
496
- 'WITHDRAW_025': BadRequest, # Please create a FIO address in the deposit page
497
- 'FUND_001': BadRequest, # Duplicate request(a bizId can only be requested once)
498
- 'FUND_002': InsufficientFunds, # Insufficient account balance
499
- 'FUND_003': BadRequest, # Transfer operations are not supported(for example, sub-accounts do not support financial transfers)
500
- 'FUND_004': ExchangeError, # Unfreeze failed
501
- 'FUND_005': PermissionDenied, # Transfer prohibited
502
- 'FUND_014': BadRequest, # The transfer-in account id and transfer-out account ID cannot be the same
503
- 'FUND_015': BadRequest, # From and to business types cannot be the same
504
- 'FUND_016': BadRequest, # Leverage transfer, symbol cannot be empty
505
- 'FUND_017': BadRequest, # Parameter error
506
- 'FUND_018': BadRequest, # Invalid freeze record
507
- 'FUND_019': BadRequest, # Freeze users not equal
508
- 'FUND_020': BadRequest, # Freeze currency are not equal
509
- 'FUND_021': BadRequest, # Operation not supported
510
- 'FUND_022': BadRequest, # Freeze record does not exist
511
- 'FUND_044': BadRequest, # The maximum length of the amount is 113 and cannot exceed the limit
512
- 'TRANSFER_001': BadRequest, # Duplicate request(a bizId can only be requested once)
513
- 'TRANSFER_002': InsufficientFunds, # Insufficient account balance
514
- 'TRANSFER_003': BadRequest, # User not registered
515
- 'TRANSFER_004': PermissionDenied, # The currency is not allowed to be transferred
516
- 'TRANSFER_005': PermissionDenied, # The user’s currency is not allowed to be transferred
517
- 'TRANSFER_006': PermissionDenied, # Transfer prohibited
518
- 'TRANSFER_007': RequestTimeout, # Request timed out
519
- 'TRANSFER_008': BadRequest, # Transferring to a leveraged account is abnormal
520
- 'TRANSFER_009': BadRequest, # Departing from a leveraged account is abnormal
521
- 'TRANSFER_010': PermissionDenied, # Leverage cleared, transfer prohibited
522
- 'TRANSFER_011': PermissionDenied, # Leverage with borrowing, transfer prohibited
523
- 'TRANSFER_012': PermissionDenied, # Currency transfer prohibited
524
- 'symbol_not_support_trading_via_api': BadSymbol, # {"returnCode":1,"msgInfo":"failure","error":{"code":"symbol_not_support_trading_via_api","msg":"The symbol does not support trading via API"},"result":null}
525
- 'open_order_min_nominal_value_limit': InvalidOrder, # {"returnCode":1,"msgInfo":"failure","error":{"code":"open_order_min_nominal_value_limit","msg":"Exceeds the minimum notional value of a single order"},"result":null}
526
- },
527
- 'broad': {
528
- 'The symbol does not support trading via API': BadSymbol, # {"returnCode":1,"msgInfo":"failure","error":{"code":"symbol_not_support_trading_via_api","msg":"The symbol does not support trading via API"},"result":null}
529
- 'Exceeds the minimum notional value of a single order': InvalidOrder, # {"returnCode":1,"msgInfo":"failure","error":{"code":"open_order_min_nominal_value_limit","msg":"Exceeds the minimum notional value of a single order"},"result":null}
530
- },
531
- },
532
- 'timeframes': {
533
- '1m': '1m',
534
- '5m': '5m',
535
- '15m': '15m',
536
- '30m': '30m',
537
- '1h': '1h', # spot only
538
- '2h': '2h', # spot only
539
- '4h': '4h',
540
- '6h': '6h', # spot only
541
- '8h': '8h', # spot only
542
- '1d': '1d',
543
- '3d': '3d', # spot only
544
- '1w': '1w',
545
- '1M': '1M', # spot only
546
- },
547
- 'commonCurrencies': {},
548
- 'options': {
549
- 'adjustForTimeDifference': False,
550
- 'timeDifference': 0,
551
- 'accountsById': {
552
- 'spot': 'SPOT',
553
- 'leverage': 'LEVER',
554
- 'finance': 'FINANCE',
555
- 'swap': 'FUTURES_U',
556
- 'future': 'FUTURES_U',
557
- 'linear': 'FUTURES_U',
558
- 'inverse': 'FUTURES_C',
559
- },
560
- 'networks': {
561
- 'ERC20': 'Ethereum',
562
- 'TRC20': 'Tron',
563
- 'BEP20': 'BNB Smart Chain',
564
- 'BEP2': 'BNB-BEP2',
565
- 'ETH': 'Ethereum',
566
- 'TRON': 'Tron',
567
- 'BNB': 'BNB Smart Chain',
568
- 'AVAX': 'AVAX C-Chain',
569
- 'GAL': 'GAL(FT)',
570
- 'ALEO': 'ALEO(IOU)',
571
- 'BTC': 'Bitcoin',
572
- 'XT': 'XT Smart Chain',
573
- 'ETC': 'Ethereum Classic',
574
- 'MATIC': 'Polygon',
575
- 'LTC': 'Litecoin',
576
- 'BTS': 'BitShares',
577
- 'XRP': 'Ripple',
578
- 'XLM': 'Stellar Network',
579
- 'ADA': 'Cardano',
580
- 'XWC': 'XWC-XWC',
581
- 'DOGE': 'dogecoin',
582
- 'DCR': 'Decred',
583
- 'SC': 'Siacoin',
584
- 'XTZ': 'Tezos',
585
- 'ZEC': 'Zcash',
586
- 'XMR': 'Monero',
587
- 'LSK': 'Lisk',
588
- 'ATOM': 'Cosmos',
589
- 'ONT': 'Ontology',
590
- 'ALGO': 'Algorand',
591
- 'SOL': 'SOL-SOL',
592
- 'DOT': 'Polkadot',
593
- 'ZEN': 'Horizen',
594
- 'FIL': 'Filecoin',
595
- 'CHZ': 'chz',
596
- 'ICP': 'Internet Computer',
597
- 'KSM': 'Kusama',
598
- 'LUNA': 'Terra',
599
- 'THETA': 'Theta Token',
600
- 'FTM': 'Fantom',
601
- 'VET': 'VeChain',
602
- 'NEAR': 'NEAR Protocol',
603
- 'ONE': 'Harmony',
604
- 'KLAY': 'Klaytn',
605
- 'AR': 'Arweave',
606
- 'CELT': 'OKT',
607
- 'EGLD': 'Elrond eGold',
608
- 'CRO': 'CRO-CRONOS',
609
- 'BCH': 'Bitcoin Cash',
610
- 'GLMR': 'Moonbeam',
611
- 'LOOP': 'LOOP-LRC',
612
- 'REI': 'REI Network',
613
- 'ASTR': 'Astar Network',
614
- 'OP': 'OPT',
615
- 'MMT': 'MMT-MMT',
616
- 'TBC': 'TBC-TBC',
617
- 'OMAX': 'OMAX-OMAX CHAIN',
618
- 'GMMT': 'GMMT chain',
619
- 'ZIL': 'Zilliqa',
620
- },
621
- 'networksById': {
622
- 'Ethereum': 'ERC20',
623
- 'Tron': 'TRC20',
624
- 'BNB Smart Chain': 'BEP20',
625
- 'BNB-BEP2': 'BEP2',
626
- 'Bitcoin': 'BTC',
627
- 'XT Smart Chain': 'XT',
628
- 'Ethereum Classic': 'ETC',
629
- 'Polygon': 'MATIC',
630
- 'Litecoin': 'LTC',
631
- 'BitShares': 'BTS',
632
- 'Ripple': 'XRP',
633
- 'Stellar Network': 'XLM',
634
- 'Cardano': 'ADA',
635
- 'XWC-XWC': 'XWC',
636
- 'dogecoin': 'DOGE',
637
- 'Decred': 'DCR',
638
- 'Siacoin': 'SC',
639
- 'Tezos': 'XTZ',
640
- 'Zcash': 'ZEC',
641
- 'Monero': 'XMR',
642
- 'Lisk': 'LSK',
643
- 'Cosmos': 'ATOM',
644
- 'Ontology': 'ONT',
645
- 'Algorand': 'ALGO',
646
- 'SOL-SOL': 'SOL',
647
- 'Polkadot': 'DOT',
648
- 'Horizen': 'ZEN',
649
- 'Filecoin': 'FIL',
650
- 'chz': 'CHZ',
651
- 'Internet Computer': 'ICP',
652
- 'Kusama': 'KSM',
653
- 'Terra': 'LUNA',
654
- 'Theta Token': 'THETA',
655
- 'Fantom': 'FTM',
656
- 'VeChain': 'VET',
657
- 'AVAX C-Chain': 'AVAX',
658
- 'NEAR Protocol': 'NEAR',
659
- 'Harmony': 'ONE',
660
- 'Klaytn': 'KLAY',
661
- 'Arweave': 'AR',
662
- 'OKT': 'CELT',
663
- 'Elrond eGold': 'EGLD',
664
- 'CRO-CRONOS': 'CRO',
665
- 'Bitcoin Cash': 'BCH',
666
- 'Moonbeam': 'GLMR',
667
- 'LOOP-LRC': 'LOOP',
668
- 'REI Network': 'REI',
669
- 'Astar Network': 'ASTR',
670
- 'GAL(FT)': 'GAL',
671
- 'ALEO(IOU)': 'ALEO',
672
- 'OPT': 'OP',
673
- 'MMT-MMT': 'MMT',
674
- 'TBC-TBC': 'TBC',
675
- 'OMAX-OMAX CHAIN': 'OMAX',
676
- 'GMMT chain': 'GMMT',
677
- 'Zilliqa': 'ZIL',
678
- },
679
- 'createMarketBuyOrderRequiresPrice': True,
680
- 'recvWindow': '5000', # in milliseconds, spot only
681
- },
682
- })
683
-
684
- def nonce(self):
685
- return self.milliseconds() - self.options['timeDifference']
686
-
687
- def fetch_time(self, params={}):
688
- """
689
- fetches the current integer timestamp in milliseconds from the xt server
690
- see https://doc.xt.com/#market1serverInfo
691
- :param dict params: extra parameters specific to the xt api endpoint
692
- :returns int: the current integer timestamp in milliseconds from the xt server
693
- """
694
- response = self.publicSpotGetTime(params)
695
- #
696
- # {
697
- # "rc": 0,
698
- # "mc": "SUCCESS",
699
- # "ma": [],
700
- # "result": {
701
- # "serverTime": 1677823301643
702
- # }
703
- # }
704
- #
705
- data = self.safe_value(response, 'result')
706
- return self.safe_integer(data, 'serverTime')
707
-
708
- def fetch_currencies(self, params={}):
709
- """
710
- fetches all available currencies on an exchange
711
- see https://doc.xt.com/#deposit_withdrawalsupportedCurrenciesGet
712
- :param dict params: extra parameters specific to the xt api endpoint
713
- :returns dict: an associative dictionary of currencies
714
- """
715
- promisesRaw = [self.publicSpotGetWalletSupportCurrency(params), self.publicSpotGetCurrencies(params)]
716
- chainsResponse, currenciesResponse = promisesRaw
717
- #
718
- # currencies
719
- #
720
- # {
721
- # "time": "1686626116145",
722
- # "version": "5dbbb2f2527c22b2b2e3b47187ef13d1",
723
- # "currencies": [
724
- # {
725
- # "id": "2",
726
- # "currency": "btc",
727
- # "fullName": "Bitcoin",
728
- # "logo": "https://a.static-global.com/1/currency/btc.png",
729
- # "cmcLink": "https://coinmarketcap.com/currencies/bitcoin/",
730
- # "weight": "99999",
731
- # "maxPrecision": "10",
732
- # "depositStatus": "1",
733
- # "withdrawStatus": "1",
734
- # "convertEnabled": "1",
735
- # "transferEnabled": "1",
736
- # "isChainExist": "1",
737
- # "plates": [152]
738
- # },
739
- # ],
740
- # }
741
- #
742
- #
743
- # chains
744
- #
745
- # {
746
- # "rc": 0,
747
- # "mc": "SUCCESS",
748
- # "ma": [],
749
- # "result": [
750
- # {
751
- # "currency": "btc",
752
- # "supportChains": [
753
- # {
754
- # "chain": "Bitcoin",
755
- # "depositEnabled": True,
756
- # "withdrawEnabled": True,
757
- # "withdrawFeeAmount": 0.0009,
758
- # "withdrawMinAmount": 0.0005,
759
- # "depositFeeRate": 0
760
- # },
761
- # ]
762
- # },
763
- # ]
764
- # }
765
- #
766
- # note: individual network's full data is available on per-currency endpoint: https://www.xt.com/sapi/v4/balance/public/currency/11
767
- #
768
- chainsData = self.safe_value(chainsResponse, 'result', [])
769
- currenciesResult = self.safe_value(currenciesResponse, 'result', [])
770
- currenciesData = self.safe_value(currenciesResult, 'currencies', [])
771
- chainsDataIndexed = self.index_by(chainsData, 'currency')
772
- result = {}
773
- for i in range(0, len(currenciesData)):
774
- entry = currenciesData[i]
775
- currencyId = self.safe_string(entry, 'currency')
776
- code = self.safe_currency_code(currencyId)
777
- minPrecision = self.parse_number(self.parse_precision(self.safe_string(entry, 'maxPrecision')))
778
- networkEntry = self.safe_value(chainsDataIndexed, currencyId, {})
779
- rawNetworks = self.safe_value(networkEntry, 'supportChains', [])
780
- networks = {}
781
- minWithdrawString = None
782
- minWithdrawFeeString = None
783
- active = False
784
- deposit = False
785
- withdraw = False
786
- for j in range(0, len(rawNetworks)):
787
- rawNetwork = rawNetworks[j]
788
- networkId = self.safe_string(rawNetwork, 'chain')
789
- network = self.network_id_to_code(networkId)
790
- depositEnabled = self.safe_value(rawNetwork, 'depositEnabled')
791
- deposit = depositEnabled if (depositEnabled) else deposit
792
- withdrawEnabled = self.safe_value(rawNetwork, 'withdrawEnabled')
793
- withdraw = withdrawEnabled if (withdrawEnabled) else withdraw
794
- networkActive = depositEnabled and withdrawEnabled
795
- active = networkActive if (networkActive) else active
796
- withdrawFeeString = self.safe_string(rawNetwork, 'withdrawFeeAmount')
797
- if withdrawFeeString is not None:
798
- minWithdrawFeeString = withdrawFeeString if (minWithdrawFeeString is None) else Precise.string_min(withdrawFeeString, minWithdrawFeeString)
799
- minNetworkWithdrawString = self.safe_string(rawNetwork, 'withdrawMinAmount')
800
- if minNetworkWithdrawString is not None:
801
- minWithdrawString = minNetworkWithdrawString if (minWithdrawString is None) else Precise.string_min(minNetworkWithdrawString, minWithdrawString)
802
- networks[network] = {
803
- 'info': rawNetwork,
804
- 'id': networkId,
805
- 'network': network,
806
- 'name': None,
807
- 'active': networkActive,
808
- 'fee': self.parse_number(withdrawFeeString),
809
- 'precision': minPrecision,
810
- 'deposit': depositEnabled,
811
- 'withdraw': withdrawEnabled,
812
- 'limits': {
813
- 'amount': {
814
- 'min': None,
815
- 'max': None,
816
- },
817
- 'withdraw': {
818
- 'min': self.parse_number(minNetworkWithdrawString),
819
- 'max': None,
820
- },
821
- 'deposit': {
822
- 'min': None,
823
- 'max': None,
824
- },
825
- },
826
- }
827
- result[code] = {
828
- 'info': entry,
829
- 'id': currencyId,
830
- 'code': code,
831
- 'name': self.safe_string(entry, 'fullName'),
832
- 'active': active,
833
- 'fee': self.parse_number(minWithdrawFeeString),
834
- 'precision': None,
835
- 'deposit': deposit,
836
- 'withdraw': withdraw,
837
- 'networks': networks,
838
- 'limits': {
839
- 'amount': {
840
- 'min': None,
841
- 'max': None,
842
- },
843
- 'withdraw': {
844
- 'min': self.parse_number(minWithdrawString),
845
- 'max': None,
846
- },
847
- 'deposit': {
848
- 'min': None,
849
- 'max': None,
850
- },
851
- },
852
- }
853
- return result
854
-
855
- def fetch_markets(self, params={}):
856
- """
857
- retrieves data on all markets for xt
858
- see https://doc.xt.com/#market2symbol
859
- see https://doc.xt.com/#futures_quotesgetSymbols
860
- :param dict params: extra parameters specific to the xt api endpoint
861
- :returns [dict]: an array of objects representing market data
862
- """
863
- if self.options['adjustForTimeDifference']:
864
- self.load_time_difference()
865
- promisesUnresolved = [
866
- self.fetch_spot_markets(params),
867
- self.fetch_swap_and_future_markets(params),
868
- ]
869
- promises = promisesUnresolved
870
- spotMarkets = promises[0]
871
- swapAndFutureMarkets = promises[1]
872
- return self.array_concat(spotMarkets, swapAndFutureMarkets)
873
-
874
- def fetch_spot_markets(self, params={}):
875
- response = self.publicSpotGetSymbol(params)
876
- #
877
- # {
878
- # "rc": 0,
879
- # "mc": "SUCCESS",
880
- # "ma": [],
881
- # "result": {
882
- # "time": 1677881368812,
883
- # "version": "abb101d1543e54bee40687b135411ba0",
884
- # "symbols": [
885
- # {
886
- # "id": 640,
887
- # "symbol": "xt_usdt",
888
- # "state": "ONLINE",
889
- # "stateTime": 1554048000000,
890
- # "tradingEnabled": True,
891
- # "openapiEnabled": True,
892
- # "nextStateTime": null,
893
- # "nextState": null,
894
- # "depthMergePrecision": 5,
895
- # "baseCurrency": "xt",
896
- # "baseCurrencyPrecision": 8,
897
- # "baseCurrencyId": 128,
898
- # "quoteCurrency": "usdt",
899
- # "quoteCurrencyPrecision": 8,
900
- # "quoteCurrencyId": 11,
901
- # "pricePrecision": 4,
902
- # "quantityPrecision": 2,
903
- # "orderTypes": ["LIMIT","MARKET"],
904
- # "timeInForces": ["GTC","IOC"],
905
- # "displayWeight": 10002,
906
- # "displayLevel": "FULL",
907
- # "plates": [],
908
- # "filters":[
909
- # {
910
- # "filter": "QUOTE_QTY",
911
- # "min": "1"
912
- # },
913
- # {
914
- # "filter": "PROTECTION_LIMIT",
915
- # "buyMaxDeviation": "0.8",
916
- # "sellMaxDeviation": "4"
917
- # },
918
- # {
919
- # "filter": "PROTECTION_MARKET",
920
- # "maxDeviation": "0.02"
921
- # }
922
- # ]
923
- # },
924
- # ]
925
- # }
926
- # }
927
- #
928
- data = self.safe_value(response, 'result', {})
929
- symbols = self.safe_value(data, 'symbols', [])
930
- return self.parse_markets(symbols)
931
-
932
- def fetch_swap_and_future_markets(self, params={}):
933
- markets = [self.publicLinearGetFutureMarketV1PublicSymbolList(params), self.publicInverseGetFutureMarketV1PublicSymbolList(params)]
934
- #
935
- # {
936
- # "returnCode": 0,
937
- # "msgInfo": "success",
938
- # "error": null,
939
- # "result": [
940
- # {
941
- # "id": 52,
942
- # "symbolGroupId": 71,
943
- # "symbol": "xt_usdt",
944
- # "pair": "xt_usdt",
945
- # "contractType": "PERPETUAL",
946
- # "productType": "perpetual",
947
- # "predictEventType": null,
948
- # "underlyingType": "U_BASED",
949
- # "contractSize": "1",
950
- # "tradeSwitch": True,
951
- # "isDisplay": True,
952
- # "isOpenApi": False,
953
- # "state": 0,
954
- # "initLeverage": 20,
955
- # "initPositionType": "CROSSED",
956
- # "baseCoin": "xt",
957
- # "quoteCoin": "usdt",
958
- # "baseCoinPrecision": 8,
959
- # "baseCoinDisplayPrecision": 4,
960
- # "quoteCoinPrecision": 8,
961
- # "quoteCoinDisplayPrecision": 4,
962
- # "quantityPrecision": 0,
963
- # "pricePrecision": 4,
964
- # "supportOrderType": "LIMIT,MARKET",
965
- # "supportTimeInForce": "GTC,FOK,IOC,GTX",
966
- # "supportEntrustType": "TAKE_PROFIT,STOP,TAKE_PROFIT_MARKET,STOP_MARKET,TRAILING_STOP_MARKET",
967
- # "supportPositionType": "CROSSED,ISOLATED",
968
- # "minQty": "1",
969
- # "minNotional": "5",
970
- # "maxNotional": "20000000",
971
- # "multiplierDown": "0.1",
972
- # "multiplierUp": "0.1",
973
- # "maxOpenOrders": 200,
974
- # "maxEntrusts": 200,
975
- # "makerFee": "0.0004",
976
- # "takerFee": "0.0006",
977
- # "liquidationFee": "0.01",
978
- # "marketTakeBound": "0.1",
979
- # "depthPrecisionMerge": 5,
980
- # "labels": ["HOT"],
981
- # "onboardDate": 1657101601000,
982
- # "enName": "XTUSDT ",
983
- # "cnName": "XTUSDT",
984
- # "minStepPrice": "0.0001",
985
- # "minPrice": null,
986
- # "maxPrice": null,
987
- # "deliveryDate": 1669879634000,
988
- # "deliveryPrice": null,
989
- # "deliveryCompletion": False,
990
- # "cnDesc": null,
991
- # "enDesc": null
992
- # },
993
- # ]
994
- # }
995
- #
996
- swapAndFutureMarkets = self.array_concat(self.safe_value(markets[0], 'result', []), self.safe_value(markets[1], 'result', []))
997
- return self.parse_markets(swapAndFutureMarkets)
998
-
999
- def parse_markets(self, markets):
1000
- result = []
1001
- for i in range(0, len(markets)):
1002
- result.append(self.parse_market(markets[i]))
1003
- return result
1004
-
1005
- def parse_market(self, market):
1006
- #
1007
- # spot
1008
- #
1009
- # {
1010
- # "id": 640,
1011
- # "symbol": "xt_usdt",
1012
- # "state": "ONLINE",
1013
- # "stateTime": 1554048000000,
1014
- # "tradingEnabled": True,
1015
- # "openapiEnabled": True,
1016
- # "nextStateTime": null,
1017
- # "nextState": null,
1018
- # "depthMergePrecision": 5,
1019
- # "baseCurrency": "xt",
1020
- # "baseCurrencyPrecision": 8,
1021
- # "baseCurrencyId": 128,
1022
- # "quoteCurrency": "usdt",
1023
- # "quoteCurrencyPrecision": 8,
1024
- # "quoteCurrencyId": 11,
1025
- # "pricePrecision": 4,
1026
- # "quantityPrecision": 2,
1027
- # "orderTypes": ["LIMIT","MARKET"],
1028
- # "timeInForces": ["GTC","IOC"],
1029
- # "displayWeight": 10002,
1030
- # "displayLevel": "FULL",
1031
- # "plates": [],
1032
- # "filters":[
1033
- # {
1034
- # "filter": "QUOTE_QTY",
1035
- # "min": "1"
1036
- # },
1037
- # {
1038
- # "filter": "PRICE",
1039
- # "min": null,
1040
- # "max": null,
1041
- # "tickSize": null
1042
- # },
1043
- # {
1044
- # "filter": "QUANTITY",
1045
- # "min": null,
1046
- # "max": null,
1047
- # "tickSize": null
1048
- # },
1049
- # {
1050
- # "filter": "PROTECTION_LIMIT",
1051
- # "buyMaxDeviation": "0.8",
1052
- # "sellMaxDeviation": "4"
1053
- # },
1054
- # {
1055
- # "filter": "PROTECTION_MARKET",
1056
- # "maxDeviation": "0.02"
1057
- # },
1058
- # {
1059
- # "filter": "PROTECTION_ONLINE",
1060
- # "durationSeconds": "300",
1061
- # "maxPriceMultiple": "5"
1062
- # },
1063
- # ]
1064
- # }
1065
- #
1066
- # swap and future
1067
- #
1068
- # {
1069
- # "id": 52,
1070
- # "symbolGroupId": 71,
1071
- # "symbol": "xt_usdt",
1072
- # "pair": "xt_usdt",
1073
- # "contractType": "PERPETUAL",
1074
- # "productType": "perpetual",
1075
- # "predictEventType": null,
1076
- # "underlyingType": "U_BASED",
1077
- # "contractSize": "1",
1078
- # "tradeSwitch": True,
1079
- # "isDisplay": True,
1080
- # "isOpenApi": False,
1081
- # "state": 0,
1082
- # "initLeverage": 20,
1083
- # "initPositionType": "CROSSED",
1084
- # "baseCoin": "xt",
1085
- # "quoteCoin": "usdt",
1086
- # "baseCoinPrecision": 8,
1087
- # "baseCoinDisplayPrecision": 4,
1088
- # "quoteCoinPrecision": 8,
1089
- # "quoteCoinDisplayPrecision": 4,
1090
- # "quantityPrecision": 0,
1091
- # "pricePrecision": 4,
1092
- # "supportOrderType": "LIMIT,MARKET",
1093
- # "supportTimeInForce": "GTC,FOK,IOC,GTX",
1094
- # "supportEntrustType": "TAKE_PROFIT,STOP,TAKE_PROFIT_MARKET,STOP_MARKET,TRAILING_STOP_MARKET",
1095
- # "supportPositionType": "CROSSED,ISOLATED",
1096
- # "minQty": "1",
1097
- # "minNotional": "5",
1098
- # "maxNotional": "20000000",
1099
- # "multiplierDown": "0.1",
1100
- # "multiplierUp": "0.1",
1101
- # "maxOpenOrders": 200,
1102
- # "maxEntrusts": 200,
1103
- # "makerFee": "0.0004",
1104
- # "takerFee": "0.0006",
1105
- # "liquidationFee": "0.01",
1106
- # "marketTakeBound": "0.1",
1107
- # "depthPrecisionMerge": 5,
1108
- # "labels": ["HOT"],
1109
- # "onboardDate": 1657101601000,
1110
- # "enName": "XTUSDT ",
1111
- # "cnName": "XTUSDT",
1112
- # "minStepPrice": "0.0001",
1113
- # "minPrice": null,
1114
- # "maxPrice": null,
1115
- # "deliveryDate": 1669879634000,
1116
- # "deliveryPrice": null,
1117
- # "deliveryCompletion": False,
1118
- # "cnDesc": null,
1119
- # "enDesc": null
1120
- # }
1121
- #
1122
- id = self.safe_string(market, 'symbol')
1123
- baseId = self.safe_string_2(market, 'baseCurrency', 'baseCoin')
1124
- quoteId = self.safe_string_2(market, 'quoteCurrency', 'quoteCoin')
1125
- base = self.safe_currency_code(baseId)
1126
- quote = self.safe_currency_code(quoteId)
1127
- state = self.safe_string(market, 'state')
1128
- symbol = base + '/' + quote
1129
- filters = self.safe_value(market, 'filters', [])
1130
- minAmount = None
1131
- maxAmount = None
1132
- minCost = None
1133
- maxCost = None
1134
- minPrice = None
1135
- maxPrice = None
1136
- for i in range(0, len(filters)):
1137
- entry = filters[i]
1138
- filter = self.safe_string(entry, 'filter')
1139
- if filter == 'QUANTITY':
1140
- minAmount = self.safe_number(entry, 'min')
1141
- maxAmount = self.safe_number(entry, 'max')
1142
- if filter == 'QUOTE_QTY':
1143
- minCost = self.safe_number(entry, 'min')
1144
- if filter == 'PRICE':
1145
- minPrice = self.safe_number(entry, 'min')
1146
- maxPrice = self.safe_number(entry, 'max')
1147
- underlyingType = self.safe_string(market, 'underlyingType')
1148
- linear = None
1149
- inverse = None
1150
- settleId = None
1151
- settle = None
1152
- expiry = None
1153
- future = False
1154
- swap = False
1155
- contract = False
1156
- spot = True
1157
- type = 'spot'
1158
- if underlyingType == 'U_BASED':
1159
- symbol = symbol + ':' + quote
1160
- settleId = baseId
1161
- settle = quote
1162
- linear = True
1163
- inverse = False
1164
- elif underlyingType == 'COIN_BASED':
1165
- symbol = symbol + ':' + base
1166
- settleId = baseId
1167
- settle = base
1168
- linear = False
1169
- inverse = True
1170
- if underlyingType is not None:
1171
- expiry = self.safe_integer(market, 'deliveryDate')
1172
- productType = self.safe_string(market, 'productType')
1173
- if productType != 'perpetual':
1174
- symbol = symbol + '-' + self.yymmdd(expiry)
1175
- type = 'future'
1176
- future = True
1177
- else:
1178
- type = 'swap'
1179
- swap = True
1180
- minAmount = self.safe_number(market, 'minQty')
1181
- minCost = self.safe_number(market, 'minNotional')
1182
- maxCost = self.safe_number(market, 'maxNotional')
1183
- minPrice = self.safe_number(market, 'minPrice')
1184
- maxPrice = self.safe_number(market, 'maxPrice')
1185
- contract = True
1186
- spot = False
1187
- isActive = False
1188
- if contract:
1189
- isActive = self.safe_value(market, 'isOpenApi', False)
1190
- else:
1191
- if (state == 'ONLINE') and (self.safe_value(market, 'tradingEnabled')) and (self.safe_value(market, 'openapiEnabled')):
1192
- isActive = True
1193
- return {
1194
- 'id': id,
1195
- 'symbol': symbol,
1196
- 'base': base,
1197
- 'quote': quote,
1198
- 'settle': settle,
1199
- 'baseId': baseId,
1200
- 'quoteId': quoteId,
1201
- 'settleId': settleId,
1202
- 'type': type,
1203
- 'spot': spot,
1204
- 'margin': None,
1205
- 'swap': swap,
1206
- 'future': future,
1207
- 'option': False,
1208
- 'active': isActive,
1209
- 'contract': contract,
1210
- 'linear': linear,
1211
- 'inverse': inverse,
1212
- 'taker': self.safe_number(market, 'takerFee'),
1213
- 'maker': self.safe_number(market, 'makerFee'),
1214
- 'contractSize': self.safe_number(market, 'contractSize'),
1215
- 'expiry': expiry,
1216
- 'expiryDatetime': self.iso8601(expiry),
1217
- 'strike': None,
1218
- 'optionType': None,
1219
- 'precision': {
1220
- 'price': self.parse_number(self.parse_precision(self.safe_string(market, 'pricePrecision'))),
1221
- 'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'quantityPrecision'))),
1222
- 'base': self.parse_number(self.parse_precision(self.safe_string(market, 'baseCoinPrecision'))),
1223
- 'quote': self.parse_number(self.parse_precision(self.safe_string(market, 'quoteCoinPrecision'))),
1224
- },
1225
- 'limits': {
1226
- 'leverage': {
1227
- 'min': self.parse_number('1'),
1228
- 'max': None,
1229
- },
1230
- 'amount': {
1231
- 'min': minAmount,
1232
- 'max': maxAmount,
1233
- },
1234
- 'price': {
1235
- 'min': minPrice,
1236
- 'max': maxPrice,
1237
- },
1238
- 'cost': {
1239
- 'min': minCost,
1240
- 'max': maxCost,
1241
- },
1242
- },
1243
- 'info': market,
1244
- }
1245
-
1246
- def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Optional[int] = None, limit: Optional[int] = None, params={}):
1247
- """
1248
- fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1249
- see https://doc.xt.com/#market4kline
1250
- see https://doc.xt.com/#futures_quotesgetKLine
1251
- :param str symbol: unified symbol of the market to fetch OHLCV data for
1252
- :param str timeframe: the length of time each candle represents
1253
- :param int|None since: timestamp in ms of the earliest candle to fetch
1254
- :param int|None limit: the maximum amount of candles to fetch
1255
- :param dict params: extra parameters specific to the xt api endpoint
1256
- :returns [[int]]: A list of candles ordered, open, high, low, close, volume
1257
- """
1258
- self.load_markets()
1259
- market = self.market(symbol)
1260
- request = {
1261
- 'symbol': market['id'],
1262
- 'interval': self.safe_string(self.timeframes, timeframe, timeframe),
1263
- }
1264
- if since is not None:
1265
- request['startTime'] = since
1266
- if limit is not None:
1267
- request['limit'] = limit
1268
- response = None
1269
- if market['linear']:
1270
- response = self.publicLinearGetFutureMarketV1PublicQKline(self.extend(request, params))
1271
- elif market['inverse']:
1272
- response = self.publicInverseGetFutureMarketV1PublicQKline(self.extend(request, params))
1273
- else:
1274
- response = self.publicSpotGetKline(self.extend(request, params))
1275
- #
1276
- # spot
1277
- #
1278
- # {
1279
- # "rc": 0,
1280
- # "mc": "SUCCESS",
1281
- # "ma": [],
1282
- # "result": [
1283
- # {
1284
- # "t": 1678167720000,
1285
- # "o": "22467.85",
1286
- # "c": "22465.87",
1287
- # "h": "22468.86",
1288
- # "l": "22465.21",
1289
- # "q": "1.316656",
1290
- # "v": "29582.73018498"
1291
- # },
1292
- # ]
1293
- # }
1294
- #
1295
- # swap and future
1296
- #
1297
- # {
1298
- # "returnCode": 0,
1299
- # "msgInfo": "success",
1300
- # "error": null,
1301
- # "result": [
1302
- # {
1303
- # "s": "btc_usdt",
1304
- # "p": "btc_usdt",
1305
- # "t": 1678168020000,
1306
- # "o": "22450.0",
1307
- # "c": "22441.5",
1308
- # "h": "22450.0",
1309
- # "l": "22441.5",
1310
- # "a": "312931",
1311
- # "v": "702461.58895"
1312
- # },
1313
- # ]
1314
- # }
1315
- #
1316
- ohlcvs = self.safe_value(response, 'result', [])
1317
- return self.parse_ohlcvs(ohlcvs, market, timeframe, since, limit)
1318
-
1319
- def parse_ohlcv(self, ohlcv, market=None):
1320
- #
1321
- # spot
1322
- #
1323
- # {
1324
- # "t": 1678167720000,
1325
- # "o": "22467.85",
1326
- # "c": "22465.87",
1327
- # "h": "22468.86",
1328
- # "l": "22465.21",
1329
- # "q": "1.316656",
1330
- # "v": "29582.73018498"
1331
- # }
1332
- #
1333
- # swap and future
1334
- #
1335
- # {
1336
- # "s": "btc_usdt",
1337
- # "p": "btc_usdt",
1338
- # "t": 1678168020000,
1339
- # "o": "22450.0",
1340
- # "c": "22441.5",
1341
- # "h": "22450.0",
1342
- # "l": "22441.5",
1343
- # "a": "312931",
1344
- # "v": "702461.58895"
1345
- # }
1346
- #
1347
- volumeIndex = 'v' if (market['inverse']) else 'a'
1348
- return [
1349
- self.safe_integer(ohlcv, 't'),
1350
- self.safe_number(ohlcv, 'o'),
1351
- self.safe_number(ohlcv, 'h'),
1352
- self.safe_number(ohlcv, 'l'),
1353
- self.safe_number(ohlcv, 'c'),
1354
- self.safe_number_2(ohlcv, volumeIndex, 'v'),
1355
- ]
1356
-
1357
- def fetch_order_book(self, symbol: str, limit: Optional[int] = None, params={}):
1358
- """
1359
- see https://doc.xt.com/#market3depth
1360
- see https://doc.xt.com/#futures_quotesgetDepth
1361
- fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1362
- :param str symbol: unified market symbol to fetch the order book for
1363
- :param int|None limit: the maximum amount of order book entries to return
1364
- :param dict params: extra parameters specific to the xt api endpoint
1365
- :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/en/latest/manual.html#order-book-structure>` indexed by market symbols
1366
- """
1367
- self.load_markets()
1368
- market = self.market(symbol)
1369
- request = {
1370
- 'symbol': market['id'],
1371
- }
1372
- response = None
1373
- if market['spot']:
1374
- if limit is not None:
1375
- request['limit'] = min(limit, 500)
1376
- response = self.publicSpotGetDepth(self.extend(request, params))
1377
- else:
1378
- if limit is not None:
1379
- request['level'] = min(limit, 50)
1380
- else:
1381
- request['level'] = 50
1382
- if market['linear']:
1383
- response = self.publicLinearGetFutureMarketV1PublicQDepth(self.extend(request, params))
1384
- elif market['inverse']:
1385
- response = self.publicInverseGetFutureMarketV1PublicQDepth(self.extend(request, params))
1386
- #
1387
- # spot
1388
- #
1389
- # {
1390
- # "rc": 0,
1391
- # "mc": "SUCCESS",
1392
- # "ma": [],
1393
- # "result": {
1394
- # "timestamp": 1678169975184,
1395
- # "lastUpdateId": 1675333221812,
1396
- # "bids": [
1397
- # ["22444.51", "0.129887"],
1398
- # ["22444.49", "0.114245"],
1399
- # ["22444.30", "0.225956"]
1400
- # ],
1401
- # "asks": [
1402
- # ["22446.19", "0.095330"],
1403
- # ["22446.24", "0.224413"],
1404
- # ["22446.28", "0.329095"]
1405
- # ]
1406
- # }
1407
- # }
1408
- #
1409
- # swap and future
1410
- #
1411
- # {
1412
- # "returnCode": 0,
1413
- # "msgInfo": "success",
1414
- # "error": null,
1415
- # "result": {
1416
- # "t": 1678170311005,
1417
- # "s": "btc_usdt",
1418
- # "u": 471694545627,
1419
- # "b": [
1420
- # ["22426", "198623"],
1421
- # ["22423.5", "80295"],
1422
- # ["22423", "163580"]
1423
- # ],
1424
- # "a": [
1425
- # ["22427", "3417"],
1426
- # ["22428.5", "43532"],
1427
- # ["22429", "119"]
1428
- # ]
1429
- # }
1430
- # }
1431
- #
1432
- orderBook = self.safe_value(response, 'result', {})
1433
- timestamp = self.safe_integer_2(orderBook, 'timestamp', 't')
1434
- if market['spot']:
1435
- return self.parse_order_book(orderBook, symbol, timestamp)
1436
- return self.parse_order_book(orderBook, symbol, timestamp, 'b', 'a')
1437
-
1438
- def fetch_ticker(self, symbol: str, params={}):
1439
- """
1440
- fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1441
- see https://doc.xt.com/#market10ticker24h
1442
- see https://doc.xt.com/#futures_quotesgetAggTicker
1443
- :param str symbol: unified market symbol to fetch the ticker for
1444
- :param dict params: extra parameters specific to the xt api endpoint
1445
- :returns dict: a `ticker structure <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
1446
- """
1447
- self.load_markets()
1448
- market = self.market(symbol)
1449
- request = {
1450
- 'symbol': market['id'],
1451
- }
1452
- response = None
1453
- if market['linear']:
1454
- response = self.publicLinearGetFutureMarketV1PublicQAggTicker(self.extend(request, params))
1455
- elif market['inverse']:
1456
- response = self.publicInverseGetFutureMarketV1PublicQAggTicker(self.extend(request, params))
1457
- else:
1458
- response = self.publicSpotGetTicker24h(self.extend(request, params))
1459
- #
1460
- # spot
1461
- #
1462
- # {
1463
- # "rc": 0,
1464
- # "mc": "SUCCESS",
1465
- # "ma": [],
1466
- # "result": [
1467
- # {
1468
- # "s": "btc_usdt",
1469
- # "t": 1678172693931,
1470
- # "cv": "34.00",
1471
- # "cr": "0.0015",
1472
- # "o": "22398.05",
1473
- # "l": "22323.72",
1474
- # "h": "22600.50",
1475
- # "c": "22432.05",
1476
- # "q": "7962.256931",
1477
- # "v": "178675209.47416856"
1478
- # }
1479
- # ]
1480
- # }
1481
- #
1482
- # swap and future
1483
- #
1484
- # {
1485
- # "returnCode": 0,
1486
- # "msgInfo": "success",
1487
- # "error": null,
1488
- # "result": {
1489
- # "t": 1678172848572,
1490
- # "s": "btc_usdt",
1491
- # "c": "22415.5",
1492
- # "h": "22590.0",
1493
- # "l": "22310.0",
1494
- # "a": "623654031",
1495
- # "v": "1399166074.31675",
1496
- # "o": "22381.5",
1497
- # "r": "0.0015",
1498
- # "i": "22424.5",
1499
- # "m": "22416.5",
1500
- # "bp": "22415",
1501
- # "ap": "22415.5"
1502
- # }
1503
- # }
1504
- #
1505
- ticker = self.safe_value(response, 'result')
1506
- if market['spot']:
1507
- return self.parse_ticker(ticker[0], market)
1508
- return self.parse_ticker(ticker, market)
1509
-
1510
- def fetch_tickers(self, symbols: Optional[List[str]] = None, params={}):
1511
- """
1512
- fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
1513
- see https://doc.xt.com/#market10ticker24h
1514
- see https://doc.xt.com/#futures_quotesgetAggTickers
1515
- :param [str]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1516
- :param dict params: extra parameters specific to the xt api endpoint
1517
- :returns dict: an array of `ticker structures <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
1518
- """
1519
- self.load_markets()
1520
- market = None
1521
- if symbols is not None:
1522
- symbols = self.market_symbols(symbols)
1523
- market = self.market(symbols[0])
1524
- request = {}
1525
- type = None
1526
- subType = None
1527
- response = None
1528
- type, params = self.handle_market_type_and_params('fetchTickers', market, params)
1529
- subType, params = self.handle_sub_type_and_params('fetchTickers', market, params)
1530
- if subType == 'inverse':
1531
- response = self.publicInverseGetFutureMarketV1PublicQAggTickers(self.extend(request, params))
1532
- elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
1533
- response = self.publicLinearGetFutureMarketV1PublicQAggTickers(self.extend(request, params))
1534
- else:
1535
- response = self.publicSpotGetTicker24h(self.extend(request, params))
1536
- #
1537
- # spot
1538
- #
1539
- # {
1540
- # "rc": 0,
1541
- # "mc": "SUCCESS",
1542
- # "ma": [],
1543
- # "result": [
1544
- # {
1545
- # "s": "btc_usdt",
1546
- # "t": 1678172693931,
1547
- # "cv": "34.00",
1548
- # "cr": "0.0015",
1549
- # "o": "22398.05",
1550
- # "l": "22323.72",
1551
- # "h": "22600.50",
1552
- # "c": "22432.05",
1553
- # "q": "7962.256931",
1554
- # "v": "178675209.47416856"
1555
- # }
1556
- # ]
1557
- # }
1558
- #
1559
- # swap and future
1560
- #
1561
- # {
1562
- # "returnCode": 0,
1563
- # "msgInfo": "success",
1564
- # "error": null,
1565
- # "result": [
1566
- # {
1567
- # "t": 1680738775108,
1568
- # "s": "badger_usdt",
1569
- # "c": "2.7176",
1570
- # "h": "2.7917",
1571
- # "l": "2.6818",
1572
- # "a": "88332",
1573
- # "v": "242286.3520",
1574
- # "o": "2.7422",
1575
- # "r": "-0.0089",
1576
- # "i": "2.7155",
1577
- # "m": "2.7161",
1578
- # "bp": "2.7152",
1579
- # "ap": "2.7176"
1580
- # },
1581
- # ]
1582
- # }
1583
- #
1584
- tickers = self.safe_value(response, 'result', [])
1585
- result = {}
1586
- for i in range(0, len(tickers)):
1587
- ticker = self.parse_ticker(tickers[i], market)
1588
- symbol = ticker['symbol']
1589
- result[symbol] = ticker
1590
- return self.filter_by_array(result, 'symbol', symbols)
1591
-
1592
- def fetch_bids_asks(self, symbols: Optional[List[str]] = None, params={}):
1593
- """
1594
- fetches the bid and ask price and volume for multiple markets
1595
- see https://doc.xt.com/#market9tickerBook
1596
- :param [str]|None symbols: unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
1597
- :param dict params: extra parameters specific to the xt api endpoint
1598
- :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
1599
- """
1600
- self.load_markets()
1601
- symbols = self.market_symbols(symbols)
1602
- request = {}
1603
- market = None
1604
- if symbols is not None:
1605
- market = self.market(symbols[0])
1606
- subType = None
1607
- subType, params = self.handle_sub_type_and_params('fetchBidsAsks', market, params)
1608
- if subType is not None:
1609
- raise NotSupported(self.id + ' fetchBidsAsks() is not available for swap and future markets, only spot markets are supported')
1610
- response = self.publicSpotGetTickerBook(self.extend(request, params))
1611
- #
1612
- # {
1613
- # "rc": 0,
1614
- # "mc": "SUCCESS",
1615
- # "ma": [],
1616
- # "result": [
1617
- # {
1618
- # "s": "kas_usdt",
1619
- # "t": 1679539891853,
1620
- # "ap": "0.016298",
1621
- # "aq": "5119.09",
1622
- # "bp": "0.016290",
1623
- # "bq": "135.37"
1624
- # },
1625
- # ]
1626
- # }
1627
- #
1628
- tickers = self.safe_value(response, 'result', [])
1629
- return self.parse_tickers(tickers, symbols)
1630
-
1631
- def parse_ticker(self, ticker, market=None):
1632
- #
1633
- # spot: fetchTicker, fetchTickers
1634
- #
1635
- # {
1636
- # "s": "btc_usdt",
1637
- # "t": 1678172693931,
1638
- # "cv": "34.00",
1639
- # "cr": "0.0015",
1640
- # "o": "22398.05",
1641
- # "l": "22323.72",
1642
- # "h": "22600.50",
1643
- # "c": "22432.05",
1644
- # "q": "7962.256931",
1645
- # "v": "178675209.47416856"
1646
- # }
1647
- #
1648
- # swap and future: fetchTicker, fetchTickers
1649
- #
1650
- # {
1651
- # "t": 1678172848572,
1652
- # "s": "btc_usdt",
1653
- # "c": "22415.5",
1654
- # "h": "22590.0",
1655
- # "l": "22310.0",
1656
- # "a": "623654031",
1657
- # "v": "1399166074.31675",
1658
- # "o": "22381.5",
1659
- # "r": "0.0015",
1660
- # "i": "22424.5",
1661
- # "m": "22416.5",
1662
- # "bp": "22415",
1663
- # "ap": "22415.5"
1664
- # }
1665
- #
1666
- # fetchBidsAsks
1667
- #
1668
- # {
1669
- # "s": "kas_usdt",
1670
- # "t": 1679539891853,
1671
- # "ap": "0.016298",
1672
- # "aq": "5119.09",
1673
- # "bp": "0.016290",
1674
- # "bq": "135.37"
1675
- # }
1676
- #
1677
- marketId = self.safe_string(ticker, 's')
1678
- marketType = market['type'] if (market is not None) else None
1679
- if marketType is None:
1680
- marketType = ('cv' in ticker) or 'spot' if ('aq' in ticker) else 'contract'
1681
- market = self.safe_market(marketId, market, '_', marketType)
1682
- symbol = market['symbol']
1683
- timestamp = self.safe_integer(ticker, 't')
1684
- return self.safe_ticker({
1685
- 'symbol': symbol,
1686
- 'timestamp': timestamp,
1687
- 'datetime': self.iso8601(timestamp),
1688
- 'high': self.safe_number(ticker, 'h'),
1689
- 'low': self.safe_number(ticker, 'l'),
1690
- 'bid': self.safe_number(ticker, 'bp'),
1691
- 'bidVolume': self.safe_number(ticker, 'bq'),
1692
- 'ask': self.safe_number(ticker, 'ap'),
1693
- 'askVolume': self.safe_number(ticker, 'aq'),
1694
- 'vwap': None,
1695
- 'open': self.safe_string(ticker, 'o'),
1696
- 'close': self.safe_string(ticker, 'c'),
1697
- 'last': self.safe_string(ticker, 'c'),
1698
- 'previousClose': None,
1699
- 'change': self.safe_number(ticker, 'cv'),
1700
- 'percentage': self.safe_number_2(ticker, 'cr', 'r'),
1701
- 'average': None,
1702
- 'baseVolume': None,
1703
- 'quoteVolume': self.safe_number_2(ticker, 'a', 'v'),
1704
- 'info': ticker,
1705
- }, market)
1706
-
1707
- def fetch_trades(self, symbol: str, since: Optional[int] = None, limit: Optional[int] = None, params={}):
1708
- """
1709
- get the list of most recent trades for a particular symbol
1710
- see https://doc.xt.com/#market5tradeRecent
1711
- see https://doc.xt.com/#futures_quotesgetDeal
1712
- :param str symbol: unified market symbol to fetch trades for
1713
- :param int|None since: timestamp in ms of the earliest trade to fetch
1714
- :param int|None limit: the maximum amount of trades to fetch
1715
- :param dict params: extra parameters specific to the xt api endpoint
1716
- :returns [dict]: a list of `trade structures <https://docs.ccxt.com/en/latest/manual.html?#public-trades>`
1717
- """
1718
- self.load_markets()
1719
- market = self.market(symbol)
1720
- request = {
1721
- 'symbol': market['id'],
1722
- }
1723
- response = None
1724
- if market['spot']:
1725
- if limit is not None:
1726
- request['limit'] = limit
1727
- response = self.publicSpotGetTradeRecent(self.extend(request, params))
1728
- else:
1729
- if limit is not None:
1730
- request['num'] = limit
1731
- if market['linear']:
1732
- response = self.publicLinearGetFutureMarketV1PublicQDeal(self.extend(request, params))
1733
- elif market['inverse']:
1734
- response = self.publicInverseGetFutureMarketV1PublicQDeal(self.extend(request, params))
1735
- #
1736
- # spot
1737
- #
1738
- # {
1739
- # "rc": 0,
1740
- # "mc": "SUCCESS",
1741
- # "ma": [],
1742
- # "result": [
1743
- # {
1744
- # "i": 203530723141917063,
1745
- # "t": 1678227505815,
1746
- # "p": "22038.81",
1747
- # "q": "0.000978",
1748
- # "v": "21.55395618",
1749
- # "b": True
1750
- # },
1751
- # ]
1752
- # }
1753
- #
1754
- # swap and future
1755
- #
1756
- # {
1757
- # "returnCode": 0,
1758
- # "msgInfo": "success",
1759
- # "error": null,
1760
- # "result": [
1761
- # {
1762
- # "t": 1678227683897,
1763
- # "s": "btc_usdt",
1764
- # "p": "22031",
1765
- # "a": "1067",
1766
- # "m": "BID"
1767
- # },
1768
- # ]
1769
- # }
1770
- #
1771
- trades = self.safe_value(response, 'result', [])
1772
- return self.parse_trades(trades, market)
1773
-
1774
- def fetch_my_trades(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
1775
- """
1776
- fetch all trades made by the user
1777
- see https://doc.xt.com/#tradetradeGet
1778
- see https://doc.xt.com/#futures_ordergetTrades
1779
- :param str|None symbol: unified market symbol to fetch trades for
1780
- :param int|None since: timestamp in ms of the earliest trade to fetch
1781
- :param int|None limit: the maximum amount of trades to fetch
1782
- :param dict params: extra parameters specific to the xt api endpoint
1783
- :returns [dict]: a list of `trade structures <https://docs.ccxt.com/en/latest/manual.html?#public-trades>`
1784
- """
1785
- self.load_markets()
1786
- request = {}
1787
- market = None
1788
- if symbol is not None:
1789
- market = self.market(symbol)
1790
- request['symbol'] = market['id']
1791
- if since is not None:
1792
- request['startTime'] = since
1793
- type = None
1794
- subType = None
1795
- response = None
1796
- type, params = self.handle_market_type_and_params('fetchMyTrades', market, params)
1797
- subType, params = self.handle_sub_type_and_params('fetchMyTrades', market, params)
1798
- if (subType is not None) or (type == 'swap') or (type == 'future'):
1799
- if limit is not None:
1800
- request['size'] = limit
1801
- if subType == 'inverse':
1802
- response = self.privateInverseGetFutureTradeV1OrderTradeList(self.extend(request, params))
1803
- else:
1804
- response = self.privateLinearGetFutureTradeV1OrderTradeList(self.extend(request, params))
1805
- else:
1806
- marginMode = None
1807
- marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
1808
- marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
1809
- request['bizType'] = marginOrSpotRequest
1810
- if limit is not None:
1811
- request['limit'] = limit
1812
- response = self.privateSpotGetTrade(self.extend(request, params))
1813
- #
1814
- # spot and margin
1815
- #
1816
- # {
1817
- # "rc": 0,
1818
- # "mc": "SUCCESS",
1819
- # "ma": [],
1820
- # "result": {
1821
- # "hasPrev": False,
1822
- # "hasNext": False,
1823
- # "items": [
1824
- # {
1825
- # "symbol": "btc_usdt",
1826
- # "tradeId": "206906233569974658",
1827
- # "orderId": "206906233178463488",
1828
- # "orderSide": "SELL",
1829
- # "orderType": "MARKET",
1830
- # "bizType": "SPOT",
1831
- # "time": 1679032290215,
1832
- # "price": "25703.46",
1833
- # "quantity": "0.000099",
1834
- # "quoteQty": "2.54464254",
1835
- # "baseCurrency": "btc",
1836
- # "quoteCurrency": "usdt",
1837
- # "fee": "0.00508929",
1838
- # "feeCurrency": "usdt",
1839
- # "takerMaker": "TAKER"
1840
- # },
1841
- # ]
1842
- # }
1843
- # }
1844
- #
1845
- # swap and future
1846
- #
1847
- # {
1848
- # "returnCode": 0,
1849
- # "msgInfo": "success",
1850
- # "error": null,
1851
- # "result": {
1852
- # "page": 1,
1853
- # "ps": 10,
1854
- # "total": 2,
1855
- # "items": [
1856
- # {
1857
- # "orderId": "207260566170987200",
1858
- # "execId": "207260566790603265",
1859
- # "symbol": "btc_usdt",
1860
- # "quantity": "13",
1861
- # "price": "27368",
1862
- # "fee": "0.02134704",
1863
- # "feeCoin": "usdt",
1864
- # "timestamp": 1679116769838,
1865
- # "takerMaker": "TAKER"
1866
- # },
1867
- # ]
1868
- # }
1869
- # }
1870
- #
1871
- data = self.safe_value(response, 'result', {})
1872
- trades = self.safe_value(data, 'items', [])
1873
- return self.parse_trades(trades, market, since, limit)
1874
-
1875
- def parse_trade(self, trade, market=None):
1876
- #
1877
- # spot: fetchTrades
1878
- #
1879
- # {
1880
- # "i": 203530723141917063,
1881
- # "t": 1678227505815,
1882
- # "p": "22038.81",
1883
- # "q": "0.000978",
1884
- # "v": "21.55395618",
1885
- # "b": True
1886
- # }
1887
- #
1888
- # swap and future: fetchTrades
1889
- #
1890
- # {
1891
- # "t": 1678227683897,
1892
- # "s": "btc_usdt",
1893
- # "p": "22031",
1894
- # "a": "1067",
1895
- # "m": "BID"
1896
- # }
1897
- #
1898
- # spot: fetchMyTrades
1899
- #
1900
- # {
1901
- # "symbol": "btc_usdt",
1902
- # "tradeId": "206906233569974658",
1903
- # "orderId": "206906233178463488",
1904
- # "orderSide": "SELL",
1905
- # "orderType": "MARKET",
1906
- # "bizType": "SPOT",
1907
- # "time": 1679032290215,
1908
- # "price": "25703.46",
1909
- # "quantity": "0.000099",
1910
- # "quoteQty": "2.54464254",
1911
- # "baseCurrency": "btc",
1912
- # "quoteCurrency": "usdt",
1913
- # "fee": "0.00508929",
1914
- # "feeCurrency": "usdt",
1915
- # "takerMaker": "TAKER"
1916
- # }
1917
- #
1918
- # swap and future: fetchMyTrades
1919
- #
1920
- # {
1921
- # "orderId": "207260566170987200",
1922
- # "execId": "207260566790603265",
1923
- # "symbol": "btc_usdt",
1924
- # "quantity": "13",
1925
- # "price": "27368",
1926
- # "fee": "0.02134704",
1927
- # "feeCoin": "usdt",
1928
- # "timestamp": 1679116769838,
1929
- # "takerMaker": "TAKER"
1930
- # }
1931
- #
1932
- marketId = self.safe_string_2(trade, 's', 'symbol')
1933
- marketType = market['type'] if (market is not None) else None
1934
- if marketType is None:
1935
- marketType = ('b' in trade) or 'spot' if ('bizType' in trade) else 'contract'
1936
- market = self.safe_market(marketId, market, '_', marketType)
1937
- bidOrAsk = self.safe_string(trade, 'm')
1938
- side = self.safe_string_lower(trade, 'orderSide')
1939
- if bidOrAsk is not None:
1940
- side = 'buy' if (bidOrAsk == 'BID') else 'sell'
1941
- buyerMaker = self.safe_value(trade, 'b')
1942
- takerOrMaker = self.safe_string_lower(trade, 'takerMaker')
1943
- if buyerMaker is not None:
1944
- takerOrMaker = 'maker' if buyerMaker else 'taker'
1945
- timestamp = self.safe_integer_n(trade, ['t', 'time', 'timestamp'])
1946
- quantity = self.safe_string_2(trade, 'q', 'quantity')
1947
- amount = None
1948
- if marketType == 'spot':
1949
- amount = quantity
1950
- else:
1951
- if quantity is None:
1952
- amount = Precise.string_mul(self.safe_string(trade, 'a'), self.number_to_string(market['contractSize']))
1953
- else:
1954
- amount = Precise.string_mul(quantity, self.number_to_string(market['contractSize']))
1955
- return self.safe_trade({
1956
- 'info': trade,
1957
- 'id': self.safe_string_n(trade, ['i', 'tradeId', 'execId']),
1958
- 'timestamp': timestamp,
1959
- 'datetime': self.iso8601(timestamp),
1960
- 'symbol': market['symbol'],
1961
- 'order': self.safe_string(trade, 'orderId'),
1962
- 'type': self.safe_string_lower(trade, 'orderType'),
1963
- 'side': side,
1964
- 'takerOrMaker': takerOrMaker,
1965
- 'price': self.safe_string_2(trade, 'p', 'price'),
1966
- 'amount': amount,
1967
- 'cost': None,
1968
- 'fee': {
1969
- 'currency': self.safe_currency_code(self.safe_string_2(trade, 'feeCurrency', 'feeCoin')),
1970
- 'cost': self.safe_string(trade, 'fee'),
1971
- 'rate': None,
1972
- },
1973
- }, market)
1974
-
1975
- def fetch_balance(self, params={}):
1976
- """
1977
- query for balance and get the amount of funds available for trading or funds locked in orders
1978
- see https://doc.xt.com/#balancebalancesGet
1979
- see https://doc.xt.com/#futures_usergetBalances
1980
- :param dict params: extra parameters specific to the xt api endpoint
1981
- :returns dict: a `balance structure <https://docs.ccxt.com/en/latest/manual.html?#balance-structure>`
1982
- """
1983
- self.load_markets()
1984
- type = None
1985
- subType = None
1986
- response = None
1987
- type, params = self.handle_market_type_and_params('fetchBalance', None, params)
1988
- subType, params = self.handle_sub_type_and_params('fetchBalance', None, params)
1989
- isContractWallet = ((type == 'swap') or (type == 'future'))
1990
- if subType == 'inverse':
1991
- response = self.privateInverseGetFutureUserV1BalanceList(params)
1992
- elif (subType == 'linear') or isContractWallet:
1993
- response = self.privateLinearGetFutureUserV1BalanceList(params)
1994
- else:
1995
- response = self.privateSpotGetBalances(params)
1996
- #
1997
- # spot
1998
- #
1999
- # {
2000
- # "rc": 0,
2001
- # "mc": "SUCCESS",
2002
- # "ma": [],
2003
- # "result": {
2004
- # "totalUsdtAmount": "31.75931133",
2005
- # "totalBtcAmount": "0.00115951",
2006
- # "assets": [
2007
- # {
2008
- # "currency": "usdt",
2009
- # "currencyId": 11,
2010
- # "frozenAmount": "0.03834082",
2011
- # "availableAmount": "31.70995965",
2012
- # "totalAmount": "31.74830047",
2013
- # "convertBtcAmount": "0.00115911",
2014
- # "convertUsdtAmount": "31.74830047"
2015
- # },
2016
- # ]
2017
- # }
2018
- # }
2019
- #
2020
- # swap and future
2021
- #
2022
- # {
2023
- # "returnCode": 0,
2024
- # "msgInfo": "success",
2025
- # "error": null,
2026
- # "result": [
2027
- # {
2028
- # "coin": "usdt",
2029
- # "walletBalance": "19.29849875",
2030
- # "openOrderMarginFrozen": "0",
2031
- # "isolatedMargin": "0.709475",
2032
- # "crossedMargin": "0",
2033
- # "availableBalance": "18.58902375",
2034
- # "bonus": "0",
2035
- # "coupon":"0"
2036
- # }
2037
- # ]
2038
- # }
2039
- #
2040
- balances = None
2041
- if (subType is not None) or isContractWallet:
2042
- balances = self.safe_value(response, 'result', [])
2043
- else:
2044
- data = self.safe_value(response, 'result', {})
2045
- balances = self.safe_value(data, 'assets', [])
2046
- return self.parse_balance(balances)
2047
-
2048
- def parse_balance(self, response):
2049
- #
2050
- # spot
2051
- #
2052
- # {
2053
- # "currency": "usdt",
2054
- # "currencyId": 11,
2055
- # "frozenAmount": "0.03834082",
2056
- # "availableAmount": "31.70995965",
2057
- # "totalAmount": "31.74830047",
2058
- # "convertBtcAmount": "0.00115911",
2059
- # "convertUsdtAmount": "31.74830047"
2060
- # }
2061
- #
2062
- # swap and future
2063
- #
2064
- # {
2065
- # "coin": "usdt",
2066
- # "walletBalance": "19.29849875",
2067
- # "openOrderMarginFrozen": "0",
2068
- # "isolatedMargin": "0.709475",
2069
- # "crossedMargin": "0",
2070
- # "availableBalance": "18.58902375",
2071
- # "bonus": "0",
2072
- # "coupon":"0"
2073
- # }
2074
- #
2075
- result = {'info': response}
2076
- for i in range(0, len(response)):
2077
- balance = response[i]
2078
- currencyId = self.safe_string_2(balance, 'currency', 'coin')
2079
- code = self.safe_currency_code(currencyId)
2080
- account = self.account()
2081
- free = self.safe_string_2(balance, 'availableAmount', 'availableBalance')
2082
- used = self.safe_string(balance, 'frozenAmount')
2083
- total = self.safe_string_2(balance, 'totalAmount', 'walletBalance')
2084
- if used is None:
2085
- crossedAndIsolatedMargin = Precise.string_add(self.safe_string(balance, 'crossedMargin'), self.safe_string(balance, 'isolatedMargin'))
2086
- used = Precise.string_add(self.safe_string(balance, 'openOrderMarginFrozen'), crossedAndIsolatedMargin)
2087
- account['free'] = free
2088
- account['used'] = used
2089
- account['total'] = total
2090
- result[code] = account
2091
- return self.safe_balance(result)
2092
-
2093
- def create_order(self, symbol: str, type, side, amount, price=None, params={}):
2094
- """
2095
- create a trade order
2096
- see https://doc.xt.com/#orderorderPost
2097
- see https://doc.xt.com/#futures_ordercreate
2098
- see https://doc.xt.com/#futures_entrustcreatePlan
2099
- see https://doc.xt.com/#futures_entrustcreateProfit
2100
- :param str symbol: unified symbol of the market to create an order in
2101
- :param str type: 'market' or 'limit'
2102
- :param str side: 'buy' or 'sell'
2103
- :param float amount: how much you want to trade in units of the base currency
2104
- :param float|None price: the price to fulfill the order, in units of the quote currency, can be ignored in market orders
2105
- :param dict params: extra parameters specific to the xt api endpoint
2106
- :param str|None params['timeInForce']: 'GTC', 'IOC', 'FOK' or 'GTX'
2107
- :param str|None params['entrustType']: 'TAKE_PROFIT', 'STOP', 'TAKE_PROFIT_MARKET', 'STOP_MARKET', 'TRAILING_STOP_MARKET', required if stopPrice is defined, currently isn't functioning on xt's side
2108
- :param str|None params['triggerPriceType']: 'INDEX_PRICE', 'MARK_PRICE', 'LATEST_PRICE', required if stopPrice is defined
2109
- :param float|None params['stopPrice']: price to trigger a stop order
2110
- :param float|None params['stopLoss']: price to set a stop-loss on an open position
2111
- :param float|None params['takeProfit']: price to set a take-profit on an open position
2112
- :returns dict: an `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
2113
- """
2114
- self.load_markets()
2115
- market = self.market(symbol)
2116
- symbol = market['symbol']
2117
- if market['spot']:
2118
- return self.create_spot_order(symbol, type, side, amount, price, params)
2119
- else:
2120
- return self.create_contract_order(symbol, type, side, amount, price, params)
2121
-
2122
- def create_spot_order(self, symbol: str, type, side, amount, price=None, params={}):
2123
- self.load_markets()
2124
- market = self.market(symbol)
2125
- request = {
2126
- 'symbol': market['id'],
2127
- 'side': side.upper(),
2128
- 'type': type.upper(),
2129
- }
2130
- timeInForce = None
2131
- marginMode = None
2132
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
2133
- marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
2134
- request['bizType'] = marginOrSpotRequest
2135
- if type == 'market':
2136
- timeInForce = self.safe_string_upper(params, 'timeInForce', 'FOK')
2137
- if side == 'buy':
2138
- createMarketBuyOrderRequiresPrice = self.safe_value(self.options, 'createMarketBuyOrderRequiresPrice', True)
2139
- if createMarketBuyOrderRequiresPrice:
2140
- if price is None:
2141
- raise InvalidOrder(self.id + ' createOrder() requires a price argument for market buy orders on spot markets to calculate the total amount to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option to False and pass in the cost to spend into the amount parameter')
2142
- else:
2143
- amountString = self.number_to_string(amount)
2144
- priceString = self.number_to_string(price)
2145
- cost = self.parse_number(Precise.string_mul(amountString, priceString))
2146
- request['quoteQty'] = self.cost_to_precision(symbol, cost)
2147
- else:
2148
- request['quoteQty'] = self.amount_to_precision(symbol, amount)
2149
- else:
2150
- timeInForce = self.safe_string_upper(params, 'timeInForce', 'GTC')
2151
- request['price'] = self.price_to_precision(symbol, price)
2152
- if (side == 'sell') or (type == 'limit'):
2153
- request['quantity'] = self.amount_to_precision(symbol, amount)
2154
- request['timeInForce'] = timeInForce
2155
- response = self.privateSpotPostOrder(self.extend(request, params))
2156
- #
2157
- # {
2158
- # "rc": 0,
2159
- # "mc": "SUCCESS",
2160
- # "ma": [],
2161
- # "result": {
2162
- # "orderId": "204371980095156544"
2163
- # }
2164
- # }
2165
- #
2166
- order = self.safe_value(response, 'result', {})
2167
- return self.parse_order(order, market)
2168
-
2169
- def create_contract_order(self, symbol: str, type, side, amount, price=None, params={}):
2170
- self.load_markets()
2171
- market = self.market(symbol)
2172
- request = {
2173
- 'symbol': market['id'],
2174
- 'origQty': self.amount_to_precision(symbol, amount),
2175
- }
2176
- timeInForce = self.safe_string_upper(params, 'timeInForce')
2177
- if timeInForce is not None:
2178
- request['timeInForce'] = timeInForce
2179
- reduceOnly = self.safe_value(params, 'reduceOnly', False)
2180
- if side == 'buy':
2181
- requestType = 'SHORT' if (reduceOnly) else 'LONG'
2182
- request['positionSide'] = requestType
2183
- else:
2184
- requestType = 'LONG' if (reduceOnly) else 'SHORT'
2185
- request['positionSide'] = requestType
2186
- response = None
2187
- triggerPrice = self.safe_number_2(params, 'triggerPrice', 'stopPrice')
2188
- stopLoss = self.safe_number_2(params, 'stopLoss', 'triggerStopPrice')
2189
- takeProfit = self.safe_number_2(params, 'takeProfit', 'triggerProfitPrice')
2190
- isTrigger = (triggerPrice is not None)
2191
- isStopLoss = (stopLoss is not None)
2192
- isTakeProfit = (takeProfit is not None)
2193
- if price is not None:
2194
- if not (isStopLoss) and not (isTakeProfit):
2195
- request['price'] = self.price_to_precision(symbol, price)
2196
- if isTrigger:
2197
- request['timeInForce'] = self.safe_string_upper(params, 'timeInForce', 'GTC')
2198
- request['triggerPriceType'] = self.safe_string(params, 'triggerPriceType', 'LATEST_PRICE')
2199
- request['orderSide'] = side.upper()
2200
- request['stopPrice'] = self.price_to_precision(symbol, triggerPrice)
2201
- entrustType = 'STOP_MARKET' if (type == 'market') else 'STOP'
2202
- request['entrustType'] = entrustType
2203
- params = self.omit(params, 'triggerPrice')
2204
- if market['linear']:
2205
- response = self.privateLinearPostFutureTradeV1EntrustCreatePlan(self.extend(request, params))
2206
- elif market['inverse']:
2207
- response = self.privateInversePostFutureTradeV1EntrustCreatePlan(self.extend(request, params))
2208
- elif isStopLoss or isTakeProfit:
2209
- if isStopLoss:
2210
- request['triggerStopPrice'] = self.price_to_precision(symbol, stopLoss)
2211
- else:
2212
- request['triggerProfitPrice'] = self.price_to_precision(symbol, takeProfit)
2213
- params = self.omit(params, ['stopLoss', 'takeProfit'])
2214
- if market['linear']:
2215
- response = self.privateLinearPostFutureTradeV1EntrustCreateProfit(self.extend(request, params))
2216
- elif market['inverse']:
2217
- response = self.privateInversePostFutureTradeV1EntrustCreateProfit(self.extend(request, params))
2218
- else:
2219
- request['orderSide'] = side.upper()
2220
- request['orderType'] = type.upper()
2221
- if market['linear']:
2222
- response = self.privateLinearPostFutureTradeV1OrderCreate(self.extend(request, params))
2223
- elif market['inverse']:
2224
- response = self.privateInversePostFutureTradeV1OrderCreate(self.extend(request, params))
2225
- #
2226
- # {
2227
- # "returnCode": 0,
2228
- # "msgInfo": "success",
2229
- # "error": null,
2230
- # "result": "206410760006650176"
2231
- # }
2232
- #
2233
- return self.parse_order(response, market)
2234
-
2235
- def fetch_order(self, id: str, symbol: Optional[str] = None, params={}):
2236
- """
2237
- fetches information on an order made by the user
2238
- see https://doc.xt.com/#orderorderGet
2239
- see https://doc.xt.com/#futures_ordergetById
2240
- see https://doc.xt.com/#futures_entrustgetPlanById
2241
- see https://doc.xt.com/#futures_entrustgetProfitById
2242
- :param str id: order id
2243
- :param str|None symbol: unified symbol of the market the order was made in
2244
- :param dict params: extra parameters specific to the xt api endpoint
2245
- :param bool|None params['stop']: if the order is a stop trigger order or not
2246
- :param bool|None params['stopLossTakeProfit']: if the order is a stop-loss or take-profit order
2247
- :returns dict: An `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
2248
- """
2249
- self.load_markets()
2250
- market = None
2251
- if symbol is not None:
2252
- market = self.market(symbol)
2253
- request = {}
2254
- type = None
2255
- subType = None
2256
- response = None
2257
- type, params = self.handle_market_type_and_params('fetchOrder', market, params)
2258
- subType, params = self.handle_sub_type_and_params('fetchOrder', market, params)
2259
- stop = self.safe_value(params, 'stop')
2260
- stopLossTakeProfit = self.safe_value(params, 'stopLossTakeProfit')
2261
- if stop:
2262
- request['entrustId'] = id
2263
- elif stopLossTakeProfit:
2264
- request['profitId'] = id
2265
- else:
2266
- request['orderId'] = id
2267
- if stop:
2268
- params = self.omit(params, 'stop')
2269
- if subType == 'inverse':
2270
- response = self.privateInverseGetFutureTradeV1EntrustPlanDetail(self.extend(request, params))
2271
- else:
2272
- response = self.privateLinearGetFutureTradeV1EntrustPlanDetail(self.extend(request, params))
2273
- elif stopLossTakeProfit:
2274
- params = self.omit(params, 'stopLossTakeProfit')
2275
- if subType == 'inverse':
2276
- response = self.privateInverseGetFutureTradeV1EntrustProfitDetail(self.extend(request, params))
2277
- else:
2278
- response = self.privateLinearGetFutureTradeV1EntrustProfitDetail(self.extend(request, params))
2279
- elif subType == 'inverse':
2280
- response = self.privateInverseGetFutureTradeV1OrderDetail(self.extend(request, params))
2281
- elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
2282
- response = self.privateLinearGetFutureTradeV1OrderDetail(self.extend(request, params))
2283
- else:
2284
- response = self.privateSpotGetOrderOrderId(self.extend(request, params))
2285
- #
2286
- # spot
2287
- #
2288
- # {
2289
- # "rc": 0,
2290
- # "mc": "SUCCESS",
2291
- # "ma": [],
2292
- # "result": {
2293
- # "symbol": "btc_usdt",
2294
- # "orderId": "207505997850909952",
2295
- # "clientOrderId": null,
2296
- # "baseCurrency": "btc",
2297
- # "quoteCurrency": "usdt",
2298
- # "side": "BUY",
2299
- # "type": "LIMIT",
2300
- # "timeInForce": "GTC",
2301
- # "price": "20000.00",
2302
- # "origQty": "0.001000",
2303
- # "origQuoteQty": "20.00",
2304
- # "executedQty": "0.000000",
2305
- # "leavingQty": "0.001000",
2306
- # "tradeBase": "0.000000",
2307
- # "tradeQuote": "0.00",
2308
- # "avgPrice": null,
2309
- # "fee": null,
2310
- # "feeCurrency": null,
2311
- # "closed": False,
2312
- # "state": "NEW",
2313
- # "time": 1679175285162,
2314
- # "updatedTime": 1679175285255
2315
- # }
2316
- # }
2317
- #
2318
- # swap and future
2319
- #
2320
- # {
2321
- # "returnCode": 0,
2322
- # "msgInfo": "success",
2323
- # "error": null,
2324
- # "result": {
2325
- # "orderId": "211451874783183936",
2326
- # "clientOrderId": null,
2327
- # "symbol": "btc_usdt",
2328
- # "orderType": "LIMIT",
2329
- # "orderSide": "BUY",
2330
- # "positionSide": "LONG",
2331
- # "timeInForce": "GTC",
2332
- # "closePosition": False,
2333
- # "price": "20000",
2334
- # "origQty": "10",
2335
- # "avgPrice": "0",
2336
- # "executedQty": "0",
2337
- # "marginFrozen": "1.34533334",
2338
- # "remark": null,
2339
- # "triggerProfitPrice": null,
2340
- # "triggerStopPrice": null,
2341
- # "sourceId": null,
2342
- # "sourceType": "DEFAULT",
2343
- # "forceClose": False,
2344
- # "closeProfit": null,
2345
- # "state": "NEW",
2346
- # "createdTime": 1680116055693,
2347
- # "updatedTime": 1680116055693
2348
- # }
2349
- # }
2350
- #
2351
- # trigger
2352
- #
2353
- # {
2354
- # "returnCode": 0,
2355
- # "msgInfo": "success",
2356
- # "error": null,
2357
- # "result": {
2358
- # "entrustId": "216300248132756992",
2359
- # "symbol": "btc_usdt",
2360
- # "entrustType": "STOP",
2361
- # "orderSide": "SELL",
2362
- # "positionSide": "SHORT",
2363
- # "timeInForce": "GTC",
2364
- # "closePosition": null,
2365
- # "price": "20000",
2366
- # "origQty": "1",
2367
- # "stopPrice": "19000",
2368
- # "triggerPriceType": "LATEST_PRICE",
2369
- # "state": "NOT_TRIGGERED",
2370
- # "marketOrderLevel": null,
2371
- # "createdTime": 1681271998064,
2372
- # "updatedTime": 1681271998064,
2373
- # "ordinary": False
2374
- # }
2375
- # }
2376
- #
2377
- # stop-loss and take-profit
2378
- #
2379
- # {
2380
- # "returnCode": 0,
2381
- # "msgInfo": "success",
2382
- # "error": null,
2383
- # "result": {
2384
- # "profitId": "216306213226230400",
2385
- # "symbol": "btc_usdt",
2386
- # "positionSide": "LONG",
2387
- # "origQty": "1",
2388
- # "triggerPriceType": "LATEST_PRICE",
2389
- # "triggerProfitPrice": null,
2390
- # "triggerStopPrice": "20000",
2391
- # "entryPrice": null,
2392
- # "positionSize": null,
2393
- # "isolatedMargin": null,
2394
- # "executedQty": null,
2395
- # "avgPrice": null,
2396
- # "positionType": "ISOLATED",
2397
- # "state": "NOT_TRIGGERED",
2398
- # "createdTime": 1681273420039
2399
- # }
2400
- # }
2401
- #
2402
- order = self.safe_value(response, 'result', {})
2403
- return self.parse_order(order, market)
2404
-
2405
- def fetch_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
2406
- """
2407
- fetches information on multiple orders made by the user
2408
- see https://doc.xt.com/#orderhistoryOrderGet
2409
- see https://doc.xt.com/#futures_ordergetHistory
2410
- see https://doc.xt.com/#futures_entrustgetPlanHistory
2411
- :param str|None symbol: unified market symbol of the market the orders were made in
2412
- :param int|None since: timestamp in ms of the earliest order
2413
- :param int|None limit: the maximum number of order structures to retrieve
2414
- :param dict params: extra parameters specific to the xt api endpoint
2415
- :param bool|None params['stop']: if the order is a stop trigger order or not
2416
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
2417
- """
2418
- self.load_markets()
2419
- request = {}
2420
- market = None
2421
- if symbol is not None:
2422
- market = self.market(symbol)
2423
- request['symbol'] = market['id']
2424
- if since is not None:
2425
- request['startTime'] = since
2426
- if limit is not None:
2427
- request['limit'] = limit
2428
- type = None
2429
- subType = None
2430
- response = None
2431
- type, params = self.handle_market_type_and_params('fetchOrders', market, params)
2432
- subType, params = self.handle_sub_type_and_params('fetchOrders', market, params)
2433
- stop = self.safe_value(params, 'stop')
2434
- if stop:
2435
- params = self.omit(params, 'stop')
2436
- if subType == 'inverse':
2437
- response = self.privateInverseGetFutureTradeV1EntrustPlanListHistory(self.extend(request, params))
2438
- else:
2439
- response = self.privateLinearGetFutureTradeV1EntrustPlanListHistory(self.extend(request, params))
2440
- elif subType == 'inverse':
2441
- response = self.privateInverseGetFutureTradeV1OrderListHistory(self.extend(request, params))
2442
- elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
2443
- response = self.privateLinearGetFutureTradeV1OrderListHistory(self.extend(request, params))
2444
- else:
2445
- marginMode = None
2446
- marginMode, params = self.handle_margin_mode_and_params('fetchOrders', params)
2447
- marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
2448
- request['bizType'] = marginOrSpotRequest
2449
- response = self.privateSpotGetHistoryOrder(self.extend(request, params))
2450
- #
2451
- # spot and margin
2452
- #
2453
- # {
2454
- # "rc": 0,
2455
- # "mc": "SUCCESS",
2456
- # "ma": [],
2457
- # "result": {
2458
- # "hasPrev": False,
2459
- # "hasNext": True,
2460
- # "items": [
2461
- # {
2462
- # "symbol": "btc_usdt",
2463
- # "orderId": "207505997850909952",
2464
- # "clientOrderId": null,
2465
- # "baseCurrency": "btc",
2466
- # "quoteCurrency": "usdt",
2467
- # "side": "BUY",
2468
- # "type": "LIMIT",
2469
- # "timeInForce": "GTC",
2470
- # "price": "20000.00",
2471
- # "origQty": "0.001000",
2472
- # "origQuoteQty": "20.00",
2473
- # "executedQty": "0.000000",
2474
- # "leavingQty": "0.000000",
2475
- # "tradeBase": "0.000000",
2476
- # "tradeQuote": "0.00",
2477
- # "avgPrice": null,
2478
- # "fee": null,
2479
- # "feeCurrency": null,
2480
- # "closed": True,
2481
- # "state": "CANCELED",
2482
- # "time": 1679175285162,
2483
- # "updatedTime": 1679175488492
2484
- # },
2485
- # ]
2486
- # }
2487
- # }
2488
- #
2489
- # swap and future
2490
- #
2491
- # {
2492
- # "returnCode": 0,
2493
- # "msgInfo": "success",
2494
- # "error": null,
2495
- # "result": {
2496
- # "hasPrev": False,
2497
- # "hasNext": True,
2498
- # "items": [
2499
- # {
2500
- # "orderId": "207519546930995456",
2501
- # "clientOrderId": null,
2502
- # "symbol": "btc_usdt",
2503
- # "orderType": "LIMIT",
2504
- # "orderSide": "BUY",
2505
- # "positionSide": "LONG",
2506
- # "timeInForce": "GTC",
2507
- # "closePosition": False,
2508
- # "price": "20000",
2509
- # "origQty": "100",
2510
- # "avgPrice": "0",
2511
- # "executedQty": "0",
2512
- # "marginFrozen": "4.12",
2513
- # "remark": null,
2514
- # "triggerProfitPrice": null,
2515
- # "triggerStopPrice": null,
2516
- # "sourceId": null,
2517
- # "sourceType": "DEFAULT",
2518
- # "forceClose": False,
2519
- # "closeProfit": null,
2520
- # "state": "CANCELED",
2521
- # "createdTime": 1679178515689,
2522
- # "updatedTime": 1679180096172
2523
- # },
2524
- # ]
2525
- # }
2526
- # }
2527
- #
2528
- # stop
2529
- #
2530
- # {
2531
- # "returnCode": 0,
2532
- # "msgInfo": "success",
2533
- # "error": null,
2534
- # "result": {
2535
- # "hasPrev": False,
2536
- # "hasNext": False,
2537
- # "items": [
2538
- # {
2539
- # "entrustId": "216300248132756992",
2540
- # "symbol": "btc_usdt",
2541
- # "entrustType": "STOP",
2542
- # "orderSide": "SELL",
2543
- # "positionSide": "SHORT",
2544
- # "timeInForce": "GTC",
2545
- # "closePosition": null,
2546
- # "price": "20000",
2547
- # "origQty": "1",
2548
- # "stopPrice": "19000",
2549
- # "triggerPriceType": "LATEST_PRICE",
2550
- # "state": "USER_REVOCATION",
2551
- # "marketOrderLevel": null,
2552
- # "createdTime": 1681271998064,
2553
- # "updatedTime": 1681273188674,
2554
- # "ordinary": False
2555
- # },
2556
- # ]
2557
- # }
2558
- # }
2559
- #
2560
- data = self.safe_value(response, 'result', {})
2561
- orders = self.safe_value(data, 'items', [])
2562
- return self.parse_orders(orders, market, since, limit)
2563
-
2564
- def fetch_orders_by_status(self, status, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
2565
- self.load_markets()
2566
- request = {}
2567
- market = None
2568
- if symbol is not None:
2569
- market = self.market(symbol)
2570
- request['symbol'] = market['id']
2571
- type = None
2572
- subType = None
2573
- response = None
2574
- type, params = self.handle_market_type_and_params('fetchOrdersByStatus', market, params)
2575
- subType, params = self.handle_sub_type_and_params('fetchOrdersByStatus', market, params)
2576
- stop = self.safe_value(params, 'stop')
2577
- stopLossTakeProfit = self.safe_value(params, 'stopLossTakeProfit')
2578
- if status == 'open':
2579
- if stop or stopLossTakeProfit:
2580
- request['state'] = 'NOT_TRIGGERED'
2581
- elif subType is not None:
2582
- request['state'] = 'NEW'
2583
- elif status == 'closed':
2584
- if stop or stopLossTakeProfit:
2585
- request['state'] = 'TRIGGERED'
2586
- else:
2587
- request['state'] = 'FILLED'
2588
- elif status == 'canceled':
2589
- if stop or stopLossTakeProfit:
2590
- request['state'] = 'USER_REVOCATION'
2591
- else:
2592
- request['state'] = 'CANCELED'
2593
- else:
2594
- request['state'] = status
2595
- if stop or stopLossTakeProfit or (subType is not None) or (type == 'swap') or (type == 'future'):
2596
- if since is not None:
2597
- request['startTime'] = since
2598
- if limit is not None:
2599
- request['size'] = limit
2600
- if stop:
2601
- params = self.omit(params, 'stop')
2602
- if subType == 'inverse':
2603
- response = self.privateInverseGetFutureTradeV1EntrustPlanList(self.extend(request, params))
2604
- else:
2605
- response = self.privateLinearGetFutureTradeV1EntrustPlanList(self.extend(request, params))
2606
- elif stopLossTakeProfit:
2607
- params = self.omit(params, 'stopLossTakeProfit')
2608
- if subType == 'inverse':
2609
- response = self.privateInverseGetFutureTradeV1EntrustProfitList(self.extend(request, params))
2610
- else:
2611
- response = self.privateLinearGetFutureTradeV1EntrustProfitList(self.extend(request, params))
2612
- elif (subType is not None) or (type == 'swap') or (type == 'future'):
2613
- if subType == 'inverse':
2614
- response = self.privateInverseGetFutureTradeV1OrderList(self.extend(request, params))
2615
- else:
2616
- response = self.privateLinearGetFutureTradeV1OrderList(self.extend(request, params))
2617
- else:
2618
- marginMode = None
2619
- marginMode, params = self.handle_margin_mode_and_params('fetchOrdersByStatus', params)
2620
- marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
2621
- request['bizType'] = marginOrSpotRequest
2622
- if status != 'open':
2623
- if since is not None:
2624
- request['startTime'] = since
2625
- if limit is not None:
2626
- request['limit'] = limit
2627
- response = self.privateSpotGetHistoryOrder(self.extend(request, params))
2628
- else:
2629
- response = self.privateSpotGetOpenOrder(self.extend(request, params))
2630
- #
2631
- # spot and margin
2632
- #
2633
- # {
2634
- # "rc": 0,
2635
- # "mc": "SUCCESS",
2636
- # "ma": [],
2637
- # "result": {
2638
- # "hasPrev": False,
2639
- # "hasNext": True,
2640
- # "items": [
2641
- # {
2642
- # "symbol": "btc_usdt",
2643
- # "orderId": "207505997850909952",
2644
- # "clientOrderId": null,
2645
- # "baseCurrency": "btc",
2646
- # "quoteCurrency": "usdt",
2647
- # "side": "BUY",
2648
- # "type": "LIMIT",
2649
- # "timeInForce": "GTC",
2650
- # "price": "20000.00",
2651
- # "origQty": "0.001000",
2652
- # "origQuoteQty": "20.00",
2653
- # "executedQty": "0.000000",
2654
- # "leavingQty": "0.000000",
2655
- # "tradeBase": "0.000000",
2656
- # "tradeQuote": "0.00",
2657
- # "avgPrice": null,
2658
- # "fee": null,
2659
- # "feeCurrency": null,
2660
- # "closed": True,
2661
- # "state": "CANCELED",
2662
- # "time": 1679175285162,
2663
- # "updatedTime": 1679175488492
2664
- # },
2665
- # ]
2666
- # }
2667
- # }
2668
- #
2669
- # spot and margin: fetchOpenOrders
2670
- #
2671
- # {
2672
- # "rc": 0,
2673
- # "mc": "SUCCESS",
2674
- # "ma": [],
2675
- # "result": [
2676
- # {
2677
- # "symbol": "eth_usdt",
2678
- # "orderId": "208249323222264320",
2679
- # "clientOrderId": null,
2680
- # "baseCurrency": "eth",
2681
- # "quoteCurrency": "usdt",
2682
- # "side": "BUY",
2683
- # "type": "LIMIT",
2684
- # "timeInForce": "GTC",
2685
- # "price": "1300.00",
2686
- # "origQty": "0.0032",
2687
- # "origQuoteQty": "4.16",
2688
- # "executedQty": "0.0000",
2689
- # "leavingQty": "0.0032",
2690
- # "tradeBase": "0.0000",
2691
- # "tradeQuote": "0.00",
2692
- # "avgPrice": null,
2693
- # "fee": null,
2694
- # "feeCurrency": null,
2695
- # "closed": False,
2696
- # "state": "NEW",
2697
- # "time": 1679352507741,
2698
- # "updatedTime": 1679352507869
2699
- # },
2700
- # ]
2701
- # }
2702
- #
2703
- # swap and future
2704
- #
2705
- # {
2706
- # "returnCode": 0,
2707
- # "msgInfo": "success",
2708
- # "error": null,
2709
- # "result": {
2710
- # "page": 1,
2711
- # "ps": 10,
2712
- # "total": 25,
2713
- # "items": [
2714
- # {
2715
- # "orderId": "207519546930995456",
2716
- # "clientOrderId": null,
2717
- # "symbol": "btc_usdt",
2718
- # "orderType": "LIMIT",
2719
- # "orderSide": "BUY",
2720
- # "positionSide": "LONG",
2721
- # "timeInForce": "GTC",
2722
- # "closePosition": False,
2723
- # "price": "20000",
2724
- # "origQty": "100",
2725
- # "avgPrice": "0",
2726
- # "executedQty": "0",
2727
- # "marginFrozen": "4.12",
2728
- # "remark": null,
2729
- # "triggerProfitPrice": null,
2730
- # "triggerStopPrice": null,
2731
- # "sourceId": null,
2732
- # "sourceType": "DEFAULT",
2733
- # "forceClose": False,
2734
- # "closeProfit": null,
2735
- # "state": "CANCELED",
2736
- # "createdTime": 1679178515689,
2737
- # "updatedTime": 1679180096172
2738
- # },
2739
- # ]
2740
- # }
2741
- # }
2742
- #
2743
- # stop
2744
- #
2745
- # {
2746
- # "returnCode": 0,
2747
- # "msgInfo": "success",
2748
- # "error": null,
2749
- # "result": {
2750
- # "page": 1,
2751
- # "ps": 3,
2752
- # "total": 8,
2753
- # "items": [
2754
- # {
2755
- # "entrustId": "216300248132756992",
2756
- # "symbol": "btc_usdt",
2757
- # "entrustType": "STOP",
2758
- # "orderSide": "SELL",
2759
- # "positionSide": "SHORT",
2760
- # "timeInForce": "GTC",
2761
- # "closePosition": null,
2762
- # "price": "20000",
2763
- # "origQty": "1",
2764
- # "stopPrice": "19000",
2765
- # "triggerPriceType": "LATEST_PRICE",
2766
- # "state": "USER_REVOCATION",
2767
- # "marketOrderLevel": null,
2768
- # "createdTime": 1681271998064,
2769
- # "updatedTime": 1681273188674,
2770
- # "ordinary": False
2771
- # },
2772
- # ]
2773
- # }
2774
- # }
2775
- #
2776
- # stop-loss and take-profit
2777
- #
2778
- # {
2779
- # "returnCode": 0,
2780
- # "msgInfo": "success",
2781
- # "error": null,
2782
- # "result": {
2783
- # "page": 1,
2784
- # "ps": 3,
2785
- # "total": 2,
2786
- # "items": [
2787
- # {
2788
- # "profitId": "216306213226230400",
2789
- # "symbol": "btc_usdt",
2790
- # "positionSide": "LONG",
2791
- # "origQty": "1",
2792
- # "triggerPriceType": "LATEST_PRICE",
2793
- # "triggerProfitPrice": null,
2794
- # "triggerStopPrice": "20000",
2795
- # "entryPrice": "0",
2796
- # "positionSize": "0",
2797
- # "isolatedMargin": "0",
2798
- # "executedQty": "0",
2799
- # "avgPrice": null,
2800
- # "positionType": "ISOLATED",
2801
- # "state": "USER_REVOCATION",
2802
- # "createdTime": 1681273420039
2803
- # },
2804
- # ]
2805
- # }
2806
- # }
2807
- #
2808
- isSpotOpenOrders = ((status == 'open') and (subType is None))
2809
- data = self.safe_value(response, 'result', {})
2810
- orders = self.safe_value(response, 'result', []) if isSpotOpenOrders else self.safe_value(data, 'items', [])
2811
- return self.parse_orders(orders, market, since, limit)
2812
-
2813
- def fetch_open_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
2814
- """
2815
- fetch all unfilled currently open orders
2816
- see https://doc.xt.com/#orderopenOrderGet
2817
- see https://doc.xt.com/#futures_ordergetOrders
2818
- see https://doc.xt.com/#futures_entrustgetPlan
2819
- see https://doc.xt.com/#futures_entrustgetProfit
2820
- :param str|None symbol: unified market symbol of the market the orders were made in
2821
- :param int|None since: timestamp in ms of the earliest order
2822
- :param int|None limit: the maximum number of open order structures to retrieve
2823
- :param dict params: extra parameters specific to the xt api endpoint
2824
- :param bool|None params['stop']: if the order is a stop trigger order or not
2825
- :param bool|None params['stopLossTakeProfit']: if the order is a stop-loss or take-profit order
2826
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
2827
- """
2828
- return self.fetch_orders_by_status('open', symbol, since, limit, params)
2829
-
2830
- def fetch_closed_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
2831
- """
2832
- fetches information on multiple closed orders made by the user
2833
- see https://doc.xt.com/#orderhistoryOrderGet
2834
- see https://doc.xt.com/#futures_ordergetOrders
2835
- see https://doc.xt.com/#futures_entrustgetPlan
2836
- see https://doc.xt.com/#futures_entrustgetProfit
2837
- :param str|None symbol: unified market symbol of the market the orders were made in
2838
- :param int|None since: timestamp in ms of the earliest order
2839
- :param int|None limit: the maximum number of order structures to retrieve
2840
- :param dict params: extra parameters specific to the xt api endpoint
2841
- :param bool|None params['stop']: if the order is a stop trigger order or not
2842
- :param bool|None params['stopLossTakeProfit']: if the order is a stop-loss or take-profit order
2843
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
2844
- """
2845
- return self.fetch_orders_by_status('closed', symbol, since, limit, params)
2846
-
2847
- def fetch_canceled_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
2848
- """
2849
- fetches information on multiple canceled orders made by the user
2850
- see https://doc.xt.com/#orderhistoryOrderGet
2851
- see https://doc.xt.com/#futures_ordergetOrders
2852
- see https://doc.xt.com/#futures_entrustgetPlan
2853
- see https://doc.xt.com/#futures_entrustgetProfit
2854
- :param str|None symbol: unified market symbol of the market the orders were made in
2855
- :param int|None since: timestamp in ms of the earliest order
2856
- :param int|None limit: the maximum number of order structures to retrieve
2857
- :param dict params: extra parameters specific to the xt api endpoint
2858
- :param bool|None params['stop']: if the order is a stop trigger order or not
2859
- :param bool|None params['stopLossTakeProfit']: if the order is a stop-loss or take-profit order
2860
- :returns dict: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
2861
- """
2862
- return self.fetch_orders_by_status('canceled', symbol, since, limit, params)
2863
-
2864
- def cancel_order(self, id: str, symbol: Optional[str] = None, params={}):
2865
- """
2866
- cancels an open order
2867
- see https://doc.xt.com/#orderorderDel
2868
- see https://doc.xt.com/#futures_ordercancel
2869
- see https://doc.xt.com/#futures_entrustcancelPlan
2870
- see https://doc.xt.com/#futures_entrustcancelProfit
2871
- :param str id: order id
2872
- :param str|None symbol: unified symbol of the market the order was made in
2873
- :param dict params: extra parameters specific to the xt api endpoint
2874
- :param bool|None params['stop']: if the order is a stop trigger order or not
2875
- :param bool|None params['stopLossTakeProfit']: if the order is a stop-loss or take-profit order
2876
- :returns dict: An `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
2877
- """
2878
- self.load_markets()
2879
- market = None
2880
- if symbol is not None:
2881
- market = self.market(symbol)
2882
- request = {}
2883
- type = None
2884
- subType = None
2885
- response = None
2886
- type, params = self.handle_market_type_and_params('cancelOrder', market, params)
2887
- subType, params = self.handle_sub_type_and_params('cancelOrder', market, params)
2888
- stop = self.safe_value(params, 'stop')
2889
- stopLossTakeProfit = self.safe_value(params, 'stopLossTakeProfit')
2890
- if stop:
2891
- request['entrustId'] = id
2892
- elif stopLossTakeProfit:
2893
- request['profitId'] = id
2894
- else:
2895
- request['orderId'] = id
2896
- if stop:
2897
- params = self.omit(params, 'stop')
2898
- if subType == 'inverse':
2899
- response = self.privateInversePostFutureTradeV1EntrustCancelPlan(self.extend(request, params))
2900
- else:
2901
- response = self.privateLinearPostFutureTradeV1EntrustCancelPlan(self.extend(request, params))
2902
- elif stopLossTakeProfit:
2903
- params = self.omit(params, 'stopLossTakeProfit')
2904
- if subType == 'inverse':
2905
- response = self.privateInversePostFutureTradeV1EntrustCancelProfitStop(self.extend(request, params))
2906
- else:
2907
- response = self.privateLinearPostFutureTradeV1EntrustCancelProfitStop(self.extend(request, params))
2908
- elif subType == 'inverse':
2909
- response = self.privateInversePostFutureTradeV1OrderCancel(self.extend(request, params))
2910
- elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
2911
- response = self.privateLinearPostFutureTradeV1OrderCancel(self.extend(request, params))
2912
- else:
2913
- response = self.privateSpotDeleteOrderOrderId(self.extend(request, params))
2914
- #
2915
- # spot
2916
- #
2917
- # {
2918
- # "rc": 0,
2919
- # "mc": "SUCCESS",
2920
- # "ma": [],
2921
- # "result": {
2922
- # "cancelId": "208322474307982720"
2923
- # }
2924
- # }
2925
- #
2926
- # swap and future
2927
- #
2928
- # {
2929
- # "returnCode": 0,
2930
- # "msgInfo": "success",
2931
- # "error": null,
2932
- # "result": "208319789679471616"
2933
- # }
2934
- #
2935
- isContractResponse = ((subType is not None) or (type == 'swap') or (type == 'future'))
2936
- order = response if isContractResponse else self.safe_value(response, 'result', {})
2937
- return self.parse_order(order, market)
2938
-
2939
- def cancel_all_orders(self, symbol: Optional[str] = None, params={}):
2940
- """
2941
- cancel all open orders in a market
2942
- see https://doc.xt.com/#orderopenOrderDel
2943
- see https://doc.xt.com/#futures_ordercancelBatch
2944
- see https://doc.xt.com/#futures_entrustcancelPlanBatch
2945
- see https://doc.xt.com/#futures_entrustcancelProfitBatch
2946
- :param str|None symbol: unified market symbol of the market to cancel orders in
2947
- :param dict params: extra parameters specific to the xt api endpoint
2948
- :param bool|None params['stop']: if the order is a stop trigger order or not
2949
- :param bool|None params['stopLossTakeProfit']: if the order is a stop-loss or take-profit order
2950
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
2951
- """
2952
- self.load_markets()
2953
- request = {}
2954
- market = None
2955
- if symbol is not None:
2956
- market = self.market(symbol)
2957
- request['symbol'] = market['id']
2958
- type = None
2959
- subType = None
2960
- response = None
2961
- type, params = self.handle_market_type_and_params('cancelAllOrders', market, params)
2962
- subType, params = self.handle_sub_type_and_params('cancelAllOrders', market, params)
2963
- stop = self.safe_value(params, 'stop')
2964
- stopLossTakeProfit = self.safe_value(params, 'stopLossTakeProfit')
2965
- if stop:
2966
- params = self.omit(params, 'stop')
2967
- if subType == 'inverse':
2968
- response = self.privateInversePostFutureTradeV1EntrustCancelAllPlan(self.extend(request, params))
2969
- else:
2970
- response = self.privateLinearPostFutureTradeV1EntrustCancelAllPlan(self.extend(request, params))
2971
- elif stopLossTakeProfit:
2972
- params = self.omit(params, 'stopLossTakeProfit')
2973
- if subType == 'inverse':
2974
- response = self.privateInversePostFutureTradeV1EntrustCancelAllProfitStop(self.extend(request, params))
2975
- else:
2976
- response = self.privateLinearPostFutureTradeV1EntrustCancelAllProfitStop(self.extend(request, params))
2977
- elif subType == 'inverse':
2978
- response = self.privateInversePostFutureTradeV1OrderCancelAll(self.extend(request, params))
2979
- elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
2980
- response = self.privateLinearPostFutureTradeV1OrderCancelAll(self.extend(request, params))
2981
- else:
2982
- marginMode = None
2983
- marginMode, params = self.handle_margin_mode_and_params('cancelAllOrders', params)
2984
- marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
2985
- request['bizType'] = marginOrSpotRequest
2986
- response = self.privateSpotDeleteOpenOrder(self.extend(request, params))
2987
- #
2988
- # spot and margin
2989
- #
2990
- # {
2991
- # "rc": 0,
2992
- # "mc": "SUCCESS",
2993
- # "ma": [],
2994
- # "result": null
2995
- # }
2996
- #
2997
- # swap and future
2998
- #
2999
- # {
3000
- # "returnCode": 0,
3001
- # "msgInfo": "success",
3002
- # "error": null,
3003
- # "result": True
3004
- # }
3005
- #
3006
- return response
3007
-
3008
- def cancel_orders(self, ids: List[str], symbol: Optional[str] = None, params={}):
3009
- """
3010
- cancel multiple orders
3011
- see https://doc.xt.com/#orderbatchOrderDel
3012
- :param [str] ids: order ids
3013
- :param str|None symbol: unified market symbol of the market to cancel orders in
3014
- :param dict params: extra parameters specific to the xt api endpoint
3015
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
3016
- """
3017
- self.load_markets()
3018
- request = {
3019
- 'orderIds': ids,
3020
- }
3021
- market = None
3022
- if symbol is not None:
3023
- market = self.market(symbol)
3024
- subType = None
3025
- subType, params = self.handle_sub_type_and_params('cancelOrders', market, params)
3026
- if subType is not None:
3027
- raise NotSupported(self.id + ' cancelOrders() does not support swap and future orders, only spot orders are accepted')
3028
- response = self.privateSpotDeleteBatchOrder(self.extend(request, params))
3029
- #
3030
- # spot
3031
- #
3032
- # {
3033
- # "rc": 0,
3034
- # "mc": "SUCCESS",
3035
- # "ma": [],
3036
- # "result": null
3037
- # }
3038
- #
3039
- return response
3040
-
3041
- def parse_order(self, order, market=None):
3042
- #
3043
- # spot: createOrder
3044
- #
3045
- # {
3046
- # "orderId": "204371980095156544"
3047
- # }
3048
- #
3049
- # spot: cancelOrder
3050
- #
3051
- # {
3052
- # "cancelId": "208322474307982720"
3053
- # }
3054
- #
3055
- # swap and future: createOrder, cancelOrder
3056
- #
3057
- # {
3058
- # "returnCode": 0,
3059
- # "msgInfo": "success",
3060
- # "error": null,
3061
- # "result": "206410760006650176"
3062
- # }
3063
- #
3064
- # spot: fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
3065
- #
3066
- # {
3067
- # "symbol": "btc_usdt",
3068
- # "orderId": "207505997850909952",
3069
- # "clientOrderId": null,
3070
- # "baseCurrency": "btc",
3071
- # "quoteCurrency": "usdt",
3072
- # "side": "BUY",
3073
- # "type": "LIMIT",
3074
- # "timeInForce": "GTC",
3075
- # "price": "20000.00",
3076
- # "origQty": "0.001000",
3077
- # "origQuoteQty": "20.00",
3078
- # "executedQty": "0.000000",
3079
- # "leavingQty": "0.001000",
3080
- # "tradeBase": "0.000000",
3081
- # "tradeQuote": "0.00",
3082
- # "avgPrice": null,
3083
- # "fee": null,
3084
- # "feeCurrency": null,
3085
- # "closed": False,
3086
- # "state": "NEW",
3087
- # "time": 1679175285162,
3088
- # "updatedTime": 1679175285255
3089
- # }
3090
- #
3091
- # swap and future: fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
3092
- #
3093
- # {
3094
- # "orderId": "207519546930995456",
3095
- # "clientOrderId": null,
3096
- # "symbol": "btc_usdt",
3097
- # "orderType": "LIMIT",
3098
- # "orderSide": "BUY",
3099
- # "positionSide": "LONG",
3100
- # "timeInForce": "GTC",
3101
- # "closePosition": False,
3102
- # "price": "20000",
3103
- # "origQty": "100",
3104
- # "avgPrice": "0",
3105
- # "executedQty": "0",
3106
- # "marginFrozen": "4.12",
3107
- # "remark": null,
3108
- # "triggerProfitPrice": null,
3109
- # "triggerStopPrice": null,
3110
- # "sourceId": null,
3111
- # "sourceType": "DEFAULT",
3112
- # "forceClose": False,
3113
- # "closeProfit": null,
3114
- # "state": "CANCELED",
3115
- # "createdTime": 1679178515689,
3116
- # "updatedTime": 1679180096172
3117
- # }
3118
- #
3119
- # trigger: fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
3120
- #
3121
- # {
3122
- # "entrustId": "216300248132756992",
3123
- # "symbol": "btc_usdt",
3124
- # "entrustType": "STOP",
3125
- # "orderSide": "SELL",
3126
- # "positionSide": "SHORT",
3127
- # "timeInForce": "GTC",
3128
- # "closePosition": null,
3129
- # "price": "20000",
3130
- # "origQty": "1",
3131
- # "stopPrice": "19000",
3132
- # "triggerPriceType": "LATEST_PRICE",
3133
- # "state": "NOT_TRIGGERED",
3134
- # "marketOrderLevel": null,
3135
- # "createdTime": 1681271998064,
3136
- # "updatedTime": 1681271998064,
3137
- # "ordinary": False
3138
- # }
3139
- #
3140
- # stop-loss and take-profit: fetchOrder, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
3141
- #
3142
- # {
3143
- # "profitId": "216306213226230400",
3144
- # "symbol": "btc_usdt",
3145
- # "positionSide": "LONG",
3146
- # "origQty": "1",
3147
- # "triggerPriceType": "LATEST_PRICE",
3148
- # "triggerProfitPrice": null,
3149
- # "triggerStopPrice": "20000",
3150
- # "entryPrice": null,
3151
- # "positionSize": null,
3152
- # "isolatedMargin": null,
3153
- # "executedQty": null,
3154
- # "avgPrice": null,
3155
- # "positionType": "ISOLATED",
3156
- # "state": "NOT_TRIGGERED",
3157
- # "createdTime": 1681273420039
3158
- # }
3159
- #
3160
- marketId = self.safe_string(order, 'symbol')
3161
- marketType = ('result' in order) or 'contract' if ('positionSide' in order) else 'spot'
3162
- market = self.safe_market(marketId, market, None, marketType)
3163
- symbol = self.safe_symbol(marketId, market, None, marketType)
3164
- timestamp = self.safe_integer_2(order, 'time', 'createdTime')
3165
- quantity = self.safe_number(order, 'origQty')
3166
- amount = quantity if (marketType == 'spot') else Precise.string_mul(self.number_to_string(quantity), self.number_to_string(market['contractSize']))
3167
- filledQuantity = self.safe_number(order, 'executedQty')
3168
- filled = filledQuantity if (marketType == 'spot') else Precise.string_mul(self.number_to_string(filledQuantity), self.number_to_string(market['contractSize']))
3169
- lastUpdatedTimestamp = self.safe_integer(order, 'updatedTime')
3170
- return self.safe_order({
3171
- 'info': order,
3172
- 'id': self.safe_string_n(order, ['orderId', 'result', 'cancelId', 'entrustId', 'profitId']),
3173
- 'clientOrderId': self.safe_string(order, 'clientOrderId'),
3174
- 'timestamp': timestamp,
3175
- 'datetime': self.iso8601(timestamp),
3176
- 'lastTradeTimestamp': lastUpdatedTimestamp,
3177
- 'lastUpdateTimestamp': lastUpdatedTimestamp,
3178
- 'symbol': symbol,
3179
- 'type': self.safe_string_lower_2(order, 'type', 'orderType'),
3180
- 'timeInForce': self.safe_string(order, 'timeInForce'),
3181
- 'postOnly': None,
3182
- 'side': self.safe_string_lower_2(order, 'side', 'orderSide'),
3183
- 'price': self.safe_number(order, 'price'),
3184
- 'stopPrice': self.safe_number(order, 'stopPrice'),
3185
- 'stopLoss': self.safe_number(order, 'triggerStopPrice'),
3186
- 'takeProfit': self.safe_number(order, 'triggerProfitPrice'),
3187
- 'amount': amount,
3188
- 'filled': filled,
3189
- 'remaining': self.safe_number(order, 'leavingQty'),
3190
- 'cost': None,
3191
- 'average': self.safe_number(order, 'avgPrice'),
3192
- 'status': self.parse_order_status(self.safe_string(order, 'state')),
3193
- 'fee': {
3194
- 'currency': self.safe_currency_code(self.safe_string(order, 'feeCurrency')),
3195
- 'cost': self.safe_number(order, 'fee'),
3196
- },
3197
- 'trades': None,
3198
- }, market)
3199
-
3200
- def parse_order_status(self, status):
3201
- statuses = {
3202
- 'NEW': 'open',
3203
- 'PARTIALLY_FILLED': 'open',
3204
- 'FILLED': 'closed',
3205
- 'CANCELED': 'canceled',
3206
- 'REJECTED': 'rejected',
3207
- 'EXPIRED': 'expired',
3208
- 'UNFINISHED': 'open',
3209
- 'NOT_TRIGGERED': 'open',
3210
- 'TRIGGERING': 'open',
3211
- 'TRIGGERED': 'closed',
3212
- 'USER_REVOCATION': 'canceled',
3213
- 'PLATFORM_REVOCATION': 'rejected',
3214
- 'HISTORY': 'expired',
3215
- }
3216
- return self.safe_string(statuses, status, status)
3217
-
3218
- def fetch_ledger(self, code: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
3219
- """
3220
- fetch the history of changes, actions done by the user or operations that altered the balance of the user
3221
- see https://doc.xt.com/#futures_usergetBalanceBill
3222
- :param str|None code: unified currency code
3223
- :param int|None since: timestamp in ms of the earliest ledger entry
3224
- :param int|None limit: max number of ledger entries to return
3225
- :param dict params: extra parameters specific to the xt api endpoint
3226
- :returns dict: a `ledger structure <https://docs.ccxt.com/en/latest/manual.html#ledger-structure>`
3227
- """
3228
- self.load_markets()
3229
- request = {}
3230
- currency = None
3231
- if code is not None:
3232
- currency = self.currency(code)
3233
- if since is not None:
3234
- request['startTime'] = since
3235
- if limit is not None:
3236
- request['limit'] = limit
3237
- type = None
3238
- subType = None
3239
- response = None
3240
- type, params = self.handle_market_type_and_params('fetchLedger', None, params)
3241
- subType, params = self.handle_sub_type_and_params('fetchLedger', None, params)
3242
- if subType == 'inverse':
3243
- response = self.privateInverseGetFutureUserV1BalanceBills(self.extend(request, params))
3244
- elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
3245
- response = self.privateLinearGetFutureUserV1BalanceBills(self.extend(request, params))
3246
- else:
3247
- raise NotSupported(self.id + ' fetchLedger() does not support spot transactions, only swap and future wallet transactions are supported')
3248
- #
3249
- # {
3250
- # "returnCode": 0,
3251
- # "msgInfo": "success",
3252
- # "error": null,
3253
- # "result": {
3254
- # "hasPrev": False,
3255
- # "hasNext": False,
3256
- # "items": [
3257
- # {
3258
- # "id": "207260567109387524",
3259
- # "coin": "usdt",
3260
- # "symbol": "btc_usdt",
3261
- # "type": "FEE",
3262
- # "amount": "-0.0213",
3263
- # "side": "SUB",
3264
- # "afterAmount": null,
3265
- # "createdTime": 1679116769914
3266
- # },
3267
- # ]
3268
- # }
3269
- # }
3270
- #
3271
- data = self.safe_value(response, 'result', {})
3272
- ledger = self.safe_value(data, 'items', [])
3273
- return self.parse_ledger(ledger, currency, since, limit)
3274
-
3275
- def parse_ledger_entry(self, item, currency=None):
3276
- #
3277
- # {
3278
- # "id": "207260567109387524",
3279
- # "coin": "usdt",
3280
- # "symbol": "btc_usdt",
3281
- # "type": "FEE",
3282
- # "amount": "-0.0213",
3283
- # "side": "SUB",
3284
- # "afterAmount": null,
3285
- # "createdTime": 1679116769914
3286
- # }
3287
- #
3288
- side = self.safe_string(item, 'side')
3289
- direction = 'in' if (side == 'ADD') else 'out'
3290
- currencyId = self.safe_string(item, 'coin')
3291
- timestamp = self.safe_integer(item, 'createdTime')
3292
- return {
3293
- 'id': self.safe_string(item, 'id'),
3294
- 'direction': direction,
3295
- 'account': None,
3296
- 'referenceId': None,
3297
- 'referenceAccount': None,
3298
- 'type': self.parse_ledger_entry_type(self.safe_string(item, 'type')),
3299
- 'currency': self.safe_currency_code(currencyId, currency),
3300
- 'amount': self.safe_number(item, 'amount'),
3301
- 'timestamp': timestamp,
3302
- 'datetime': self.iso8601(timestamp),
3303
- 'before': None,
3304
- 'after': self.safe_number(item, 'afterAmount'),
3305
- 'status': None,
3306
- 'fee': {
3307
- 'currency': None,
3308
- 'cost': None,
3309
- },
3310
- 'info': item,
3311
- }
3312
-
3313
- def parse_ledger_entry_type(self, type):
3314
- ledgerType = {
3315
- 'EXCHANGE': 'transfer',
3316
- 'CLOSE_POSITION': 'trade',
3317
- 'TAKE_OVER': 'trade',
3318
- 'MERGE': 'trade',
3319
- 'QIANG_PING_MANAGER': 'fee',
3320
- 'FUND': 'fee',
3321
- 'FEE': 'fee',
3322
- 'ADL': 'auto-deleveraging',
3323
- }
3324
- return self.safe_string(ledgerType, type, type)
3325
-
3326
- def fetch_deposit_address(self, code: str, params={}):
3327
- """
3328
- fetch the deposit address for a currency associated with self account
3329
- see https://doc.xt.com/#deposit_withdrawaldepositAddressGet
3330
- :param str code: unified currency code
3331
- :param dict params: extra parameters specific to the xt api endpoint
3332
- :param str params['network']: required network id
3333
- :returns dict: an `address structure <https://docs.ccxt.com/en/latest/manual.html#address-structure>`
3334
- """
3335
- self.load_markets()
3336
- networkCode = None
3337
- networkCode, params = self.handle_network_code_and_params(params)
3338
- currency = self.currency(code)
3339
- networkId = self.network_code_to_id(networkCode, code)
3340
- self.check_required_argument('fetchDepositAddress', networkId, 'network')
3341
- request = {
3342
- 'currency': currency['id'],
3343
- 'chain': networkId,
3344
- }
3345
- response = self.privateSpotGetDepositAddress(self.extend(request, params))
3346
- #
3347
- # {
3348
- # "rc": 0,
3349
- # "mc": "SUCCESS",
3350
- # "ma": [],
3351
- # "result": {
3352
- # "address": "0x7f7173cf29d3846d20ca5a3aec1120b93dbd157a",
3353
- # "memo": ""
3354
- # }
3355
- # }
3356
- #
3357
- result = self.safe_value(response, 'result', {})
3358
- return self.parse_deposit_address(result, currency)
3359
-
3360
- def parse_deposit_address(self, depositAddress, currency=None):
3361
- #
3362
- # {
3363
- # "address": "0x7f7173cf29d3846d20ca5a3aec1120b93dbd157a",
3364
- # "memo": ""
3365
- # }
3366
- #
3367
- address = self.safe_string(depositAddress, 'address')
3368
- self.check_address(address)
3369
- return {
3370
- 'currency': self.safe_currency_code(None, currency),
3371
- 'address': address,
3372
- 'tag': self.safe_string(depositAddress, 'memo'),
3373
- 'network': None,
3374
- 'info': depositAddress,
3375
- }
3376
-
3377
- def fetch_deposits(self, code: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
3378
- """
3379
- fetch all deposits made to an account
3380
- see https://doc.xt.com/#deposit_withdrawalhistoryDepositGet
3381
- :param str|None code: unified currency code
3382
- :param int|None since: the earliest time in ms to fetch deposits for
3383
- :param int|None limit: the maximum number of transaction structures to retrieve
3384
- :param dict params: extra parameters specific to the xt api endpoint
3385
- :returns [dict]: a list of `transaction structures <https://docs.ccxt.com/en/latest/manual.html#transaction-structure>`
3386
- """
3387
- self.load_markets()
3388
- request = {}
3389
- currency = None
3390
- if code is not None:
3391
- currency = self.currency(code)
3392
- request['currency'] = currency['id']
3393
- if since is not None:
3394
- request['startTime'] = since
3395
- if limit is not None:
3396
- request['limit'] = limit # default 10, max 200
3397
- response = self.privateSpotGetDepositHistory(self.extend(request, params))
3398
- #
3399
- # {
3400
- # "rc": 0,
3401
- # "mc": "SUCCESS",
3402
- # "ma": [],
3403
- # "result": {
3404
- # "hasPrev": False,
3405
- # "hasNext": False,
3406
- # "items": [
3407
- # {
3408
- # "id": 170368702,
3409
- # "currency": "usdt",
3410
- # "chain": "Ethereum",
3411
- # "memo": "",
3412
- # "status": "SUCCESS",
3413
- # "amount": "31.792528",
3414
- # "confirmations": 12,
3415
- # "transactionId": "0x90b8487c258b81b85e15e461b1839c49d4d8e6e9de4c1adb658cd47d4f5c5321",
3416
- # "address": "0x7f7172cf29d3846d30ca5a3aec1120b92dbd150b",
3417
- # "fromAddr": "0x7830c87c02e56aff27fa9ab1241711331fa86f58",
3418
- # "createdTime": 1678491442000
3419
- # },
3420
- # ]
3421
- # }
3422
- # }
3423
- #
3424
- data = self.safe_value(response, 'result', {})
3425
- deposits = self.safe_value(data, 'items', [])
3426
- return self.parse_transactions(deposits, currency, since, limit, params)
3427
-
3428
- def fetch_withdrawals(self, code: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
3429
- """
3430
- fetch all withdrawals made from an account
3431
- see https://doc.xt.com/#deposit_withdrawalwithdrawHistory
3432
- :param str|None code: unified currency code
3433
- :param int|None since: the earliest time in ms to fetch withdrawals for
3434
- :param int|None limit: the maximum number of transaction structures to retrieve
3435
- :param dict params: extra parameters specific to the xt api endpoint
3436
- :returns [dict]: a list of `transaction structures <https://docs.ccxt.com/en/latest/manual.html#transaction-structure>`
3437
- """
3438
- self.load_markets()
3439
- request = {}
3440
- currency = None
3441
- if code is not None:
3442
- currency = self.currency(code)
3443
- request['currency'] = currency['id']
3444
- if since is not None:
3445
- request['startTime'] = since
3446
- if limit is not None:
3447
- request['limit'] = limit # default 10, max 200
3448
- response = self.privateSpotGetWithdrawHistory(self.extend(request, params))
3449
- #
3450
- # {
3451
- # "rc": 0,
3452
- # "mc": "SUCCESS",
3453
- # "ma": [],
3454
- # "result": {
3455
- # "hasPrev": False,
3456
- # "hasNext": False,
3457
- # "items": [
3458
- # {
3459
- # "id": 950898,
3460
- # "currency": "usdt",
3461
- # "chain": "Tron",
3462
- # "address": "TGB2vxTjiqraVZBy7YHXF8V3CSMVhQKcaf",
3463
- # "memo": "",
3464
- # "status": "SUCCESS",
3465
- # "amount": "5",
3466
- # "fee": "2",
3467
- # "confirmations": 6,
3468
- # "transactionId": "c36e230b879842b1d7afd19d15ee1a866e26eaa0626e367d6f545d2932a15156",
3469
- # "createdTime": 1680049062000
3470
- # }
3471
- # ]
3472
- # }
3473
- # }
3474
- #
3475
- data = self.safe_value(response, 'result', {})
3476
- withdrawals = self.safe_value(data, 'items', [])
3477
- return self.parse_transactions(withdrawals, currency, since, limit, params)
3478
-
3479
- def withdraw(self, code: str, amount, address, tag=None, params={}):
3480
- """
3481
- make a withdrawal
3482
- see https://doc.xt.com/#deposit_withdrawalwithdraw
3483
- :param str code: unified currency code
3484
- :param float amount: the amount to withdraw
3485
- :param str address: the address to withdraw to
3486
- :param str|None tag:
3487
- :param dict params: extra parameters specific to the xt api endpoint
3488
- :returns dict: a `transaction structure <https://docs.ccxt.com/en/latest/manual.html#transaction-structure>`
3489
- """
3490
- self.check_address(address)
3491
- self.load_markets()
3492
- currency = self.currency(code)
3493
- tag, params = self.handle_withdraw_tag_and_params(tag, params)
3494
- networkCode = None
3495
- networkCode, params = self.handle_network_code_and_params(params)
3496
- networkIdsByCodes = self.safe_value(self.options, 'networks', {})
3497
- networkId = self.safe_string_2(networkIdsByCodes, networkCode, code, code)
3498
- request = {
3499
- 'currency': currency['id'],
3500
- 'chain': networkId,
3501
- 'amount': self.currency_to_precision(code, amount),
3502
- 'address': address,
3503
- }
3504
- if tag is not None:
3505
- request['memo'] = tag
3506
- response = self.privateSpotPostWithdraw(self.extend(request, params))
3507
- #
3508
- # {
3509
- # "rc": 0,
3510
- # "mc": "SUCCESS",
3511
- # "ma": [],
3512
- # "result": {
3513
- # "id": 950898
3514
- # }
3515
- # }
3516
- #
3517
- result = self.safe_value(response, 'result', {})
3518
- return self.parse_transaction(result, currency)
3519
-
3520
- def parse_transaction(self, transaction, currency=None):
3521
- #
3522
- # fetchDeposits
3523
- #
3524
- # {
3525
- # "id": 170368702,
3526
- # "currency": "usdt",
3527
- # "chain": "Ethereum",
3528
- # "memo": "",
3529
- # "status": "SUCCESS",
3530
- # "amount": "31.792528",
3531
- # "confirmations": 12,
3532
- # "transactionId": "0x90b8487c258b81b85e15e461b1839c49d4d8e6e9de4c1adb658cd47d4f5c5321",
3533
- # "address": "0x7f7172cf29d3846d30ca5a3aec1120b92dbd150b",
3534
- # "fromAddr": "0x7830c87c02e56aff27fa9ab1241711331fa86f58",
3535
- # "createdTime": 1678491442000
3536
- # }
3537
- #
3538
- # fetchWithdrawals
3539
- #
3540
- # {
3541
- # "id": 950898,
3542
- # "currency": "usdt",
3543
- # "chain": "Tron",
3544
- # "address": "TGB2vxTjiqraVZBy7YHXF8V3CSMVhQKcaf",
3545
- # "memo": "",
3546
- # "status": "SUCCESS",
3547
- # "amount": "5",
3548
- # "fee": "2",
3549
- # "confirmations": 6,
3550
- # "transactionId": "c36e230b879842b1d7afd19d15ee1a866e26eaa0626e367d6f545d2932a15156",
3551
- # "createdTime": 1680049062000
3552
- # }
3553
- #
3554
- # withdraw
3555
- #
3556
- # {
3557
- # "id": 950898
3558
- # }
3559
- #
3560
- type = 'deposit' if ('fromAddr' in transaction) else 'withdraw'
3561
- timestamp = self.safe_integer(transaction, 'createdTime')
3562
- address = self.safe_string(transaction, 'address')
3563
- memo = self.safe_string(transaction, 'memo')
3564
- currencyCode = self.safe_currency_code(self.safe_string(transaction, 'currency'), currency)
3565
- fee = self.safe_number(transaction, 'fee')
3566
- feeCurrency = currencyCode if (fee is not None) else None
3567
- networkId = self.safe_string(transaction, 'chain')
3568
- return {
3569
- 'info': transaction,
3570
- 'id': self.safe_string(transaction, 'id'),
3571
- 'txid': self.safe_string(transaction, 'transactionId'),
3572
- 'timestamp': timestamp,
3573
- 'datetime': self.iso8601(timestamp),
3574
- 'updated': None,
3575
- 'addressFrom': self.safe_string(transaction, 'fromAddr'),
3576
- 'addressTo': address,
3577
- 'address': address,
3578
- 'tagFrom': None,
3579
- 'tagTo': None,
3580
- 'tag': memo,
3581
- 'type': type,
3582
- 'amount': self.safe_number(transaction, 'amount'),
3583
- 'currency': currencyCode,
3584
- 'network': self.network_id_to_code(networkId, currencyCode),
3585
- 'status': self.parse_transaction_status(self.safe_string(transaction, 'status')),
3586
- 'comment': memo,
3587
- 'fee': {
3588
- 'currency': feeCurrency,
3589
- 'cost': fee,
3590
- 'rate': None,
3591
- },
3592
- }
3593
-
3594
- def parse_transaction_status(self, status):
3595
- statuses = {
3596
- 'SUBMIT': 'pending',
3597
- 'REVIEW': 'pending',
3598
- 'AUDITED': 'pending',
3599
- 'PENDING': 'pending',
3600
- 'CANCEL': 'canceled',
3601
- 'FAIL': 'failed',
3602
- 'SUCCESS': 'ok',
3603
- }
3604
- return self.safe_string(statuses, status, status)
3605
-
3606
- def set_leverage(self, leverage, symbol: Optional[str] = None, params={}):
3607
- """
3608
- set the level of leverage for a market
3609
- see https://doc.xt.com/#futures_useradjustLeverage
3610
- :param float leverage: the rate of leverage
3611
- :param str symbol: unified market symbol
3612
- :param dict params: extra parameters specific to the xt api endpoint
3613
- :param str params['positionSide']: 'LONG' or 'SHORT'
3614
- :returns dict: response from the exchange
3615
- """
3616
- self.check_required_symbol('setLeverage', symbol)
3617
- positionSide = self.safe_string(params, 'positionSide')
3618
- self.check_required_argument('setLeverage', positionSide, 'positionSide', ['LONG', 'SHORT'])
3619
- if (leverage < 1) or (leverage > 125):
3620
- raise BadRequest(self.id + ' setLeverage() leverage should be between 1 and 125')
3621
- self.load_markets()
3622
- market = self.market(symbol)
3623
- if not (market['contract']):
3624
- raise BadSymbol(self.id + ' setLeverage() supports contract markets only')
3625
- request = {
3626
- 'symbol': market['id'],
3627
- 'positionSide': positionSide,
3628
- 'leverage': leverage,
3629
- }
3630
- subType = None
3631
- subType, params = self.handle_sub_type_and_params('setLeverage', market, params)
3632
- response = None
3633
- if subType == 'inverse':
3634
- response = self.privateInversePostFutureUserV1PositionAdjustLeverage(self.extend(request, params))
3635
- else:
3636
- response = self.privateLinearPostFutureUserV1PositionAdjustLeverage(self.extend(request, params))
3637
- #
3638
- # {
3639
- # "returnCode": 0,
3640
- # "msgInfo": "success",
3641
- # "error": null,
3642
- # "result": null
3643
- # }
3644
- #
3645
- return response
3646
-
3647
- def add_margin(self, symbol: str, amount, params={}):
3648
- """
3649
- add margin to a position
3650
- see https://doc.xt.com/#futures_useradjustMargin
3651
- :param str symbol: unified market symbol
3652
- :param float amount: amount of margin to add
3653
- :param dict params: extra parameters specific to the xt api endpoint
3654
- :param str params['positionSide']: 'LONG' or 'SHORT'
3655
- :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
3656
- """
3657
- return self.modify_margin_helper(symbol, amount, 'ADD', params)
3658
-
3659
- def reduce_margin(self, symbol: str, amount, params={}):
3660
- """
3661
- remove margin from a position
3662
- see https://doc.xt.com/#futures_useradjustMargin
3663
- :param str symbol: unified market symbol
3664
- :param float amount: the amount of margin to remove
3665
- :param dict params: extra parameters specific to the xt api endpoint
3666
- :param str params['positionSide']: 'LONG' or 'SHORT'
3667
- :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
3668
- """
3669
- return self.modify_margin_helper(symbol, amount, 'SUB', params)
3670
-
3671
- def modify_margin_helper(self, symbol: str, amount, addOrReduce, params={}):
3672
- positionSide = self.safe_string(params, 'positionSide')
3673
- self.check_required_argument('setLeverage', positionSide, 'positionSide', ['LONG', 'SHORT'])
3674
- self.load_markets()
3675
- market = self.market(symbol)
3676
- request = {
3677
- 'symbol': market['id'],
3678
- 'margin': amount,
3679
- 'type': addOrReduce,
3680
- 'positionSide': positionSide,
3681
- }
3682
- subType = None
3683
- subType, params = self.handle_sub_type_and_params('modifyMarginHelper', market, params)
3684
- response = None
3685
- if subType == 'inverse':
3686
- response = self.privateInversePostFutureUserV1PositionMargin(self.extend(request, params))
3687
- else:
3688
- response = self.privateLinearPostFutureUserV1PositionMargin(self.extend(request, params))
3689
- #
3690
- # {
3691
- # "returnCode": 0,
3692
- # "msgInfo": "success",
3693
- # "error": null,
3694
- # "result": null
3695
- # }
3696
- #
3697
- return self.parse_margin_modification(response, market)
3698
-
3699
- def parse_margin_modification(self, data, market=None):
3700
- return {
3701
- 'info': data,
3702
- 'type': None,
3703
- 'amount': None,
3704
- 'code': None,
3705
- 'symbol': self.safe_symbol(None, market),
3706
- 'status': None,
3707
- }
3708
-
3709
- def fetch_leverage_tiers(self, symbols: Optional[List[str]] = None, params={}):
3710
- """
3711
- see https://doc.xt.com/#futures_quotesgetLeverageBrackets
3712
- retrieve information on the maximum leverage for different trade sizes
3713
- :param [str]|None symbols: a list of unified market symbols
3714
- :param dict params: extra parameters specific to the xt api endpoint
3715
- :returns dict: a dictionary of `leverage tiers structures <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`
3716
- """
3717
- self.load_markets()
3718
- subType = None
3719
- subType, params = self.handle_sub_type_and_params('fetchLeverageTiers', None, params)
3720
- response = None
3721
- if subType == 'inverse':
3722
- response = self.publicInverseGetFutureMarketV1PublicLeverageBracketList(params)
3723
- else:
3724
- response = self.publicLinearGetFutureMarketV1PublicLeverageBracketList(params)
3725
- #
3726
- # {
3727
- # "returnCode": 0,
3728
- # "msgInfo": "success",
3729
- # "error": null,
3730
- # "result": [
3731
- # {
3732
- # "symbol": "rad_usdt",
3733
- # "leverageBrackets": [
3734
- # {
3735
- # "symbol": "rad_usdt",
3736
- # "bracket": 1,
3737
- # "maxNominalValue": "5000",
3738
- # "maintMarginRate": "0.025",
3739
- # "startMarginRate": "0.05",
3740
- # "maxStartMarginRate": null,
3741
- # "maxLeverage": "20",
3742
- # "minLeverage": "1"
3743
- # },
3744
- # ]
3745
- # },
3746
- # ]
3747
- # }
3748
- #
3749
- data = self.safe_value(response, 'result', [])
3750
- symbols = self.market_symbols(symbols)
3751
- return self.parse_leverage_tiers(data, symbols, 'symbol')
3752
-
3753
- def parse_leverage_tiers(self, response, symbols=None, marketIdKey=None):
3754
- #
3755
- # {
3756
- # "symbol": "rad_usdt",
3757
- # "leverageBrackets": [
3758
- # {
3759
- # "symbol": "rad_usdt",
3760
- # "bracket": 1,
3761
- # "maxNominalValue": "5000",
3762
- # "maintMarginRate": "0.025",
3763
- # "startMarginRate": "0.05",
3764
- # "maxStartMarginRate": null,
3765
- # "maxLeverage": "20",
3766
- # "minLeverage": "1"
3767
- # },
3768
- # ]
3769
- # }
3770
- #
3771
- result = {}
3772
- for i in range(0, len(response)):
3773
- entry = response[i]
3774
- marketId = self.safe_string(entry, 'symbol')
3775
- market = self.safe_market(marketId, None, '_', 'contract')
3776
- symbol = self.safe_symbol(marketId, market)
3777
- if symbols is not None:
3778
- if self.in_array(symbol, symbols):
3779
- result[symbol] = self.parse_market_leverage_tiers(entry, market)
3780
- else:
3781
- result[symbol] = self.parse_market_leverage_tiers(response[i], market)
3782
- return result
3783
-
3784
- def fetch_market_leverage_tiers(self, symbol: str, params={}):
3785
- """
3786
- see https://doc.xt.com/#futures_quotesgetLeverageBracket
3787
- retrieve information on the maximum leverage for different trade sizes of a single market
3788
- :param str symbol: unified market symbol
3789
- :param dict params: extra parameters specific to the xt api endpoint
3790
- :returns dict: a `leverage tiers structure <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`
3791
- """
3792
- self.load_markets()
3793
- market = self.market(symbol)
3794
- request = {
3795
- 'symbol': market['id'],
3796
- }
3797
- subType = None
3798
- subType, params = self.handle_sub_type_and_params('fetchMarketLeverageTiers', market, params)
3799
- response = None
3800
- if subType == 'inverse':
3801
- response = self.publicInverseGetFutureMarketV1PublicLeverageBracketDetail(self.extend(request, params))
3802
- else:
3803
- response = self.publicLinearGetFutureMarketV1PublicLeverageBracketDetail(self.extend(request, params))
3804
- #
3805
- # {
3806
- # "returnCode": 0,
3807
- # "msgInfo": "success",
3808
- # "error": null,
3809
- # "result": {
3810
- # "symbol": "btc_usdt",
3811
- # "leverageBrackets": [
3812
- # {
3813
- # "symbol": "btc_usdt",
3814
- # "bracket": 1,
3815
- # "maxNominalValue": "500000",
3816
- # "maintMarginRate": "0.004",
3817
- # "startMarginRate": "0.008",
3818
- # "maxStartMarginRate": null,
3819
- # "maxLeverage": "125",
3820
- # "minLeverage": "1"
3821
- # },
3822
- # ]
3823
- # }
3824
- # }
3825
- #
3826
- data = self.safe_value(response, 'result', {})
3827
- return self.parse_market_leverage_tiers(data, market)
3828
-
3829
- def parse_market_leverage_tiers(self, info, market=None):
3830
- #
3831
- # {
3832
- # "symbol": "rad_usdt",
3833
- # "leverageBrackets": [
3834
- # {
3835
- # "symbol": "rad_usdt",
3836
- # "bracket": 1,
3837
- # "maxNominalValue": "5000",
3838
- # "maintMarginRate": "0.025",
3839
- # "startMarginRate": "0.05",
3840
- # "maxStartMarginRate": null,
3841
- # "maxLeverage": "20",
3842
- # "minLeverage": "1"
3843
- # },
3844
- # ]
3845
- # }
3846
- #
3847
- tiers = []
3848
- brackets = self.safe_value(info, 'leverageBrackets', [])
3849
- for i in range(0, len(brackets)):
3850
- tier = brackets[i]
3851
- marketId = self.safe_string(info, 'symbol')
3852
- market = self.safe_market(marketId, market, '_', 'contract')
3853
- tiers.append({
3854
- 'tier': self.safe_integer(tier, 'bracket'),
3855
- 'currency': market['settle'],
3856
- 'minNotional': self.safe_number(brackets[i - 1], 'maxNominalValue', 0),
3857
- 'maxNotional': self.safe_number(tier, 'maxNominalValue'),
3858
- 'maintenanceMarginRate': self.safe_number(tier, 'maintMarginRate'),
3859
- 'maxLeverage': self.safe_number(tier, 'maxLeverage'),
3860
- 'info': tier,
3861
- })
3862
- return tiers
3863
-
3864
- def fetch_funding_rate_history(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
3865
- """
3866
- fetches historical funding rates
3867
- see https://doc.xt.com/#futures_quotesgetFundingRateRecord
3868
- :param str|None symbol: unified symbol of the market to fetch the funding rate history for
3869
- :param int|None since: timestamp in ms of the earliest funding rate to fetch
3870
- :param int|None limit: the maximum amount of [funding rate structures] to fetch
3871
- :param dict params: extra parameters specific to the xt api endpoint
3872
- :returns [dict]: a list of `funding rate structures <https://docs.ccxt.com/en/latest/manual.html?#funding-rate-history-structure>`
3873
- """
3874
- self.check_required_symbol('fetchFundingRateHistory', symbol)
3875
- self.load_markets()
3876
- market = self.market(symbol)
3877
- if not market['swap']:
3878
- raise BadSymbol(self.id + ' fetchFundingRateHistory() supports swap contracts only')
3879
- request = {
3880
- 'symbol': market['id'],
3881
- }
3882
- if limit is not None:
3883
- request['limit'] = limit
3884
- subType = None
3885
- subType, params = self.handle_sub_type_and_params('fetchFundingRateHistory', market, params)
3886
- response = None
3887
- if subType == 'inverse':
3888
- response = self.publicInverseGetFutureMarketV1PublicQFundingRateRecord(self.extend(request, params))
3889
- else:
3890
- response = self.publicLinearGetFutureMarketV1PublicQFundingRateRecord(self.extend(request, params))
3891
- #
3892
- # {
3893
- # "returnCode": 0,
3894
- # "msgInfo": "success",
3895
- # "error": null,
3896
- # "result": {
3897
- # "hasPrev": False,
3898
- # "hasNext": True,
3899
- # "items": [
3900
- # {
3901
- # "id": "210441653482221888",
3902
- # "symbol": "btc_usdt",
3903
- # "fundingRate": "0.000057",
3904
- # "createdTime": 1679875200000,
3905
- # "collectionInternal": 28800
3906
- # },
3907
- # ]
3908
- # }
3909
- # }
3910
- #
3911
- result = self.safe_value(response, 'result', {})
3912
- items = self.safe_value(result, 'items', [])
3913
- rates = []
3914
- for i in range(0, len(items)):
3915
- entry = items[i]
3916
- marketId = self.safe_string(entry, 'symbol')
3917
- symbolInner = self.safe_symbol(marketId, market)
3918
- timestamp = self.safe_integer(entry, 'createdTime')
3919
- rates.append({
3920
- 'info': entry,
3921
- 'symbol': symbolInner,
3922
- 'fundingRate': self.safe_number(entry, 'fundingRate'),
3923
- 'timestamp': timestamp,
3924
- 'datetime': self.iso8601(timestamp),
3925
- })
3926
- sorted = self.sort_by(rates, 'timestamp')
3927
- return self.filter_by_symbol_since_limit(sorted, market['symbol'], since, limit)
3928
-
3929
- def fetch_funding_rate(self, symbol: str, params={}):
3930
- """
3931
- fetch the current funding rate
3932
- see https://doc.xt.com/#futures_quotesgetFundingRate
3933
- :param str symbol: unified market symbol
3934
- :param dict params: extra parameters specific to the xt api endpoint
3935
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
3936
- """
3937
- self.load_markets()
3938
- market = self.market(symbol)
3939
- if not market['swap']:
3940
- raise BadSymbol(self.id + ' fetchFundingRate() supports swap contracts only')
3941
- request = {
3942
- 'symbol': market['id'],
3943
- }
3944
- subType = None
3945
- subType, params = self.handle_sub_type_and_params('fetchFundingRate', market, params)
3946
- response = None
3947
- if subType == 'inverse':
3948
- response = self.publicInverseGetFutureMarketV1PublicQFundingRate(self.extend(request, params))
3949
- else:
3950
- response = self.publicLinearGetFutureMarketV1PublicQFundingRate(self.extend(request, params))
3951
- #
3952
- # {
3953
- # "returnCode": 0,
3954
- # "msgInfo": "success",
3955
- # "error": null,
3956
- # "result": {
3957
- # "symbol": "btc_usdt",
3958
- # "fundingRate": "0.000086",
3959
- # "nextCollectionTime": 1680307200000,
3960
- # "collectionInternal": 8
3961
- # }
3962
- # }
3963
- #
3964
- result = self.safe_value(response, 'result', {})
3965
- return self.parse_funding_rate(result, market)
3966
-
3967
- def parse_funding_rate(self, contract, market=None):
3968
- #
3969
- # {
3970
- # "symbol": "btc_usdt",
3971
- # "fundingRate": "0.000086",
3972
- # "nextCollectionTime": 1680307200000,
3973
- # "collectionInternal": 8
3974
- # }
3975
- #
3976
- marketId = self.safe_string(contract, 'symbol')
3977
- symbol = self.safe_symbol(marketId, market, '_', 'swap')
3978
- timestamp = self.safe_integer(contract, 'nextCollectionTime')
3979
- return {
3980
- 'info': contract,
3981
- 'symbol': symbol,
3982
- 'markPrice': None,
3983
- 'indexPrice': None,
3984
- 'interestRate': None,
3985
- 'estimatedSettlePrice': None,
3986
- 'timestamp': None,
3987
- 'datetime': None,
3988
- 'fundingRate': self.safe_number(contract, 'fundingRate'),
3989
- 'fundingTimestamp': timestamp,
3990
- 'fundingDatetime': self.iso8601(timestamp),
3991
- 'nextFundingRate': None,
3992
- 'nextFundingTimestamp': None,
3993
- 'nextFundingDatetime': None,
3994
- 'previousFundingRate': None,
3995
- 'previousFundingTimestamp': None,
3996
- 'previousFundingDatetime': None,
3997
- }
3998
-
3999
- def fetch_funding_history(self, symbol: str, since: Optional[int] = None, limit: Optional[int] = None, params={}):
4000
- """
4001
- fetch the funding history
4002
- see https://doc.xt.com/#futures_usergetFunding
4003
- :param str symbol: unified market symbol
4004
- :param int|None since: the starting timestamp in milliseconds
4005
- :param int|None limit: the number of entries to return
4006
- :param dict params: extra parameters specific to the xt api endpoint
4007
- :returns [dict]: a list of `funding history structures <https://docs.ccxt.com/#/?id=funding-history-structure>`
4008
- """
4009
- self.load_markets()
4010
- market = self.market(symbol)
4011
- if not market['swap']:
4012
- raise BadSymbol(self.id + ' fetchFundingHistory() supports swap contracts only')
4013
- request = {
4014
- 'symbol': market['id'],
4015
- }
4016
- if since is not None:
4017
- request['startTime'] = since
4018
- if limit is not None:
4019
- request['limit'] = limit
4020
- subType = None
4021
- subType, params = self.handle_sub_type_and_params('fetchFundingHistory', market, params)
4022
- response = None
4023
- if subType == 'inverse':
4024
- response = self.privateInverseGetFutureUserV1BalanceFundingRateList(self.extend(request, params))
4025
- else:
4026
- response = self.privateLinearGetFutureUserV1BalanceFundingRateList(self.extend(request, params))
4027
- #
4028
- # {
4029
- # "returnCode": 0,
4030
- # "msgInfo": "success",
4031
- # "error": null,
4032
- # "result": {
4033
- # "hasPrev": False,
4034
- # "hasNext": False,
4035
- # "items": [
4036
- # {
4037
- # "id": "210804044057280512",
4038
- # "symbol": "btc_usdt",
4039
- # "cast": "-0.0013",
4040
- # "coin": "usdt",
4041
- # "positionSide": "SHORT",
4042
- # "createdTime": 1679961600653
4043
- # },
4044
- # ]
4045
- # }
4046
- # }
4047
- #
4048
- data = self.safe_value(response, 'result', {})
4049
- items = self.safe_value(data, 'items', [])
4050
- result = []
4051
- for i in range(0, len(items)):
4052
- entry = items[i]
4053
- result.append(self.parse_funding_history(entry, market))
4054
- sorted = self.sort_by(result, 'timestamp')
4055
- return self.filter_by_since_limit(sorted, since, limit)
4056
-
4057
- def parse_funding_history(self, contract, market=None):
4058
- #
4059
- # {
4060
- # "id": "210804044057280512",
4061
- # "symbol": "btc_usdt",
4062
- # "cast": "-0.0013",
4063
- # "coin": "usdt",
4064
- # "positionSide": "SHORT",
4065
- # "createdTime": 1679961600653
4066
- # }
4067
- #
4068
- marketId = self.safe_string(contract, 'symbol')
4069
- symbol = self.safe_symbol(marketId, market, '_', 'swap')
4070
- currencyId = self.safe_string(contract, 'coin')
4071
- code = self.safe_currency_code(currencyId)
4072
- timestamp = self.safe_integer(contract, 'createdTime')
4073
- return {
4074
- 'info': contract,
4075
- 'symbol': symbol,
4076
- 'code': code,
4077
- 'timestamp': timestamp,
4078
- 'datetime': self.iso8601(timestamp),
4079
- 'id': self.safe_string(contract, 'id'),
4080
- 'amount': self.safe_number(contract, 'cast'),
4081
- }
4082
-
4083
- def fetch_position(self, symbol: str, params={}):
4084
- """
4085
- fetch data on a single open contract trade position
4086
- see https://doc.xt.com/#futures_usergetPosition
4087
- :param str symbol: unified market symbol of the market the position is held in
4088
- :param dict params: extra parameters specific to the xt api endpoint
4089
- :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
4090
- """
4091
- self.load_markets()
4092
- market = self.market(symbol)
4093
- request = {
4094
- 'symbol': market['id'],
4095
- }
4096
- subType = None
4097
- subType, params = self.handle_sub_type_and_params('fetchPosition', market, params)
4098
- response = None
4099
- if subType == 'inverse':
4100
- response = self.privateInverseGetFutureUserV1PositionList(self.extend(request, params))
4101
- else:
4102
- response = self.privateLinearGetFutureUserV1PositionList(self.extend(request, params))
4103
- #
4104
- # {
4105
- # "returnCode": 0,
4106
- # "msgInfo": "success",
4107
- # "error": null,
4108
- # "result": [
4109
- # {
4110
- # "symbol": "btc_usdt",
4111
- # "positionType": "ISOLATED",
4112
- # "positionSide": "SHORT",
4113
- # "contractType": "PERPETUAL",
4114
- # "positionSize": "10",
4115
- # "closeOrderSize": "0",
4116
- # "availableCloseSize": "10",
4117
- # "entryPrice": "27060",
4118
- # "openOrderSize": "0",
4119
- # "isolatedMargin": "1.0824",
4120
- # "openOrderMarginFrozen": "0",
4121
- # "realizedProfit": "-0.00130138",
4122
- # "autoMargin": False,
4123
- # "leverage": 25
4124
- # },
4125
- # ]
4126
- # }
4127
- #
4128
- positions = self.safe_value(response, 'result', [])
4129
- for i in range(0, len(positions)):
4130
- entry = positions[i]
4131
- marketId = self.safe_string(entry, 'symbol')
4132
- marketInner = self.safe_market(marketId, None, None, 'contract')
4133
- positionSize = self.safe_string(entry, 'positionSize')
4134
- if positionSize != '0':
4135
- return self.parse_position(entry, marketInner)
4136
- return None
4137
-
4138
- def fetch_positions(self, symbols: Optional[List[str]] = None, params={}):
4139
- """
4140
- fetch all open positions
4141
- see https://doc.xt.com/#futures_usergetPosition
4142
- :param [str]|None symbols: list of unified market symbols, not supported with xt
4143
- :param dict params: extra parameters specific to the xt api endpoint
4144
- :returns [dict]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
4145
- """
4146
- self.load_markets()
4147
- if symbols is not None:
4148
- raise BadRequest(self.id + ' fetchPositions() only supports the symbols argument')
4149
- subType = None
4150
- subType, params = self.handle_sub_type_and_params('fetchPositions', None, params)
4151
- response = None
4152
- if subType == 'inverse':
4153
- response = self.privateInverseGetFutureUserV1PositionList(params)
4154
- else:
4155
- response = self.privateLinearGetFutureUserV1PositionList(params)
4156
- #
4157
- # {
4158
- # "returnCode": 0,
4159
- # "msgInfo": "success",
4160
- # "error": null,
4161
- # "result": [
4162
- # {
4163
- # "symbol": "btc_usdt",
4164
- # "positionType": "ISOLATED",
4165
- # "positionSide": "SHORT",
4166
- # "contractType": "PERPETUAL",
4167
- # "positionSize": "10",
4168
- # "closeOrderSize": "0",
4169
- # "availableCloseSize": "10",
4170
- # "entryPrice": "27060",
4171
- # "openOrderSize": "0",
4172
- # "isolatedMargin": "1.0824",
4173
- # "openOrderMarginFrozen": "0",
4174
- # "realizedProfit": "-0.00130138",
4175
- # "autoMargin": False,
4176
- # "leverage": 25
4177
- # },
4178
- # ]
4179
- # }
4180
- #
4181
- positions = self.safe_value(response, 'result', [])
4182
- result = []
4183
- for i in range(0, len(positions)):
4184
- entry = positions[i]
4185
- marketId = self.safe_string(entry, 'symbol')
4186
- marketInner = self.safe_market(marketId, None, None, 'contract')
4187
- result.append(self.parse_position(entry, marketInner))
4188
- return self.filter_by_array(result, 'symbol', None, False)
4189
-
4190
- def parse_position(self, position, market=None):
4191
- #
4192
- # {
4193
- # "symbol": "btc_usdt",
4194
- # "positionType": "ISOLATED",
4195
- # "positionSide": "SHORT",
4196
- # "contractType": "PERPETUAL",
4197
- # "positionSize": "10",
4198
- # "closeOrderSize": "0",
4199
- # "availableCloseSize": "10",
4200
- # "entryPrice": "27060",
4201
- # "openOrderSize": "0",
4202
- # "isolatedMargin": "1.0824",
4203
- # "openOrderMarginFrozen": "0",
4204
- # "realizedProfit": "-0.00130138",
4205
- # "autoMargin": False,
4206
- # "leverage": 25
4207
- # }
4208
- #
4209
- marketId = self.safe_string(position, 'symbol')
4210
- market = self.safe_market(marketId, market, None, 'contract')
4211
- symbol = self.safe_symbol(marketId, market, None, 'contract')
4212
- positionType = self.safe_string(position, 'positionType')
4213
- marginMode = 'cross' if (positionType == 'CROSSED') else 'isolated'
4214
- collateral = self.safe_number(position, 'isolatedMargin')
4215
- return self.safe_position({
4216
- 'info': position,
4217
- 'id': None,
4218
- 'symbol': symbol,
4219
- 'timestamp': None,
4220
- 'datetime': None,
4221
- 'hedged': None,
4222
- 'side': self.safe_string_lower(position, 'positionSide'),
4223
- 'contracts': self.safe_number(position, 'positionSize'),
4224
- 'contractSize': market['contractSize'],
4225
- 'entryPrice': self.safe_number(position, 'entryPrice'),
4226
- 'markPrice': None,
4227
- 'notional': None,
4228
- 'leverage': self.safe_integer(position, 'leverage'),
4229
- 'collateral': collateral,
4230
- 'initialMargin': collateral,
4231
- 'maintenanceMargin': None,
4232
- 'initialMarginPercentage': None,
4233
- 'maintenanceMarginPercentage': None,
4234
- 'unrealizedPnl': None,
4235
- 'liquidationPrice': None,
4236
- 'marginMode': marginMode,
4237
- 'percentage': None,
4238
- 'marginRatio': None,
4239
- })
4240
-
4241
- def transfer(self, code: str, amount, fromAccount, toAccount, params={}):
4242
- """
4243
- transfer currency internally between wallets on the same account
4244
- see https://doc.xt.com/#transfersubTransferPost
4245
- :param str code: unified currency code
4246
- :param float amount: amount to transfer
4247
- :param str fromAccount: account to transfer from - spot, swap, leverage, finance
4248
- :param str toAccount: account to transfer to - spot, swap, leverage, finance
4249
- :param dict params: extra parameters specific to the whitebit api endpoint
4250
- :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
4251
- """
4252
- self.load_markets()
4253
- currency = self.currency(code)
4254
- accountsByType = self.safe_value(self.options, 'accountsById')
4255
- fromAccountId = self.safe_string(accountsByType, fromAccount, fromAccount)
4256
- toAccountId = self.safe_string(accountsByType, toAccount, toAccount)
4257
- amountString = self.currency_to_precision(code, amount)
4258
- request = {
4259
- 'bizId': self.uuid(),
4260
- 'currency': currency['id'],
4261
- 'amount': amountString,
4262
- 'from': fromAccountId,
4263
- 'to': toAccountId,
4264
- }
4265
- response = self.privateSpotPostBalanceTransfer(self.extend(request, params))
4266
- #
4267
- # {
4268
- # info: {rc: '0', mc: 'SUCCESS', ma: [], result: '226971333791398656'},
4269
- # id: '226971333791398656',
4270
- # timestamp: None,
4271
- # datetime: None,
4272
- # currency: None,
4273
- # amount: None,
4274
- # fromAccount: None,
4275
- # toAccount: None,
4276
- # status: None
4277
- # }
4278
- #
4279
- return self.parse_transfer(response, currency)
4280
-
4281
- def parse_transfer(self, transfer, currency=None):
4282
- return {
4283
- 'info': transfer,
4284
- 'id': self.safe_string(transfer, 'result'),
4285
- 'timestamp': None,
4286
- 'datetime': None,
4287
- 'currency': None,
4288
- 'amount': None,
4289
- 'fromAccount': None,
4290
- 'toAccount': None,
4291
- 'status': None,
4292
- }
4293
-
4294
- def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
4295
- #
4296
- # spot: error
4297
- #
4298
- # {
4299
- # "rc": 1,
4300
- # "mc": "AUTH_103",
4301
- # "ma": [],
4302
- # "result": null
4303
- # }
4304
- #
4305
- # spot: success
4306
- #
4307
- # {
4308
- # "returnCode": 0,
4309
- # "msgInfo": "success",
4310
- # "error": null,
4311
- # "result": []
4312
- # }
4313
- #
4314
- # swap and future: error
4315
- #
4316
- # {
4317
- # "returnCode": 1,
4318
- # "msgInfo": "failure",
4319
- # "error": {
4320
- # "code": "403",
4321
- # "msg": "invalid signature"
4322
- # },
4323
- # "result": null
4324
- # }
4325
- #
4326
- # swap and future: success
4327
- #
4328
- # {
4329
- # "returnCode": 0,
4330
- # "msgInfo": "success",
4331
- # "error": null,
4332
- # "result": null
4333
- # }
4334
- #
4335
- # other:
4336
- #
4337
- # {
4338
- # "rc": 0,
4339
- # "mc": "SUCCESS",
4340
- # "ma": [],
4341
- # "result": {}
4342
- # }
4343
- #
4344
- status = self.safe_string_upper_2(response, 'msgInfo', 'mc')
4345
- if status is not None and status != 'SUCCESS':
4346
- feedback = self.id + ' ' + body
4347
- error = self.safe_value(response, 'error', {})
4348
- spotErrorCode = self.safe_string(response, 'mc')
4349
- errorCode = self.safe_string(error, 'code', spotErrorCode)
4350
- spotMessage = self.safe_string(response, 'msgInfo')
4351
- message = self.safe_string(error, 'msg', spotMessage)
4352
- self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
4353
- self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
4354
- raise ExchangeError(feedback)
4355
- return None
4356
-
4357
- def sign(self, path, api=[], method='GET', params={}, headers=None, body=None):
4358
- signed = api[0] == 'private'
4359
- endpoint = api[1]
4360
- request = '/' + self.implode_params(path, params)
4361
- payload = None
4362
- if (endpoint == 'spot') or (endpoint == 'user'):
4363
- if signed:
4364
- payload = '/' + self.version + request
4365
- else:
4366
- payload = '/' + self.version + '/public' + request
4367
- else:
4368
- payload = request
4369
- url = self.urls['api'][endpoint] + payload
4370
- query = self.omit(params, self.extract_params(path))
4371
- urlencoded = self.urlencode(self.keysort(query))
4372
- headers = {
4373
- 'Content-Type': 'application/json',
4374
- }
4375
- if signed:
4376
- self.check_required_credentials()
4377
- defaultRecvWindow = self.safe_string(self.options, 'recvWindow')
4378
- recvWindow = self.safe_string(query, 'recvWindow', defaultRecvWindow)
4379
- timestamp = self.number_to_string(self.nonce())
4380
- body = query
4381
- if (payload == '/v4/order') or (payload == '/future/trade/v1/order/create') or (payload == '/future/trade/v1/entrust/create-plan') or (payload == '/future/trade/v1/entrust/create-profit') or (payload == '/future/trade/v1/order/create-batch'):
4382
- id = 'CCXT'
4383
- if payload.find('future') > -1:
4384
- body['clientMedia'] = id
4385
- else:
4386
- body['media'] = id
4387
- isUndefinedBody = ((method == 'GET') or (path == 'order/{orderId}'))
4388
- body = None if isUndefinedBody else self.json(body)
4389
- payloadString = None
4390
- if (endpoint == 'spot') or (endpoint == 'user'):
4391
- payloadString = 'xt-validate-algorithms=HmacSHA256&xt-validate-appkey=' + self.apiKey + '&xt-validate-recvwindow=' + recvWindow + '&xt-validate-t' + 'imestamp=' + timestamp
4392
- if isUndefinedBody:
4393
- if urlencoded:
4394
- url += '?' + urlencoded
4395
- payloadString += '#' + method + '#' + payload + '#' + urlencoded
4396
- else:
4397
- payloadString += '#' + method + '#' + payload
4398
- else:
4399
- payloadString += '#' + method + '#' + payload + '#' + body
4400
- headers['xt-validate-algorithms'] = 'HmacSHA256'
4401
- headers['xt-validate-recvwindow'] = recvWindow
4402
- else:
4403
- payloadString = 'xt-validate-appkey=' + self.apiKey + '&xt-validate-t' + 'imestamp=' + timestamp # we can't glue timestamp, breaks in php
4404
- if method == 'GET':
4405
- if urlencoded:
4406
- url += '?' + urlencoded
4407
- payloadString += '#' + payload + '#' + urlencoded
4408
- else:
4409
- payloadString += '#' + payload
4410
- else:
4411
- payloadString += '#' + payload + '#' + body
4412
- signature = self.hmac(self.encode(payloadString), self.encode(self.secret), hashlib.sha256)
4413
- headers['xt-validate-appkey'] = self.apiKey
4414
- headers['xt-validate-timestamp'] = timestamp
4415
- headers['xt-validate-signature'] = signature
4416
- else:
4417
- if urlencoded:
4418
- url += '?' + urlencoded
4419
- return {'url': url, 'method': method, 'body': body, 'headers': headers}