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/zb.py DELETED
@@ -1,4126 +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
- import hashlib
8
- from ccxt.base.types import OrderSide
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 AccountSuspended
14
- from ccxt.base.errors import ArgumentsRequired
15
- from ccxt.base.errors import BadRequest
16
- from ccxt.base.errors import BadSymbol
17
- from ccxt.base.errors import BadResponse
18
- from ccxt.base.errors import InsufficientFunds
19
- from ccxt.base.errors import InvalidAddress
20
- from ccxt.base.errors import InvalidOrder
21
- from ccxt.base.errors import OrderNotFound
22
- from ccxt.base.errors import DuplicateOrderId
23
- from ccxt.base.errors import NotSupported
24
- from ccxt.base.errors import NetworkError
25
- from ccxt.base.errors import DDoSProtection
26
- from ccxt.base.errors import RateLimitExceeded
27
- from ccxt.base.errors import ExchangeNotAvailable
28
- from ccxt.base.errors import OnMaintenance
29
- from ccxt.base.errors import RequestTimeout
30
- from ccxt.base.errors import AuthenticationError
31
- from ccxt.base.decimal_to_precision import TICK_SIZE
32
- from ccxt.base.precise import Precise
33
-
34
-
35
- class zb(Exchange):
36
-
37
- def describe(self):
38
- return self.deep_extend(super(zb, self).describe(), {
39
- 'id': 'zb',
40
- 'name': 'ZB',
41
- 'countries': ['CN'],
42
- # previously rateLimit = 100
43
- # Trading and Margin 10 000 per minute(IP) => 10000 / 60 = 166.66666... per second => rateLimit = 1000/166.66666 = 6
44
- # Trade and Margin 60 per second(apiKey) => weight = 166.666 / 60 = 2.778(2.7777777...)
45
- # Kline 1 per second => weight = 166.667
46
- # v2 Futures API 100 per 2 seconds => 50 per second => weight = 3.334(3.3333333...)
47
- # for endpoints not mentioned in docs
48
- # previous rateLimit was 100 translating to 10 requests per second => weight = 166.666 / 10 = 16.667(16.666666...)
49
- 'rateLimit': 6,
50
- 'version': 'v1',
51
- 'pro': True,
52
- 'has': {
53
- 'CORS': None,
54
- 'spot': True,
55
- 'margin': True,
56
- 'swap': True,
57
- 'future': None,
58
- 'option': None,
59
- 'addMargin': True,
60
- 'borrowMargin': True,
61
- 'cancelAllOrders': True,
62
- 'cancelOrder': True,
63
- 'createMarketOrder': False,
64
- 'createOrder': True,
65
- 'createReduceOnlyOrder': False,
66
- 'createStopLimitOrder': True,
67
- 'createStopMarketOrder': True,
68
- 'createStopOrder': True,
69
- 'fetchBalance': True,
70
- 'fetchBorrowRate': True,
71
- 'fetchBorrowRateHistories': False,
72
- 'fetchBorrowRateHistory': False,
73
- 'fetchBorrowRates': True,
74
- 'fetchCanceledOrders': True,
75
- 'fetchClosedOrders': True,
76
- 'fetchCurrencies': True,
77
- 'fetchDepositAddress': True,
78
- 'fetchDepositAddresses': True,
79
- 'fetchDeposits': True,
80
- 'fetchFundingHistory': False,
81
- 'fetchFundingRate': True,
82
- 'fetchFundingRateHistory': True,
83
- 'fetchFundingRates': True,
84
- 'fetchIndexOHLCV': True,
85
- 'fetchLedger': True,
86
- 'fetchLeverage': False,
87
- 'fetchLeverageTiers': False,
88
- 'fetchMarketLeverageTiers': False,
89
- 'fetchMarkets': True,
90
- 'fetchMarkOHLCV': True,
91
- 'fetchOHLCV': True,
92
- 'fetchOpenOrders': True,
93
- 'fetchOrder': True,
94
- 'fetchOrderBook': True,
95
- 'fetchOrders': True,
96
- 'fetchPosition': True,
97
- 'fetchPositions': True,
98
- 'fetchPositionsRisk': False,
99
- 'fetchPremiumIndexOHLCV': False,
100
- 'fetchTicker': True,
101
- 'fetchTickers': True,
102
- 'fetchTrades': True,
103
- 'fetchTradingFee': False,
104
- 'fetchTradingFees': False,
105
- 'fetchWithdrawals': True,
106
- 'reduceMargin': True,
107
- 'setLeverage': True,
108
- 'setMarginMode': False,
109
- 'setPositionMode': False,
110
- 'transfer': True,
111
- 'withdraw': True,
112
- },
113
- 'timeframes': {
114
- '1m': '1m',
115
- '3m': '3m',
116
- '5m': '5m',
117
- '15m': '15m',
118
- '30m': '30m',
119
- '1h': '1h',
120
- '2h': '2h',
121
- '4h': '4h',
122
- '6h': '6h',
123
- '12h': '12h',
124
- '1d': '1d',
125
- '3d': '3d',
126
- '5d': '5d',
127
- '1w': '1w',
128
- },
129
- 'hostname': 'zb.com', # zb.cafe for users in China
130
- 'urls': {
131
- 'logo': 'https://user-images.githubusercontent.com/1294454/32859187-cd5214f0-ca5e-11e7-967d-96568e2e2bd1.jpg',
132
- 'api': {
133
- 'spot': {
134
- 'v1': {
135
- 'public': 'https://api.{hostname}/data',
136
- 'private': 'https://trade.{hostname}/api',
137
- },
138
- },
139
- 'contract': {
140
- 'v1': {
141
- 'public': 'https://fapi.{hostname}/api/public',
142
- },
143
- 'v2': {
144
- 'public': 'https://fapi.{hostname}/Server/api',
145
- 'private': 'https://fapi.{hostname}/Server/api',
146
- },
147
- },
148
- },
149
- 'www': 'https://www.zb.com',
150
- 'doc': 'https://www.zb.com/i/developer',
151
- 'fees': 'https://www.zb.com/i/rate',
152
- 'referral': {
153
- 'url': 'https://www.zb.com/en/register?ref=4301lera',
154
- 'discount': 0.16,
155
- },
156
- },
157
- 'api': {
158
- 'spot': {
159
- 'v1': {
160
- 'public': {
161
- 'get': {
162
- 'markets': 16.667,
163
- 'ticker': 16.667,
164
- 'allTicker': 16.667,
165
- 'depth': 16.667,
166
- 'trades': 16.667,
167
- 'kline': 166.667, # Kline 1 per second
168
- 'getGroupMarkets': 16.667,
169
- 'getFeeInfo': 16.667,
170
- },
171
- },
172
- 'private': {
173
- 'get': {
174
- # spot API
175
- 'order': 1, # Trade API
176
- 'orderMoreV2': 1, # Trade API
177
- 'cancelOrder': 1, # Trade API
178
- 'cancelAllOrdersAfter': 1, # Trade API TODO add cancelAllOrders
179
- 'getOrder': 1, # Trade API
180
- 'getOrders': 1, # Trade API
181
- 'getOrdersNew': 16.667,
182
- 'getOrdersIgnoreTradeType': 1, # Trade API
183
- 'getUnfinishedOrdersIgnoreTradeType': 1, # Trade API
184
- 'getFinishedAndPartialOrders': 1, # Trade API
185
- 'getAccountInfo': 16.667,
186
- 'getUserAddress': 16.667,
187
- 'getPayinAddress': 16.667,
188
- 'getWithdrawAddress': 16.667,
189
- 'getWithdrawRecord': 16.667,
190
- 'getChargeRecord': 16.667,
191
- 'getCnyWithdrawRecord': 16.667,
192
- 'getCnyChargeRecord': 16.667,
193
- 'withdraw': 16.667,
194
- # sub accounts
195
- 'addSubUser': 16.667,
196
- 'getSubUserList': 16.667,
197
- 'doTransferFunds': 16.667,
198
- 'createSubUserKey': 16.667, # removed on 2021-03-16 according to the update log in the API doc
199
- # leverage API
200
- 'getLeverAssetsInfo': 16.667,
201
- 'getLeverBills': 16.667,
202
- 'transferInLever': 16.667,
203
- 'transferOutLever': 16.667,
204
- 'loan': 16.667,
205
- 'cancelLoan': 16.667,
206
- 'getLoans': 16.667,
207
- 'getLoanRecords': 16.667,
208
- 'borrow': 16.667,
209
- 'autoBorrow': 16.667,
210
- 'repay': 16.667,
211
- 'doAllRepay': 16.667,
212
- 'getRepayments': 16.667,
213
- 'getFinanceRecords': 16.667,
214
- 'changeInvestMark': 16.667,
215
- 'changeLoop': 16.667,
216
- # cross API
217
- 'getCrossAssets': 16.667,
218
- 'getCrossBills': 16.667,
219
- 'transferInCross': 16.667,
220
- 'transferOutCross': 16.667,
221
- 'doCrossLoan': 16.667,
222
- 'doCrossRepay': 16.667,
223
- 'getCrossRepayRecords': 16.667,
224
- },
225
- },
226
- },
227
- },
228
- 'contract': {
229
- 'v1': {
230
- 'public': {
231
- 'get': {
232
- 'depth': 16.667,
233
- 'fundingRate': 16.667,
234
- 'indexKline': 16.667,
235
- 'indexPrice': 16.667,
236
- 'kline': 16.667,
237
- 'markKline': 16.667,
238
- 'markPrice': 16.667,
239
- 'ticker': 16.667,
240
- 'trade': 16.667,
241
- },
242
- },
243
- },
244
- 'v2': {
245
- 'public': {
246
- 'get': {
247
- 'allForceOrders': 3.334,
248
- 'config/marketList': 3.334,
249
- 'topLongShortAccountRatio': 3.334,
250
- 'topLongShortPositionRatio': 3.334,
251
- 'fundingRate': 3.334,
252
- 'premiumIndex': 3.334,
253
- },
254
- },
255
- 'private': {
256
- 'get': {
257
- 'Fund/balance': 3.334,
258
- 'Fund/getAccount': 3.334,
259
- 'Fund/getBill': 3.334,
260
- 'Fund/getBillTypeList': 3.334,
261
- 'Fund/marginHistory': 3.334,
262
- 'Positions/getPositions': 3.334,
263
- 'Positions/getNominalValue': 3.334,
264
- 'Positions/marginInfo': 3.334,
265
- 'setting/get': 3.334,
266
- 'trade/getAllOrders': 3.334,
267
- 'trade/getOrder': 3.334,
268
- 'trade/getOrderAlgos': 3.334,
269
- 'trade/getTradeList': 3.334,
270
- 'trade/getUndoneOrders': 3.334,
271
- 'trade/tradeHistory': 3.334,
272
- },
273
- 'post': {
274
- 'activity/buyTicket': 3.334,
275
- 'Fund/transferFund': 3.334,
276
- 'Positions/setMarginCoins': 3.334,
277
- 'Positions/updateAppendUSDValue': 3.334,
278
- 'Positions/updateMargin': 3.334,
279
- 'setting/setLeverage': 3.334,
280
- 'setting/setPositionsMode': 3.334,
281
- 'trade/batchOrder': 3.334,
282
- 'trade/batchCancelOrder': 3.334,
283
- 'trade/cancelAlgos': 3.334,
284
- 'trade/cancelAllOrders': 3.334,
285
- 'trade/cancelOrder': 3.334,
286
- 'trade/order': 3.334,
287
- 'trade/orderAlgo': 3.334,
288
- 'trade/updateOrderAlgo': 3.334,
289
- },
290
- },
291
- },
292
- },
293
- },
294
- 'fees': {
295
- 'funding': {
296
- 'withdraw': {},
297
- },
298
- 'trading': {
299
- 'maker': self.parse_number('0.002'),
300
- 'taker': self.parse_number('0.002'),
301
- },
302
- },
303
- 'commonCurrencies': {
304
- 'ANG': 'Anagram',
305
- 'ENT': 'ENTCash',
306
- 'BCHABC': 'BCHABC', # conflict with BCH / BCHA
307
- 'BCHSV': 'BCHSV', # conflict with BCH / BSV
308
- },
309
- 'options': {
310
- 'timeframes': {
311
- 'spot': {
312
- '1m': '1min',
313
- '3m': '3min',
314
- '5m': '5min',
315
- '15m': '15min',
316
- '30m': '30min',
317
- '1h': '1hour',
318
- '2h': '2hour',
319
- '4h': '4hour',
320
- '6h': '6hour',
321
- '12h': '12hour',
322
- '1d': '1day',
323
- '3d': '3day',
324
- '1w': '1week',
325
- },
326
- 'swap': {
327
- '1m': '1M',
328
- '5m': '5M',
329
- '15m': '15M',
330
- '30m': '30M',
331
- '1h': '1H',
332
- '6h': '6H',
333
- '1d': '1D',
334
- '5d': '5D',
335
- },
336
- },
337
- },
338
- 'precisionMode': TICK_SIZE,
339
- 'exceptions': {
340
- 'ws': {
341
- # '1000': ExchangeError, # The call is successful.
342
- '1001': ExchangeError, # General error prompt
343
- '1002': ExchangeError, # Internal Error
344
- '1003': AuthenticationError, # Fail to verify
345
- '1004': AuthenticationError, # The transaction password is locked
346
- '1005': AuthenticationError, # Wrong transaction password, please check it and re-enter。
347
- '1006': PermissionDenied, # Real-name authentication is pending approval or unapproved
348
- '1007': ExchangeError, # Channel does not exist
349
- '1009': OnMaintenance, # This interface is under maintenance
350
- '1010': ExchangeNotAvailable, # Not available now
351
- '1012': PermissionDenied, # Insufficient permissions
352
- '1013': ExchangeError, # Cannot trade, please contact email: support@zb.cn for support.
353
- '1014': ExchangeError, # Cannot sell during the pre-sale period
354
- '2001': InsufficientFunds, # Insufficient CNY account balance
355
- '2002': InsufficientFunds, # Insufficient BTC account balance
356
- '2003': InsufficientFunds, # Insufficient LTC account balance
357
- '2005': InsufficientFunds, # Insufficient ETH account balance
358
- '2006': InsufficientFunds, # ETCInsufficient account balance
359
- '2007': InsufficientFunds, # BTSInsufficient account balance
360
- '2008': InsufficientFunds, # EOSInsufficient account balance
361
- '2009': InsufficientFunds, # BCCInsufficient account balance
362
- '3001': OrderNotFound, # Order not found or is completed
363
- '3002': InvalidOrder, # Invalid amount
364
- '3003': InvalidOrder, # Invalid quantity
365
- '3004': AuthenticationError, # User does not exist
366
- '3005': BadRequest, # Invalid parameter
367
- '3006': PermissionDenied, # Invalid IP or not consistent with the bound IP
368
- '3007': RequestTimeout, # The request time has expired
369
- '3008': ExchangeError, # Transaction not found
370
- '3009': InvalidOrder, # The price exceeds the limit
371
- '3010': PermissionDenied, # It fails to place an order, due to you have set up to prohibit trading of self market.
372
- '3011': InvalidOrder, # The entrusted price is abnormal, please modify it and place order again
373
- '3012': InvalidOrder, # Duplicate custom customerOrderId
374
- '4001': AccountSuspended, # APIThe interface is locked for one hour
375
- '4002': RateLimitExceeded, # Request too frequently
376
- },
377
- 'exact': {
378
- # '1000': 'Successful operation',
379
- '10001': ExchangeError, # Operation failed
380
- '10002': PermissionDenied, # Operation is forbidden
381
- '10003': BadResponse, # Data existed
382
- '10004': BadResponse, # Date not exist
383
- '10005': PermissionDenied, # Forbidden to access the interface
384
- '10006': BadRequest, # Currency invalid or expired
385
- '10007': ExchangeError, # {0}
386
- '10008': ExchangeError, # Operation failed: {0}
387
- '10009': ExchangeError, # URL error
388
- '1001': ExchangeError, # 'General error message',
389
- '10010': AuthenticationError, # API KEY not exist
390
- '10011': AuthenticationError, # API KEY CLOSED
391
- '10012': AccountSuspended, # User API has been frozen, please contact customer service for processing
392
- '10013': AuthenticationError, # API verification failed
393
- '10014': AuthenticationError, # Invalid signature(1001)
394
- '10015': AuthenticationError, # Invalid signature(1002)
395
- '10016': AuthenticationError, # Invalid ip
396
- '10017': PermissionDenied, # Permission denied
397
- '10018': AccountSuspended, # User has been frozen, please contact customer service
398
- '10019': RequestTimeout, # Request time has expired
399
- '1002': ExchangeError, # 'Internal error',
400
- '10020': BadRequest, # {0}Parameter cannot be empty
401
- '10021': BadRequest, # {0}Invalid parameter
402
- '10022': BadRequest, # Request method error
403
- '10023': RateLimitExceeded, # Request frequency is too fast, exceeding the limit allowed by the interface
404
- '10024': AuthenticationError, # Login failed
405
- '10025': ExchangeError, # Non-personal operation
406
- '10026': NetworkError, # Failed to request interface, please try again
407
- '10027': RequestTimeout, # Timed out, please try again later
408
- '10028': ExchangeNotAvailable, # System busy, please try again later
409
- '10029': DDoSProtection, # Frequent operation, please try again later
410
- '1003': AuthenticationError, # 'Verification does not pass',
411
- '10030': BadRequest, # Currency already exist
412
- '10031': BadRequest, # Currency does not exist
413
- '10032': BadRequest, # Market existed
414
- '10033': BadRequest, # Market not exist
415
- '10034': BadRequest, # Currency error
416
- '10035': BadRequest, # Market not open
417
- '10036': BadRequest, # Ineffective market type
418
- '10037': ArgumentsRequired, # User id cannot be empty
419
- '10038': BadRequest, # Market id cannot be empty
420
- '10039': BadResponse, # Failed to get mark price
421
- '1004': AuthenticationError, # 'Funding security password lock',
422
- '10040': BadResponse, # Failed to obtain the opening margin configuration
423
- '10041': BadResponse, # Failed to obtain maintenance margin allocation
424
- '10042': ExchangeError, # Avg. price error
425
- '10043': ExchangeError, # Abnormal acquisition of liquidation price
426
- '10044': ExchangeError, # Unrealized profit and loss acquisition exception
427
- '10045': ExchangeError, # jdbcData source acquisition failed
428
- '10046': ExchangeError, # Invalid position opening direction
429
- '10047': ExchangeError, # The maximum position allowed by the current leverage multiple has been exceeded
430
- '10048': ExchangeError, # The maximum allowable order quantity has been exceeded
431
- '10049': NetworkError, # Failed to get the latest price
432
- '1005': AuthenticationError, # 'Funds security password is incorrect, please confirm and re-enter.',
433
- '1006': AuthenticationError, # 'Real-name certification pending approval or audit does not pass',
434
- '1009': ExchangeNotAvailable, # 'This interface is under maintenance',
435
- '1010': ExchangeNotAvailable, # Not available now
436
- '10100': OnMaintenance, # Sorry! System maintenance, stop operation
437
- '1012': PermissionDenied, # Insufficient permissions
438
- '1013': ExchangeError, # Cannot trade, please contact email: support@zb.cn for support.
439
- '1014': ExchangeError, # Cannot sell during the pre-sale period
440
- '11000': ExchangeError, # Funding change failed
441
- '11001': ExchangeError, # Position change failed
442
- '110011': ExchangeError, # Exceeds the maximum leverage allowed by the position
443
- '11002': ExchangeError, # Funding not exist
444
- '11003': ExchangeError, # Freeze records not exist
445
- '11004': InsufficientFunds, # Insufficient frozen funds
446
- '11005': InvalidOrder, # Insufficient positions
447
- '11006': InsufficientFunds, # Insufficient frozen positions
448
- '11007': OrderNotFound, # Position not exist
449
- '11008': ExchangeError, # The contract have positions, cannot be modified
450
- '11009': ExchangeError, # Failed to query data
451
- '110110': ExchangeError, # Exceed the market's maximum leverage
452
- '11012': InsufficientFunds, # Insufficient margin
453
- '11013': ExchangeError, # Exceeding accuracy limit
454
- '11014': ExchangeError, # Invalid bill type
455
- '11015': AuthenticationError, # Failed to add default account
456
- '11016': AuthenticationError, # Account not exist
457
- '11017': ExchangeError, # Funds are not frozen or unfrozen
458
- '11018': InsufficientFunds, # Insufficient funds
459
- '11019': ExchangeError, # Bill does not exist
460
- '11021': InsufficientFunds, # Inconsistent currency for funds transfer
461
- '11023': ExchangeError, # Same transaction currency
462
- '11030': PermissionDenied, # Position is locked, the operation is prohibited
463
- '11031': ExchangeError, # The number of bill changes is zero
464
- '11032': ExchangeError, # The same request is being processed, please do not submit it repeatedly
465
- '11033': ArgumentsRequired, # Position configuration data is empty
466
- '11034': ExchangeError, # Funding fee is being settled, please do not operate
467
- '12000': InvalidOrder, # Invalid order price
468
- '12001': InvalidOrder, # Invalid order amount
469
- '12002': InvalidOrder, # Invalid order type
470
- '12003': InvalidOrder, # Invalid price accuracy
471
- '12004': InvalidOrder, # Invalid quantity precision
472
- '12005': InvalidOrder, # order value less than the minimum or greater than the maximum
473
- '12006': InvalidOrder, # Customize's order number format is wrong
474
- '12007': InvalidOrder, # Direction error
475
- '12008': InvalidOrder, # Order type error
476
- '12009': InvalidOrder, # Commission type error
477
- '12010': InvalidOrder, # Failed to place the order, the loss of the order placed at self price will exceed margin
478
- '12011': InvalidOrder, # it's not a buz order
479
- '12012': OrderNotFound, # order not exist
480
- '12013': InvalidOrder, # Order user does not match
481
- '12014': InvalidOrder, # Order is still in transaction
482
- '12015': InvalidOrder, # Order preprocessing failed
483
- '12016': InvalidOrder, # Order cannot be canceled
484
- '12017': InvalidOrder, # Transaction Record not exist
485
- '12018': InvalidOrder, # Order failed
486
- '12019': ArgumentsRequired, # self.extend parameter cannot be empty
487
- '12020': ExchangeError, # self.extend Parameter error
488
- '12021': InvalidOrder, # The order price is not within the price limit rules!
489
- '12022': InvalidOrder, # Stop placing an order while the system is calculating the fund fee
490
- '12023': OrderNotFound, # There are no positions to close
491
- '12024': InvalidOrder, # Orders are prohibited, stay tuned!
492
- '12025': InvalidOrder, # Order cancellation is prohibited, so stay tuned!
493
- '12026': DuplicateOrderId, # Order failed, customize order number exists
494
- '12027': ExchangeNotAvailable, # System busy, please try again later
495
- '12028': InvalidOrder, # The market has banned trading
496
- '12029': InvalidOrder, # Forbidden place order, stay tuned
497
- '12201': InvalidOrder, # Delegation strategy does not exist or the status has changed
498
- '12202': InvalidOrder, # Delegation strategy has been changed, cannot be canceled
499
- '12203': InvalidOrder, # Wrong order type
500
- '12204': InvalidOrder, # Invalid trigger price
501
- '12205': InvalidOrder, # The trigger price must be greater than the market’s selling price or lower than the buying price.
502
- '12206': InvalidOrder, # Direction and order type do not match
503
- '12207': RateLimitExceeded, # Submission failed, exceeding the allowed limit
504
- '13001': AuthenticationError, # User not exist
505
- '13002': PermissionDenied, # User did not activate futures
506
- # '13003': AuthenticationError, # User is locked
507
- '13003': InvalidOrder, # Margin gear is not continuous
508
- '13004': InvalidOrder, # The margin quick calculation amount is less than 0
509
- '13005': RateLimitExceeded, # You have exceeded the number of exports that day
510
- '13006': ExchangeError, # No markets are bookmarked
511
- '13007': ExchangeError, # Market not favorited
512
- '13008': ExchangeError, # Not in any market user whitelist
513
- '13009': ExchangeError, # Not in the whitelist of users in self market
514
- '14000': ExchangeError, # {0}not support
515
- '14001': AuthenticationError, # Already logged in, no need to log in multiple times
516
- '14002': AuthenticationError, # Not logged in yet, please log in before subscribing
517
- '14003': ExchangeError, # This is a channel for one-time queries, no need to unsubscribe
518
- '14100': ExchangeError, # Accuracy does not support
519
- '14101': RateLimitExceeded, # Request exceeded frequency limit
520
- '14200': ArgumentsRequired, # id empty
521
- '14300': ExchangeError, # activity not exist
522
- '14301': ExchangeError, # The event has been opened and cannot be admitted
523
- '14302': ExchangeError, # The purchase time has passed and cannot be admitted
524
- '14303': ExchangeError, # Not yet open for the purchase
525
- '14305': ExchangeError, # Cannot enter, the maximum number of returns has been exceeded
526
- '14306': ExchangeError, # Cannot repeat admission
527
- '14307': InvalidOrder, # Unable to cancel, status has been changed
528
- '14308': InvalidOrder, # Unable to cancel, the amount does not match
529
- '14309': ExchangeError, # Activity has not started
530
- '14310': NotSupported, # Activity is over
531
- '14311': NotSupported, # The activity does not support orders placed in self market
532
- '14312': ExchangeError, # You have not participated in self activity
533
- '14313': PermissionDenied, # Sorry! The purchase failed, the maximum number of participants has been reached
534
- '14314': ExchangeError, # Active period id error
535
- '2001': InsufficientFunds, # 'Insufficient CNY Balance',
536
- '2002': InsufficientFunds, # 'Insufficient BTC Balance',
537
- '2003': InsufficientFunds, # 'Insufficient LTC Balance',
538
- '2005': InsufficientFunds, # 'Insufficient ETH Balance',
539
- '2006': InsufficientFunds, # 'Insufficient ETC Balance',
540
- '2007': InsufficientFunds, # 'Insufficient BTS Balance',
541
- '2008': InsufficientFunds, # EOSInsufficient account balance
542
- '2009': InsufficientFunds, # 'Account balance is not enough',
543
- '3001': OrderNotFound, # 'Pending orders not found',
544
- '3002': InvalidOrder, # 'Invalid price',
545
- '3003': InvalidOrder, # 'Invalid amount',
546
- '3004': AuthenticationError, # 'User does not exist',
547
- '3005': BadRequest, # 'Invalid parameter',
548
- '3006': AuthenticationError, # 'Invalid IP or inconsistent with the bound IP',
549
- '3007': AuthenticationError, # 'The request time has expired',
550
- '3008': OrderNotFound, # 'Transaction records not found',
551
- '3009': InvalidOrder, # 'The price exceeds the limit',
552
- '3010': PermissionDenied, # It fails to place an order, due to you have set up to prohibit trading of self market.
553
- '3011': InvalidOrder, # 'The entrusted price is abnormal, please modify it and place order again',
554
- '3012': InvalidOrder, # Duplicate custom customerOrderId
555
- '4001': ExchangeNotAvailable, # 'API interface is locked or not enabled',
556
- '4002': RateLimitExceeded, # 'Request too often',
557
- '9999': ExchangeError, # Unknown error
558
- },
559
- 'broad': {
560
- '提币地址有误, 请先添加提币地址。': InvalidAddress, # {"code":1001,"message":"提币地址有误,请先添加提币地址。"}
561
- '资金不足,无法划账': InsufficientFunds, # {"code":1001,"message":"资金不足,无法划账"}
562
- '响应超时': RequestTimeout, # {"code":1001,"message":"响应超时"}
563
- },
564
- },
565
- })
566
-
567
- def fetch_markets(self, params={}):
568
- """
569
- retrieves data on all markets for zb
570
- :param dict params: extra parameters specific to the exchange api endpoint
571
- :returns [dict]: an array of objects representing market data
572
- """
573
- #
574
- # {
575
- # "zb_qc":{
576
- # "amountScale":2,
577
- # "minAmount":0.01,
578
- # "minSize":5,
579
- # "priceScale":4,
580
- # },
581
- # }
582
- #
583
- promises = [self.spotV1PublicGetMarkets(params), self.contractV2PublicGetConfigMarketList(params)]
584
- promises = promises
585
- markets = promises[0]
586
- contracts = promises[1]
587
- #
588
- # {
589
- # BTC_USDT: {
590
- # symbol: 'BTC_USDT',
591
- # buyerCurrencyId: '6',
592
- # contractType: '1',
593
- # defaultMarginMode: '1',
594
- # marketType: '2',
595
- # historyDBName: 'trade_history_readonly.dbc',
596
- # defaultLeverage: '20',
597
- # id: '100',
598
- # canCancelOrder: True,
599
- # area: '1',
600
- # mixMarginCoinName: 'usdt',
601
- # fundingRateRatio: '0.25',
602
- # marginCurrencyName: 'usdt',
603
- # minTradeMoney: '0.0001',
604
- # enableTime: '1638954000000',
605
- # maxTradeMoney: '10000000',
606
- # canTrade: True,
607
- # maxLeverage: '125',
608
- # defaultPositionsMode: '2',
609
- # onlyWhitelistVisible: False,
610
- # riskWarnRatio: '0.8',
611
- # marginDecimal: '8',
612
- # spot: False,
613
- # status: '1',
614
- # amountDecimal: '3',
615
- # leverage: False,
616
- # minAmount: '0.001',
617
- # canOrder: True,
618
- # duration: '1',
619
- # feeDecimal: '8',
620
- # sellerCurrencyId: '1',
621
- # maxAmount: '1000',
622
- # canOpenPosition: True,
623
- # isSupportMixMargin: False,
624
- # markPriceLimitRate: '0.05',
625
- # marginCurrencyId: '6',
626
- # stopFundingFee: False,
627
- # priceDecimal: '2',
628
- # lightenUpFeeRate: '0',
629
- # futures: True,
630
- # sellerCurrencyName: 'btc',
631
- # marketPriceLimitRate: '0.05',
632
- # canRebate: True,
633
- # marketName: 'BTC_USDT',
634
- # depth: [0.01, 0.1, 1],
635
- # createTime: '1607590430094',
636
- # mixMarginCoinIds: [6],
637
- # buyerCurrencyName: 'usdt',
638
- # stopService: False
639
- # },
640
- # }
641
- #
642
- contractsData = self.safe_value(contracts, 'data', [])
643
- contractsById = self.index_by(contractsData, 'marketName')
644
- dataById = self.deep_extend(contractsById, markets)
645
- keys = list(dataById.keys())
646
- result = []
647
- for i in range(0, len(keys)):
648
- id = keys[i]
649
- market = dataById[id]
650
- baseId, quoteId = id.split('_')
651
- base = self.safe_currency_code(baseId)
652
- quote = self.safe_currency_code(quoteId)
653
- settleId = self.safe_value(market, 'marginCurrencyName')
654
- settle = self.safe_currency_code(settleId)
655
- spot = settle is None
656
- swap = self.safe_value(market, 'futures', False)
657
- linear = True if swap else None
658
- active = True
659
- symbol = base + '/' + quote
660
- if swap:
661
- status = self.safe_string(market, 'status')
662
- active = (status == '1')
663
- symbol = base + '/' + quote + ':' + settle
664
- result.append({
665
- 'id': id,
666
- 'symbol': symbol,
667
- 'base': base,
668
- 'quote': quote,
669
- 'settle': settle,
670
- 'baseId': baseId,
671
- 'quoteId': quoteId,
672
- 'settleId': settleId,
673
- 'type': 'swap' if swap else 'spot',
674
- 'spot': spot,
675
- 'margin': False,
676
- 'swap': swap,
677
- 'future': False,
678
- 'option': False,
679
- 'active': active,
680
- 'contract': swap,
681
- 'linear': linear,
682
- 'inverse': not linear if swap else None,
683
- 'contractSize': None,
684
- 'expiry': None,
685
- 'expiryDatetime': None,
686
- 'strike': None,
687
- 'optionType': None,
688
- 'precision': {
689
- 'amount': self.parse_number(self.parse_precision(self.safe_string_2(market, 'amountScale', 'amountDecimal'))),
690
- 'price': self.parse_number(self.parse_precision(self.safe_string_2(market, 'priceScale', 'priceDecimal'))),
691
- },
692
- 'limits': {
693
- 'leverage': {
694
- 'min': None,
695
- 'max': self.safe_number(market, 'maxLeverage'),
696
- },
697
- 'amount': {
698
- 'min': self.safe_number(market, 'minAmount'),
699
- 'max': self.safe_number(market, 'maxAmount'),
700
- },
701
- 'price': {
702
- 'min': None,
703
- 'max': None,
704
- },
705
- 'cost': {
706
- 'min': self.safe_number_2(market, 'minSize', 'minTradeMoney'),
707
- 'max': self.safe_number(market, 'maxTradeMoney'),
708
- },
709
- },
710
- 'info': market,
711
- })
712
- return result
713
-
714
- def fetch_currencies(self, params={}):
715
- """
716
- fetches all available currencies on an exchange
717
- :param dict params: extra parameters specific to the zb api endpoint
718
- :returns dict: an associative dictionary of currencies
719
- """
720
- response = self.spotV1PublicGetGetFeeInfo(params)
721
- #
722
- # {
723
- # "code":1000,
724
- # "message":"success",
725
- # "result":{
726
- # "USDT":[
727
- # {
728
- # "chainName":"TRC20",
729
- # "canWithdraw":true,
730
- # "fee":1.0,
731
- # "mainChainName":"TRX",
732
- # "canDeposit":true
733
- # },
734
- # {
735
- # "chainName":"OMNI",
736
- # "canWithdraw":true,
737
- # "fee":5.0,
738
- # "mainChainName":"BTC",
739
- # "canDeposit":true
740
- # },
741
- # {
742
- # "chainName":"ERC20",
743
- # "canWithdraw":true,
744
- # "fee":15.0,
745
- # "mainChainName":"ETH",
746
- # "canDeposit":true
747
- # }
748
- # ],
749
- # }
750
- # }
751
- #
752
- currencies = self.safe_value(response, 'result', {})
753
- ids = list(currencies.keys())
754
- result = {}
755
- for i in range(0, len(ids)):
756
- id = ids[i]
757
- currency = currencies[id]
758
- code = self.safe_currency_code(id)
759
- isWithdrawEnabled = True
760
- isDepositEnabled = True
761
- fees = {}
762
- for j in range(0, len(currency)):
763
- networkItem = currency[j]
764
- network = self.safe_string_2(networkItem, 'chainName', 'mainChainName')
765
- # name = self.safe_string(networkItem, 'name')
766
- withdrawFee = self.safe_number(networkItem, 'fee')
767
- depositEnable = self.safe_value(networkItem, 'canDeposit')
768
- withdrawEnable = self.safe_value(networkItem, 'canWithdraw')
769
- isDepositEnabled = isDepositEnabled or depositEnable
770
- isWithdrawEnabled = isWithdrawEnabled or withdrawEnable
771
- fees[network] = withdrawFee
772
- active = (isWithdrawEnabled and isDepositEnabled)
773
- result[code] = {
774
- 'id': id,
775
- 'name': None,
776
- 'code': code,
777
- 'precision': None,
778
- 'info': currency,
779
- 'active': active,
780
- 'deposit': isDepositEnabled,
781
- 'withdraw': isWithdrawEnabled,
782
- 'fee': None,
783
- 'fees': fees,
784
- 'limits': self.limits,
785
- }
786
- return result
787
-
788
- def parse_balance(self, response):
789
- balances = self.safe_value(response['result'], 'coins')
790
- result = {
791
- 'info': response,
792
- }
793
- for i in range(0, len(balances)):
794
- balance = balances[i]
795
- # { enName: "BTC",
796
- # freez: "0.00000000",
797
- # unitDecimal: 8, # always 8
798
- # cnName: "BTC",
799
- # isCanRecharge: True, # TODO: should use self
800
- # unitTag: "฿",
801
- # isCanWithdraw: True, # TODO: should use self
802
- # available: "0.00000000",
803
- # key: "btc" }
804
- account = self.account()
805
- currencyId = self.safe_string(balance, 'key')
806
- code = self.safe_currency_code(currencyId)
807
- account['free'] = self.safe_string(balance, 'available')
808
- account['used'] = self.safe_string(balance, 'freez')
809
- result[code] = account
810
- return self.safe_balance(result)
811
-
812
- def parse_swap_balance(self, response):
813
- result = {
814
- 'info': response,
815
- }
816
- data = self.safe_value(response, 'data', {})
817
- for i in range(0, len(data)):
818
- balance = data[i]
819
- #
820
- # {
821
- # "userId": "6896693805014120448",
822
- # "currencyId": "6",
823
- # "currencyName": "usdt",
824
- # "amount": "30.56585118",
825
- # "freezeAmount": "0",
826
- # "contractType": 1,
827
- # "id": "6899113714763638819",
828
- # "createTime": "1644876888934",
829
- # "modifyTime": "1645787446037",
830
- # "accountBalance": "30.56585118",
831
- # "allMargin": "0",
832
- # "allowTransferOutAmount": "30.56585118"
833
- # },
834
- #
835
- code = self.safe_currency_code(self.safe_string(balance, 'currencyName'))
836
- account = self.account()
837
- account['total'] = self.safe_string(balance, 'accountBalance')
838
- account['free'] = self.safe_string(balance, 'allowTransferOutAmount')
839
- account['used'] = self.safe_string(balance, 'freezeAmount')
840
- result[code] = account
841
- return self.safe_balance(result)
842
-
843
- def parse_margin_balance(self, response, marginMode):
844
- result = {
845
- 'info': response,
846
- }
847
- levers = None
848
- if marginMode == 'isolated':
849
- message = self.safe_value(response, 'message', {})
850
- data = self.safe_value(message, 'datas', {})
851
- levers = self.safe_value(data, 'levers', [])
852
- else:
853
- crossResponse = self.safe_value(response, 'result', {})
854
- levers = self.safe_value(crossResponse, 'list', [])
855
- for i in range(0, len(levers)):
856
- balance = levers[i]
857
- #
858
- # Isolated Margin
859
- #
860
- # {
861
- # "cNetUSD": "0.00",
862
- # "repayLeverShow": "-",
863
- # "cCanLoanIn": "0.002115400000000",
864
- # "fNetCNY": "147.76081161",
865
- # "fLoanIn": "0.00",
866
- # "repayLevel": 0,
867
- # "level": 1,
868
- # "netConvertCNY": "147.760811613032",
869
- # "cFreeze": "0.00",
870
- # "cUnitTag": "BTC",
871
- # "version": 1646783178609,
872
- # "cAvailableUSD": "0.00",
873
- # "cNetCNY": "0.00",
874
- # "riskRate": "-",
875
- # "fAvailableUSD": "20.49273433",
876
- # "fNetUSD": "20.49273432",
877
- # "cShowName": "BTC",
878
- # "leverMultiple": "5.00",
879
- # "couldTransferOutFiat": "20.49273433",
880
- # "noticeLine": "1.13",
881
- # "fFreeze": "0.00",
882
- # "cUnitDecimal": 8,
883
- # "fCanLoanIn": "81.970937320000000",
884
- # "cAvailable": "0.00",
885
- # "repayLock": False,
886
- # "status": 1,
887
- # "forbidType": 0,
888
- # "totalConvertCNY": "147.760811613032",
889
- # "cAvailableCNY": "0.00",
890
- # "unwindPrice": "0.00",
891
- # "fOverdraft": "0.00",
892
- # "fShowName": "USDT",
893
- # "statusShow": "%E6%AD%A3%E5%B8%B8",
894
- # "cOverdraft": "0.00",
895
- # "netConvertUSD": "20.49273433",
896
- # "cNetBtc": "0.00",
897
- # "loanInConvertCNY": "0.00",
898
- # "fAvailableCNY": "147.760811613032",
899
- # "key": "btcusdt",
900
- # "fNetBtc": "0.0005291",
901
- # "fUnitDecimal": 8,
902
- # "loanInConvertUSD": "0.00",
903
- # "showName": "BTC/USDT",
904
- # "startLine": "1.25",
905
- # "totalConvertUSD": "20.49273433",
906
- # "couldTransferOutCoin": "0.00",
907
- # "cEnName": "BTC",
908
- # "leverMultipleInterest": "3.00",
909
- # "fAvailable": "20.49273433",
910
- # "fEnName": "USDT",
911
- # "forceRepayLine": "1.08",
912
- # "cLoanIn": "0.00"
913
- # }
914
- #
915
- # Cross Margin
916
- #
917
- # [
918
- # {
919
- # "fundType": 2,
920
- # "loanIn": 0,
921
- # "amount": 0,
922
- # "freeze": 0,
923
- # "overdraft": 0,
924
- # "key": "BTC",
925
- # "canTransferOut": 0
926
- # },
927
- # ],
928
- #
929
- account = self.account()
930
- if marginMode == 'isolated':
931
- code = self.safe_currency_code(self.safe_string(balance, 'fShowName'))
932
- account['total'] = self.safe_string(balance, 'fAvailableUSD') # total amount in USD
933
- account['free'] = self.safe_string(balance, 'couldTransferOutFiat')
934
- account['used'] = self.safe_string(balance, 'fFreeze')
935
- result[code] = account
936
- else:
937
- code = self.safe_currency_code(self.safe_string(balance, 'key'))
938
- account['total'] = self.safe_string(balance, 'amount')
939
- account['free'] = self.safe_string(balance, 'canTransferOut')
940
- account['used'] = self.safe_string(balance, 'freeze')
941
- result[code] = account
942
- return self.safe_balance(result)
943
-
944
- def fetch_balance(self, params={}):
945
- """
946
- query for balance and get the amount of funds available for trading or funds locked in orders
947
- :param dict params: extra parameters specific to the zb api endpoint
948
- :param str params['marginMode']: 'cross' or 'isolated'
949
- :returns dict: a `balance structure <https://docs.ccxt.com/en/latest/manual.html?#balance-structure>`
950
- """
951
- self.load_markets()
952
- marketType, marketTypeQuery = self.handle_market_type_and_params('fetchBalance', None, params)
953
- marginMode, query = self.handle_margin_mode_and_params('fetchBalance', marketTypeQuery)
954
- swap = (marketType == 'swap')
955
- marginMethod = 'spotV1PrivateGetGetCrossAssets' if (marginMode == 'cross') else 'spotV1PrivateGetGetLeverAssetsInfo'
956
- method = self.get_supported_mapping(marketType, {
957
- 'spot': 'spotV1PrivateGetGetAccountInfo',
958
- 'swap': 'contractV2PrivateGetFundBalance',
959
- 'margin': marginMethod,
960
- })
961
- if marginMode == 'isolated':
962
- method = 'spotV1PrivateGetGetLeverAssetsInfo'
963
- elif marginMode == 'cross':
964
- method = 'spotV1PrivateGetGetCrossAssets'
965
- request = {
966
- # 'futuresAccountType': 1, # SWAP
967
- # 'currencyId': currency['id'], # SWAP
968
- # 'currencyName': 'usdt', # SWAP
969
- }
970
- if swap:
971
- request['futuresAccountType'] = 1
972
- response = getattr(self, method)(self.extend(request, query))
973
- #
974
- # Spot
975
- #
976
- # {
977
- # "result": {
978
- # "coins": [
979
- # {
980
- # "isCanWithdraw": "true",
981
- # "canLoan": False,
982
- # "fundstype": 51,
983
- # "showName": "ZB",
984
- # "isCanRecharge": "true",
985
- # "cnName": "ZB",
986
- # "enName": "ZB",
987
- # "available": "0",
988
- # "freez": "0",
989
- # "unitTag": "ZB",
990
- # "key": "zb",
991
- # "unitDecimal": 8
992
- # },
993
- # ],
994
- # "version": 1645856691340,
995
- # "base": {
996
- # "auth_google_enabled": True,
997
- # "auth_mobile_enabled": False,
998
- # "trade_password_enabled": True,
999
- # "username": "blank@gmail.com"
1000
- # }
1001
- # },
1002
- # "leverPerm": True,
1003
- # "otcPerm": False,
1004
- # "assetPerm": True,
1005
- # "moneyPerm": True,
1006
- # "subUserPerm": True,
1007
- # "entrustPerm": True
1008
- # }
1009
- #
1010
- # Swap
1011
- #
1012
- # {
1013
- # "code": 10000,
1014
- # "data": [
1015
- # {
1016
- # "userId": "6896693805014120448",
1017
- # "currencyId": "6",
1018
- # "currencyName": "usdt",
1019
- # "amount": "30.56585118",
1020
- # "freezeAmount": "0",
1021
- # "contractType": 1,
1022
- # "id": "6899113714763638819",
1023
- # "createTime": "1644876888934",
1024
- # "modifyTime": "1645787446037",
1025
- # "accountBalance": "30.56585118",
1026
- # "allMargin": "0",
1027
- # "allowTransferOutAmount": "30.56585118"
1028
- # },
1029
- # ],
1030
- # "desc": "操作成功"
1031
- # }
1032
- #
1033
- # Isolated Margin
1034
- #
1035
- # {
1036
- # "code": 1000,
1037
- # "message": {
1038
- # "des": "success",
1039
- # "isSuc": True,
1040
- # "datas": {
1041
- # "leverPerm": True,
1042
- # "levers": [
1043
- # {
1044
- # "cNetUSD": "0.00",
1045
- # "repayLeverShow": "-",
1046
- # "cCanLoanIn": "0.002115400000000",
1047
- # "fNetCNY": "147.76081161",
1048
- # "fLoanIn": "0.00",
1049
- # "repayLevel": 0,
1050
- # "level": 1,
1051
- # "netConvertCNY": "147.760811613032",
1052
- # "cFreeze": "0.00",
1053
- # "cUnitTag": "BTC",
1054
- # "version": 1646783178609,
1055
- # "cAvailableUSD": "0.00",
1056
- # "cNetCNY": "0.00",
1057
- # "riskRate": "-",
1058
- # "fAvailableUSD": "20.49273433",
1059
- # "fNetUSD": "20.49273432",
1060
- # "cShowName": "BTC",
1061
- # "leverMultiple": "5.00",
1062
- # "couldTransferOutFiat": "20.49273433",
1063
- # "noticeLine": "1.13",
1064
- # "fFreeze": "0.00",
1065
- # "cUnitDecimal": 8,
1066
- # "fCanLoanIn": "81.970937320000000",
1067
- # "cAvailable": "0.00",
1068
- # "repayLock": False,
1069
- # "status": 1,
1070
- # "forbidType": 0,
1071
- # "totalConvertCNY": "147.760811613032",
1072
- # "cAvailableCNY": "0.00",
1073
- # "unwindPrice": "0.00",
1074
- # "fOverdraft": "0.00",
1075
- # "fShowName": "USDT",
1076
- # "statusShow": "%E6%AD%A3%E5%B8%B8",
1077
- # "cOverdraft": "0.00",
1078
- # "netConvertUSD": "20.49273433",
1079
- # "cNetBtc": "0.00",
1080
- # "loanInConvertCNY": "0.00",
1081
- # "fAvailableCNY": "147.760811613032",
1082
- # "key": "btcusdt",
1083
- # "fNetBtc": "0.0005291",
1084
- # "fUnitDecimal": 8,
1085
- # "loanInConvertUSD": "0.00",
1086
- # "showName": "BTC/USDT",
1087
- # "startLine": "1.25",
1088
- # "totalConvertUSD": "20.49273433",
1089
- # "couldTransferOutCoin": "0.00",
1090
- # "cEnName": "BTC",
1091
- # "leverMultipleInterest": "3.00",
1092
- # "fAvailable": "20.49273433",
1093
- # "fEnName": "USDT",
1094
- # "forceRepayLine": "1.08",
1095
- # "cLoanIn": "0.00"
1096
- # }
1097
- # ]
1098
- # }
1099
- # }
1100
- # }
1101
- #
1102
- # Cross Margin
1103
- #
1104
- # {
1105
- # "code": 1000,
1106
- # "message": "操作成功",
1107
- # "result": {
1108
- # "loanIn": 0,
1109
- # "total": 71.167,
1110
- # "riskRate": "-",
1111
- # "list" :[
1112
- # {
1113
- # "fundType": 2,
1114
- # "loanIn": 0,
1115
- # "amount": 0,
1116
- # "freeze": 0,
1117
- # "overdraft": 0,
1118
- # "key": "BTC",
1119
- # "canTransferOut": 0
1120
- # },
1121
- # ],
1122
- # "net": 71.167
1123
- # }
1124
- # }
1125
- #
1126
- # todo: use self somehow
1127
- # permissions = response['result']['base']
1128
- if swap:
1129
- return self.parse_swap_balance(response)
1130
- elif marginMode is not None:
1131
- return self.parse_margin_balance(response, marginMode)
1132
- else:
1133
- return self.parse_balance(response)
1134
-
1135
- def parse_deposit_address(self, depositAddress, currency=None):
1136
- #
1137
- # fetchDepositAddress
1138
- #
1139
- # {
1140
- # "key": "0x0af7f36b8f09410f3df62c81e5846da673d4d9a9"
1141
- # }
1142
- #
1143
- # fetchDepositAddresses
1144
- #
1145
- # {
1146
- # "blockChain": "btc",
1147
- # "isUseMemo": False,
1148
- # "address": "1LL5ati6pXHZnTGzHSA3rWdqi4mGGXudwM",
1149
- # "canWithdraw": True,
1150
- # "canDeposit": True
1151
- # }
1152
- # {
1153
- # "blockChain": "bts",
1154
- # "isUseMemo": True,
1155
- # "account": "btstest",
1156
- # "memo": "123",
1157
- # "canWithdraw": True,
1158
- # "canDeposit": True
1159
- # }
1160
- #
1161
- address = self.safe_string_2(depositAddress, 'key', 'address')
1162
- tag = None
1163
- memo = self.safe_string(depositAddress, 'memo')
1164
- if memo is not None:
1165
- tag = memo
1166
- elif address.find('_') >= 0:
1167
- parts = address.split('_')
1168
- address = parts[0] # WARNING: MAY BE tag_address INSTEAD OF address_tag FOR SOME CURRENCIESnot !
1169
- tag = parts[1]
1170
- self.check_address(address)
1171
- currencyId = self.safe_string(depositAddress, 'blockChain')
1172
- code = self.safe_currency_code(currencyId, currency)
1173
- return {
1174
- 'currency': code,
1175
- 'address': address,
1176
- 'tag': tag,
1177
- 'network': None,
1178
- 'info': depositAddress,
1179
- }
1180
-
1181
- def fetch_deposit_addresses(self, codes=None, params={}):
1182
- self.load_markets()
1183
- response = self.spotV1PrivateGetGetPayinAddress(params)
1184
- #
1185
- # {
1186
- # "code": 1000,
1187
- # "message": {
1188
- # "des": "success",
1189
- # "isSuc": True,
1190
- # "datas": [
1191
- # {
1192
- # "blockChain": "btc",
1193
- # "isUseMemo": False,
1194
- # "address": "1LL5ati6pXHZnTGzHSA3rWdqi4mGGXudwM",
1195
- # "canWithdraw": True,
1196
- # "canDeposit": True
1197
- # },
1198
- # {
1199
- # "blockChain": "bts",
1200
- # "isUseMemo": True,
1201
- # "account": "btstest",
1202
- # "memo": "123",
1203
- # "canWithdraw": True,
1204
- # "canDeposit": True
1205
- # },
1206
- # ]
1207
- # }
1208
- # }
1209
- #
1210
- message = self.safe_value(response, 'message', {})
1211
- datas = self.safe_value(message, 'datas', [])
1212
- return self.parse_deposit_addresses(datas, codes)
1213
-
1214
- def fetch_deposit_address(self, code: str, params={}):
1215
- """
1216
- fetch the deposit address for a currency associated with self account
1217
- :param str code: unified currency code
1218
- :param dict params: extra parameters specific to the zb api endpoint
1219
- :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1220
- """
1221
- self.load_markets()
1222
- currency = self.currency(code)
1223
- request = {
1224
- 'currency': currency['id'],
1225
- }
1226
- response = self.spotV1PrivateGetGetUserAddress(self.extend(request, params))
1227
- #
1228
- # {
1229
- # "code": 1000,
1230
- # "message": {
1231
- # "des": "success",
1232
- # "isSuc": True,
1233
- # "datas": {
1234
- # "key": "0x0af7f36b8f09410f3df62c81e5846da673d4d9a9"
1235
- # }
1236
- # }
1237
- # }
1238
- #
1239
- message = self.safe_value(response, 'message', {})
1240
- datas = self.safe_value(message, 'datas', {})
1241
- return self.parse_deposit_address(datas, currency)
1242
-
1243
- def fetch_order_book(self, symbol: str, limit: Optional[int] = None, params={}):
1244
- """
1245
- fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1246
- :param str symbol: unified symbol of the market to fetch the order book for
1247
- :param int|None limit: the maximum amount of order book entries to return
1248
- :param dict params: extra parameters specific to the zb api endpoint
1249
- :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1250
- """
1251
- self.load_markets()
1252
- market = self.market(symbol)
1253
- request = {
1254
- # 'market': market['id'], # only applicable to SPOT
1255
- # 'symbol': market['id'], # only applicable to SWAP
1256
- # 'size': limit, # 1-50 applicable to SPOT and SWAP
1257
- # 'merge': 5.0, # float default depth only applicable to SPOT
1258
- # 'scale': 5, # int accuracy, only applicable to SWAP
1259
- }
1260
- marketIdField = 'symbol' if market['swap'] else 'market'
1261
- request[marketIdField] = market['id']
1262
- method = self.get_supported_mapping(market['type'], {
1263
- 'spot': 'spotV1PublicGetDepth',
1264
- 'swap': 'contractV1PublicGetDepth',
1265
- })
1266
- if limit is not None:
1267
- request['size'] = limit
1268
- response = getattr(self, method)(self.extend(request, params))
1269
- #
1270
- # Spot
1271
- #
1272
- # {
1273
- # "asks":[
1274
- # [35000.0,0.2741],
1275
- # [34949.0,0.0173],
1276
- # [34900.0,0.5004],
1277
- # ],
1278
- # "bids":[
1279
- # [34119.32,0.0030],
1280
- # [34107.83,0.1500],
1281
- # [34104.42,0.1500],
1282
- # ],
1283
- # "timestamp":1624536510
1284
- # }
1285
- #
1286
- # Swap
1287
- #
1288
- # {
1289
- # "code": 10000,
1290
- # "desc": "操作成功",
1291
- # "data": {
1292
- # "asks": [
1293
- # [43416.6,0.02],
1294
- # [43418.25,0.04],
1295
- # [43425.82,0.02]
1296
- # ],
1297
- # "bids": [
1298
- # [43414.61,0.1],
1299
- # [43414.18,0.04],
1300
- # [43413.03,0.05]
1301
- # ],
1302
- # "time": 1645087743071
1303
- # }
1304
- # }
1305
- #
1306
- result = None
1307
- timestamp = None
1308
- if market['type'] == 'swap':
1309
- result = self.safe_value(response, 'data')
1310
- timestamp = self.safe_integer(result, 'time')
1311
- else:
1312
- result = response
1313
- timestamp = self.safe_timestamp(response, 'timestamp')
1314
- return self.parse_order_book(result, symbol, timestamp)
1315
-
1316
- def fetch_tickers(self, symbols: Optional[List[str]] = None, params={}):
1317
- """
1318
- fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
1319
- :param [str]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1320
- :param dict params: extra parameters specific to the zb api endpoint
1321
- :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1322
- """
1323
- self.load_markets()
1324
- symbols = self.market_symbols(symbols)
1325
- response = self.spotV1PublicGetAllTicker(params)
1326
- result = {}
1327
- marketsByIdWithoutUnderscore = {}
1328
- marketIds = self.ids
1329
- for i in range(0, len(marketIds)):
1330
- marketId = marketIds[i]
1331
- tickerId = marketId.replace('_', '')
1332
- marketsByIdWithoutUnderscore[tickerId] = marketId
1333
- ids = list(response.keys())
1334
- for i in range(0, len(ids)):
1335
- marketId = self.safe_value(marketsByIdWithoutUnderscore, ids[i])
1336
- market = self.safe_market(marketId, None, '_')
1337
- if market is not None:
1338
- symbol = market['symbol']
1339
- ticker = self.safe_value(response, ids[i])
1340
- if ticker is not None:
1341
- result[symbol] = self.parse_ticker(ticker, market)
1342
- return self.filter_by_array(result, 'symbol', symbols)
1343
-
1344
- def fetch_ticker(self, symbol: str, params={}):
1345
- """
1346
- fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1347
- :param str symbol: unified symbol of the market to fetch the ticker for
1348
- :param dict params: extra parameters specific to the zb api endpoint
1349
- :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1350
- """
1351
- self.load_markets()
1352
- market = self.market(symbol)
1353
- request = {
1354
- # 'market': market['id'], # only applicable to SPOT
1355
- # 'symbol': market['id'], # only applicable to SWAP
1356
- }
1357
- marketIdField = 'symbol' if market['swap'] else 'market'
1358
- request[marketIdField] = market['id']
1359
- method = self.get_supported_mapping(market['type'], {
1360
- 'spot': 'spotV1PublicGetTicker',
1361
- 'swap': 'contractV1PublicGetTicker',
1362
- })
1363
- response = getattr(self, method)(self.extend(request, params))
1364
- #
1365
- # Spot
1366
- #
1367
- # {
1368
- # "date":"1624399623587",
1369
- # "ticker":{
1370
- # "high":"33298.38",
1371
- # "vol":"56152.9012",
1372
- # "last":"32578.55",
1373
- # "low":"28808.19",
1374
- # "buy":"32572.68",
1375
- # "sell":"32615.37",
1376
- # "turnover":"1764201303.6100",
1377
- # "open":"31664.85",
1378
- # "riseRate":"2.89"
1379
- # }
1380
- # }
1381
- #
1382
- # Swap
1383
- #
1384
- # {
1385
- # "code": 10000,
1386
- # "desc": "操作成功",
1387
- # "data": {
1388
- # "BTC_USDT": [44053.47,44357.77,42911.54,43297.79,53471.264,-1.72,1645093002,302201.255084]
1389
- # }
1390
- # }
1391
- #
1392
- ticker = None
1393
- if market['type'] == 'swap':
1394
- ticker = {}
1395
- data = self.safe_value(response, 'data')
1396
- values = self.safe_value(data, market['id'], [])
1397
- for i in range(0, len(values)):
1398
- ticker['open'] = self.safe_value(values, 0)
1399
- ticker['high'] = self.safe_value(values, 1)
1400
- ticker['low'] = self.safe_value(values, 2)
1401
- ticker['last'] = self.safe_value(values, 3)
1402
- ticker['vol'] = self.safe_value(values, 4)
1403
- ticker['riseRate'] = self.safe_value(values, 5)
1404
- else:
1405
- ticker = self.safe_value(response, 'ticker', {})
1406
- ticker['date'] = self.safe_value(response, 'date')
1407
- return self.parse_ticker(ticker, market)
1408
-
1409
- def parse_ticker(self, ticker, market=None):
1410
- #
1411
- # Spot
1412
- #
1413
- # {
1414
- # "date":"1624399623587", # injected from outside
1415
- # "high":"33298.38",
1416
- # "vol":"56152.9012",
1417
- # "last":"32578.55",
1418
- # "low":"28808.19",
1419
- # "buy":"32572.68",
1420
- # "sell":"32615.37",
1421
- # "turnover":"1764201303.6100",
1422
- # "open":"31664.85",
1423
- # "riseRate":"2.89"
1424
- # }
1425
- #
1426
- # Swap
1427
- #
1428
- # {
1429
- # open: 44083.82,
1430
- # high: 44357.77,
1431
- # low: 42911.54,
1432
- # last: 43097.87,
1433
- # vol: 53451.641,
1434
- # riseRate: -2.24
1435
- # }
1436
- #
1437
- timestamp = self.safe_integer(ticker, 'date', self.milliseconds())
1438
- last = self.safe_string(ticker, 'last')
1439
- return self.safe_ticker({
1440
- 'symbol': self.safe_symbol(None, market),
1441
- 'timestamp': timestamp,
1442
- 'datetime': self.iso8601(timestamp),
1443
- 'high': self.safe_string(ticker, 'high'),
1444
- 'low': self.safe_string(ticker, 'low'),
1445
- 'bid': self.safe_string(ticker, 'buy'),
1446
- 'bidVolume': None,
1447
- 'ask': self.safe_string(ticker, 'sell'),
1448
- 'askVolume': None,
1449
- 'vwap': None,
1450
- 'open': self.safe_string(ticker, 'open'),
1451
- 'close': last,
1452
- 'last': last,
1453
- 'previousClose': None,
1454
- 'change': None,
1455
- 'percentage': None,
1456
- 'average': None,
1457
- 'baseVolume': self.safe_string(ticker, 'vol'),
1458
- 'quoteVolume': None,
1459
- 'info': ticker,
1460
- }, market)
1461
-
1462
- def parse_ohlcv(self, ohlcv, market=None):
1463
- if market['swap']:
1464
- ohlcvLength = len(ohlcv)
1465
- if ohlcvLength > 5:
1466
- return [
1467
- self.safe_timestamp(ohlcv, 5),
1468
- self.safe_number(ohlcv, 0),
1469
- self.safe_number(ohlcv, 1),
1470
- self.safe_number(ohlcv, 2),
1471
- self.safe_number(ohlcv, 3),
1472
- self.safe_number(ohlcv, 4),
1473
- ]
1474
- else:
1475
- return [
1476
- self.safe_timestamp(ohlcv, 4),
1477
- self.safe_number(ohlcv, 0),
1478
- self.safe_number(ohlcv, 1),
1479
- self.safe_number(ohlcv, 2),
1480
- self.safe_number(ohlcv, 3),
1481
- None,
1482
- ]
1483
- else:
1484
- return [
1485
- self.safe_integer(ohlcv, 0),
1486
- self.safe_number(ohlcv, 1),
1487
- self.safe_number(ohlcv, 2),
1488
- self.safe_number(ohlcv, 3),
1489
- self.safe_number(ohlcv, 4),
1490
- self.safe_number(ohlcv, 5),
1491
- ]
1492
-
1493
- def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Optional[int] = None, limit: Optional[int] = None, params={}):
1494
- """
1495
- fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1496
- :param str symbol: unified symbol of the market to fetch OHLCV data for
1497
- :param str timeframe: the length of time each candle represents
1498
- :param int|None since: timestamp in ms of the earliest candle to fetch
1499
- :param int|None limit: the maximum amount of candles to fetch
1500
- :param dict params: extra parameters specific to the zb api endpoint
1501
- :returns [[int]]: A list of candles ordered, open, high, low, close, volume
1502
- """
1503
- self.load_markets()
1504
- market = self.market(symbol)
1505
- swap = market['swap']
1506
- spot = market['spot']
1507
- options = self.safe_value(self.options, 'timeframes', {})
1508
- timeframes = self.safe_value(options, market['type'], {})
1509
- timeframeValue = self.safe_string(timeframes, timeframe)
1510
- if timeframeValue is None:
1511
- raise NotSupported(self.id + ' fetchOHLCV() does not support ' + timeframe + ' timeframe for ' + market['type'] + ' markets')
1512
- if limit is None:
1513
- limit = 1000
1514
- request = {
1515
- 'size': limit,
1516
- # 'market': market['id'], # spot only
1517
- # 'symbol': market['id'], # swap only
1518
- # 'type': timeframeValue, # spot only
1519
- # 'period': timeframeValue, # swap only
1520
- # 'since': since, # spot only
1521
- # 'size': limit, # spot and swap
1522
- }
1523
- marketIdField = 'symbol' if swap else 'market'
1524
- request[marketIdField] = market['id']
1525
- periodField = 'period' if swap else 'type'
1526
- request[periodField] = timeframeValue
1527
- price = self.safe_string(params, 'price')
1528
- params = self.omit(params, 'price')
1529
- method = self.get_supported_mapping(market['type'], {
1530
- 'spot': 'spotV1PublicGetKline',
1531
- 'swap': 'contractV1PublicGetKline',
1532
- })
1533
- if swap:
1534
- if price == 'mark':
1535
- method = 'contractV1PublicGetMarkKline'
1536
- elif price == 'index':
1537
- method = 'contractV1PublicGetIndexKline'
1538
- elif spot:
1539
- if since is not None:
1540
- request['since'] = since
1541
- response = getattr(self, method)(self.extend(request, params))
1542
- #
1543
- # Spot
1544
- #
1545
- # {
1546
- # "symbol": "BTC",
1547
- # "data": [
1548
- # [1645091400000,43183.24,43187.49,43145.92,43182.28,0.9110],
1549
- # [1645091460000,43182.18,43183.15,43182.06,43183.15,1.4393],
1550
- # [1645091520000,43182.11,43240.1,43182.11,43240.1,0.3802]
1551
- # ],
1552
- # "moneyType": "USDT"
1553
- # }
1554
- #
1555
- # Swap
1556
- #
1557
- # {
1558
- # "code": 10000,
1559
- # "desc": "操作成功",
1560
- # "data": [
1561
- # [41433.44,41433.44,41405.88,41408.75,21.368,1646366460],
1562
- # [41409.25,41423.74,41408.8,41423.42,9.828,1646366520],
1563
- # [41423.96,41429.39,41369.98,41370.31,123.104,1646366580]
1564
- # ]
1565
- # }
1566
- #
1567
- # Mark
1568
- #
1569
- # {
1570
- # "code": 10000,
1571
- # "desc": "操作成功",
1572
- # "data": [
1573
- # [41603.39,41603.39,41591.59,41600.81,1646381760],
1574
- # [41600.36,41605.75,41587.69,41601.97,1646381820],
1575
- # [41601.97,41601.97,41562.62,41593.96,1646381880]
1576
- # ]
1577
- # }
1578
- #
1579
- # Index
1580
- #
1581
- # {
1582
- # "code": 10000,
1583
- # "desc": "操作成功",
1584
- # "data": [
1585
- # [41697.53,41722.29,41689.16,41689.16,1646381640],
1586
- # [41690.1,41691.73,41611.61,41611.61,1646381700],
1587
- # [41611.61,41619.49,41594.87,41594.87,1646381760]
1588
- # ]
1589
- # }
1590
- #
1591
- data = self.safe_value(response, 'data', [])
1592
- return self.parse_ohlcvs(data, market, timeframe, since, limit)
1593
-
1594
- def parse_trade(self, trade, market=None):
1595
- #
1596
- # Spot
1597
- #
1598
- # {
1599
- # "date":1624537391,
1600
- # "amount":"0.0142",
1601
- # "price":"33936.42",
1602
- # "trade_type":"ask",
1603
- # "type":"sell",
1604
- # "tid":1718869018
1605
- # }
1606
- #
1607
- # Swap
1608
- #
1609
- # {
1610
- # "amount": "0.002",
1611
- # "createTime": "1645787446034",
1612
- # "feeAmount": "-0.05762699",
1613
- # "feeCurrency": "USDT",
1614
- # "id": "6902932868050395136",
1615
- # "maker": False,
1616
- # "orderId": "6902932868042006528",
1617
- # "price": "38417.99",
1618
- # "relizedPnl": "0.30402",
1619
- # "side": 4,
1620
- # "userId": "6896693805014120448"
1621
- # },
1622
- #
1623
- sideField = 'side' if market['swap'] else 'trade_type'
1624
- side = self.safe_string(trade, sideField)
1625
- takerOrMaker = None
1626
- maker = self.safe_value(trade, 'maker')
1627
- if maker is not None:
1628
- takerOrMaker = 'maker' if maker else 'taker'
1629
- if market['spot']:
1630
- side = 'buy' if (side == 'bid') else 'sell'
1631
- else:
1632
- if side == '3':
1633
- side = 'sell' # close long
1634
- elif side == '4':
1635
- side = 'buy' # close short
1636
- elif side == '1':
1637
- side = 'buy' # open long
1638
- elif side == '2':
1639
- side = 'sell' # open short
1640
- timestamp = None
1641
- if market['swap']:
1642
- timestamp = self.safe_integer(trade, 'createTime')
1643
- else:
1644
- timestamp = self.safe_timestamp(trade, 'date')
1645
- price = self.safe_string(trade, 'price')
1646
- amount = self.safe_string(trade, 'amount')
1647
- fee = None
1648
- feeCostString = self.safe_string(trade, 'feeAmount')
1649
- if feeCostString is not None:
1650
- feeCurrencyId = self.safe_string(trade, 'feeCurrency')
1651
- fee = {
1652
- 'cost': feeCostString,
1653
- 'currency': self.safe_currency_code(feeCurrencyId),
1654
- }
1655
- market = self.safe_market(None, market)
1656
- return self.safe_trade({
1657
- 'info': trade,
1658
- 'id': self.safe_string(trade, 'tid'),
1659
- 'timestamp': timestamp,
1660
- 'datetime': self.iso8601(timestamp),
1661
- 'symbol': market['symbol'],
1662
- 'type': None,
1663
- 'side': side,
1664
- 'order': self.safe_string(trade, 'orderId'),
1665
- 'takerOrMaker': takerOrMaker,
1666
- 'price': price,
1667
- 'amount': amount,
1668
- 'cost': None,
1669
- 'fee': fee,
1670
- }, market)
1671
-
1672
- def fetch_trades(self, symbol: str, since: Optional[int] = None, limit: Optional[int] = None, params={}):
1673
- """
1674
- get the list of most recent trades for a particular symbol
1675
- :param str symbol: unified symbol of the market to fetch trades for
1676
- :param int|None since: timestamp in ms of the earliest trade to fetch
1677
- :param int|None limit: the maximum amount of trades to fetch
1678
- :param dict params: extra parameters specific to the zb api endpoint
1679
- :returns [dict]: a list of `trade structures <https://docs.ccxt.com/en/latest/manual.html?#public-trades>`
1680
- """
1681
- if symbol is None:
1682
- raise ArgumentsRequired(self.id + ' fetchTrades() requires a symbol argument')
1683
- self.load_markets()
1684
- market = self.market(symbol)
1685
- swap = market['swap']
1686
- request = {
1687
- # 'market': market['id'], # SPOT
1688
- # 'symbol': market['id'], # SWAP
1689
- # 'side': 1, # SWAP
1690
- # 'dateRange': 0, # SWAP
1691
- # 'startTime': since, # SWAP
1692
- # 'endtime': self.milliseconds(), # SWAP
1693
- # 'pageNum': 1, # SWAP
1694
- # 'pageSize': limit, # SWAP default is 10
1695
- }
1696
- if limit is not None:
1697
- request['pageSize'] = limit
1698
- if since is not None:
1699
- request['startTime'] = since
1700
- marketIdField = 'symbol' if swap else 'market'
1701
- request[marketIdField] = market['id']
1702
- if swap and params['pageNum'] is None:
1703
- request['pageNum'] = 1
1704
- method = self.get_supported_mapping(market['type'], {
1705
- 'spot': 'spotV1PublicGetTrades',
1706
- 'swap': 'contractV2PrivateGetTradeTradeHistory',
1707
- })
1708
- response = getattr(self, method)(self.extend(request, params))
1709
- #
1710
- # Spot
1711
- #
1712
- # [
1713
- # {"date":1624537391,"amount":"0.0142","price":"33936.42","trade_type":"ask","type":"sell","tid":1718869018},
1714
- # {"date":1624537391,"amount":"0.0010","price":"33936.42","trade_type":"ask","type":"sell","tid":1718869020},
1715
- # {"date":1624537391,"amount":"0.0133","price":"33936.42","trade_type":"ask","type":"sell","tid":1718869021},
1716
- # ]
1717
- #
1718
- # Swap
1719
- #
1720
- # {
1721
- # "code": 10000,
1722
- # "data": {
1723
- # "list": [
1724
- # {
1725
- # "amount": "0.002",
1726
- # "createTime": "1645787446034",
1727
- # "feeAmount": "-0.05762699",
1728
- # "feeCurrency": "USDT",
1729
- # "id": "6902932868050395136",
1730
- # "maker": False,
1731
- # "orderId": "6902932868042006528",
1732
- # "price": "38417.99",
1733
- # "relizedPnl": "0.30402",
1734
- # "side": 4,
1735
- # "userId": "6896693805014120448"
1736
- # },
1737
- # ],
1738
- # "pageNum": 1,
1739
- # "pageSize": 10
1740
- # },
1741
- # "desc": "操作成功"
1742
- # }
1743
- #
1744
- if swap:
1745
- data = self.safe_value(response, 'data')
1746
- response = self.safe_value(data, 'list')
1747
- return self.parse_trades(response, market, since, limit)
1748
-
1749
- def create_order(self, symbol: str, type, side: OrderSide, amount, price=None, params={}):
1750
- """
1751
- create a trade order
1752
- :param str symbol: unified symbol of the market to create an order in
1753
- :param str type: must be 'limit'
1754
- :param str side: 'buy' or 'sell'
1755
- :param float amount: how much of currency you want to trade in units of base currency
1756
- :param float|None price: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1757
- :param dict params: extra parameters specific to the zb api endpoint
1758
- :param str params['marginMode']: 'cross' or 'isolated'
1759
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1760
- """
1761
- self.load_markets()
1762
- market = self.market(symbol)
1763
- marginMode, query = self.handle_margin_mode_and_params('createOrder', params)
1764
- swap = market['swap']
1765
- spot = market['spot']
1766
- timeInForce = self.safe_string(params, 'timeInForce')
1767
- reduceOnly = self.safe_value(params, 'reduceOnly')
1768
- triggerPrice = self.safe_value_2(params, 'triggerPrice', 'stopPrice')
1769
- stopLossPrice = self.safe_value(params, 'stopLossPrice')
1770
- takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
1771
- isStopLoss = stopLossPrice is not None
1772
- isTakeProfit = takeProfitPrice is not None
1773
- isTriggerOrder = triggerPrice is not None
1774
- if self.sum(isStopLoss, isTakeProfit, isTriggerOrder):
1775
- raise ExchangeError(self.id + ' createOrder() stopLossPrice and takeProfitPrice cannot both be defined')
1776
- isStopOrder = isStopLoss or isTakeProfit or isTriggerOrder
1777
- if isStopOrder and spot:
1778
- raise ExchangeError(self.id + ' createOrder() it is not possible to make a stop order on spot markets')
1779
- if type == 'market':
1780
- raise InvalidOrder(self.id + ' createOrder() on ' + market['type'] + ' markets does not allow market orders')
1781
- method = self.get_supported_mapping(market['type'], {
1782
- 'spot': 'spotV1PrivateGetOrder',
1783
- 'margin': 'spotV1PrivateGetOrder',
1784
- 'swap': 'contractV2PrivatePostTradeOrder',
1785
- })
1786
- request = {
1787
- 'amount': self.amount_to_precision(symbol, amount),
1788
- # 'symbol': market['id'],
1789
- # 'acctType': 0, # Spot, Margin 0/1/2 [Spot/Isolated/Cross] Optional, Default to: 0 Spot
1790
- # 'customerOrderId': '1f2g', # Spot, Margin
1791
- # 'orderType': 1, # Spot, Margin order type 1/2 [PostOnly/IOC] Optional
1792
- # 'triggerPrice': 30000.0, # Stop trigger price
1793
- # 'algoPrice': 29000.0, # Stop order price
1794
- # 'priceType': 1, # Stop Loss Take Profit, 1: Mark price, 2: Last price
1795
- # 'bizType': 1, # Stop Loss Take Profit, 1: TP, 2: SL
1796
- }
1797
- if spot:
1798
- exchangeSpecificParam = self.safe_integer(params, 'orderType', type) == 1
1799
- postOnly = self.is_post_only(False, exchangeSpecificParam, params)
1800
- request['tradeType'] = 1 if (side == 'buy') else 0
1801
- request['currency'] = market['id']
1802
- if postOnly:
1803
- request['orderType'] = 1
1804
- elif timeInForce == 'IOC':
1805
- request['orderType'] = 2
1806
- if price is not None:
1807
- request['price'] = self.price_to_precision(symbol, price)
1808
- if marginMode is not None:
1809
- if marginMode == 'isolated':
1810
- request['acctType'] = 1
1811
- elif marginMode == 'cross':
1812
- request['acctType'] = 2
1813
- elif swap:
1814
- exchangeSpecificParam = self.safe_integer(params, 'action', type) == 4
1815
- postOnly = self.is_post_only(False, exchangeSpecificParam, params)
1816
- # the default mode on zb is one way mode
1817
- # currently ccxt does not support hedge mode natively
1818
- if isStopLoss or isTakeProfit:
1819
- reduceOnly = True
1820
- if reduceOnly:
1821
- request['side'] = 0
1822
- else:
1823
- request['side'] = 5 if (side == 'buy') else 6
1824
- if isStopOrder:
1825
- method = 'contractV2PrivatePostTradeOrderAlgo'
1826
- if isStopLoss:
1827
- request['orderType'] = 2
1828
- request['bizType'] = 2
1829
- request['triggerPrice'] = self.price_to_precision(symbol, stopLossPrice)
1830
- elif isTakeProfit:
1831
- request['orderType'] = 2
1832
- request['bizType'] = 1
1833
- request['triggerPrice'] = self.price_to_precision(symbol, takeProfitPrice)
1834
- elif isTriggerOrder:
1835
- request['orderType'] = 1
1836
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
1837
- request['algoPrice'] = self.price_to_precision(symbol, price)
1838
- request['pricetype'] = 2
1839
- else:
1840
- if timeInForce == 'IOC':
1841
- request['action'] = 3
1842
- elif postOnly:
1843
- request['action'] = 4
1844
- elif timeInForce == 'FOK':
1845
- request['action'] = 5
1846
- elif type == 'limit':
1847
- request['action'] = 1
1848
- else:
1849
- request['action'] = type
1850
- if price is not None:
1851
- request['price'] = self.price_to_precision(symbol, price)
1852
- request['symbol'] = market['id']
1853
- clientOrderId = self.safe_string(params, 'clientOrderId') # OPTIONAL '^[a-zA-Z0-9-_]{1,36}$', # The user-defined order number
1854
- if clientOrderId is not None:
1855
- request['clientOrderId'] = clientOrderId
1856
- # using self.extend name causes issues in python
1857
- extendOrderAlgos = self.safe_value(params, 'extend', None) # OPTIONAL {"orderAlgos":[{"bizType":1,"priceType":1,"triggerPrice":"70000"},{"bizType":2,"priceType":1,"triggerPrice":"40000"}]}
1858
- if extendOrderAlgos is not None:
1859
- request['extend'] = extendOrderAlgos
1860
- params = self.omit(query, ['takeProfitPrice', 'stopLossPrice', 'stopPrice', 'reduceOnly', 'orderType', 'triggerPrice', 'priceType', 'clientOrderId', 'extend'])
1861
- response = getattr(self, method)(self.extend(request, params))
1862
- #
1863
- # Spot and Margin
1864
- #
1865
- # {
1866
- # "code": 1000,
1867
- # "message": "操作成功",
1868
- # "id": "202202224851151555"
1869
- # }
1870
- #
1871
- # Swap
1872
- #
1873
- # {
1874
- # "code": 10000,
1875
- # "desc": "操作成功",
1876
- # "data": {
1877
- # "orderId": "6901786759944937472",
1878
- # "orderCode": null
1879
- # }
1880
- # }
1881
- #
1882
- # Algo order
1883
- #
1884
- # {
1885
- # "code": 10000,
1886
- # "data": "6919884551305242624",
1887
- # "desc": "操作成功"
1888
- # }
1889
- #
1890
- result = response
1891
- if swap and not isStopOrder:
1892
- result = self.safe_value(response, 'data')
1893
- return self.parse_order(result, market)
1894
-
1895
- def cancel_order(self, id: str, symbol: Optional[str] = None, params={}):
1896
- """
1897
- cancels an open order
1898
- :param str id: order id
1899
- :param str symbol: unified symbol of the market the order was made in
1900
- :param dict params: extra parameters specific to the zb api endpoint
1901
- :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1902
- """
1903
- if symbol is None:
1904
- raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
1905
- self.load_markets()
1906
- market = self.market(symbol)
1907
- swap = market['swap']
1908
- request = {
1909
- # 'currency': self.market_id(symbol), # only applicable to SPOT
1910
- # 'id': str(id), # only applicable to SPOT
1911
- # 'symbol': self.market_id(symbol), # only applicable to SWAP
1912
- # 'orderId': str(id), # only applicable to SWAP
1913
- # 'clientOrderId': params['clientOrderId'], # only applicable to SWAP
1914
- }
1915
- marketIdField = 'symbol' if swap else 'currency'
1916
- request[marketIdField] = self.market_id(symbol)
1917
- orderIdField = 'orderId' if swap else 'id'
1918
- request[orderIdField] = str(id)
1919
- method = self.get_supported_mapping(market['type'], {
1920
- 'spot': 'spotV1PrivateGetCancelOrder',
1921
- 'swap': 'contractV2PrivatePostTradeCancelOrder',
1922
- })
1923
- response = getattr(self, method)(self.extend(request, params))
1924
- #
1925
- # Spot
1926
- #
1927
- # {
1928
- # "code": 1000,
1929
- # "message": "Success。"
1930
- # }
1931
- #
1932
- # Swap
1933
- #
1934
- # {
1935
- # "code": 10007,
1936
- # "desc": "orderId与clientOrderId选填1个"
1937
- # }
1938
- #
1939
- return self.parse_order(response, market)
1940
-
1941
- def cancel_all_orders(self, symbol: Optional[str] = None, params={}):
1942
- """
1943
- cancel all open orders in a market
1944
- :param str symbol: unified market symbol of the market to cancel orders in
1945
- :param dict params: extra parameters specific to the zb api endpoint
1946
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1947
- """
1948
- if symbol is None:
1949
- raise ArgumentsRequired(self.id + ' cancelAllOrders() requires a symbol argument')
1950
- self.load_markets()
1951
- market = self.market(symbol)
1952
- stop = self.safe_value(params, 'stop')
1953
- if market['spot']:
1954
- raise NotSupported(self.id + ' cancelAllOrders() is not supported on ' + market['type'] + ' markets')
1955
- request = {
1956
- 'symbol': market['id'],
1957
- # 'ids': [6904603200733782016, 6819506476072247297], # STOP
1958
- # 'side': params['side'], # STOP, for stop orders: 1 Open long(buy), 2 Open short(sell), 3 Close long(sell), 4 Close Short(Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
1959
- }
1960
- method = 'contractV2PrivatePostTradeCancelAllOrders'
1961
- if stop:
1962
- method = 'contractV2PrivatePostTradeCancelAlgos'
1963
- query = self.omit(params, 'stop')
1964
- return getattr(self, method)(self.extend(request, query))
1965
-
1966
- def fetch_order(self, id: str, symbol: Optional[str] = None, params={}):
1967
- """
1968
- fetches information on an order made by the user
1969
- :param str symbol: unified symbol of the market the order was made in
1970
- :param dict params: extra parameters specific to the zb api endpoint
1971
- :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1972
- """
1973
- if symbol is None:
1974
- raise ArgumentsRequired(self.id + ' fetchOrder() requires a symbol argument')
1975
- self.load_markets()
1976
- market = self.market(symbol)
1977
- orderType = self.safe_integer(params, 'orderType')
1978
- if orderType is not None:
1979
- raise ExchangeError(self.id + ' fetchOrder() it is not possible to fetch a single conditional order, use fetchOrders() instead')
1980
- swap = market['swap']
1981
- request = {
1982
- # 'currency': self.market_id(symbol), # only applicable to SPOT
1983
- # 'id': str(id), # only applicable to SPOT
1984
- # 'orderId': str(id), # only applicable to SWAP
1985
- # 'clientOrderId': params['clientOrderId'], # only applicable to SWAP
1986
- # 'symbol': market['id'], # STOP and SWAP
1987
- # 'side': params['side'], # STOP and SWAP, for stop orders: 1 Open long(buy), 2 Open short(sell), 3 Close long(sell), 4 Close Short(Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
1988
- # 'orderType': 1, # STOP, 1: Plan order, 2: SP/SL
1989
- # 'bizType': 1, # Plan order, 1: TP, 2: SL
1990
- # 'status': 1, # STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
1991
- # 'startTime': since, # STOP and SWAP
1992
- # 'endTime': params['endTime'], # STOP and SWAP
1993
- # 'pageNum': 1, # STOP and SWAP, default 1
1994
- # 'pageSize': limit, # STOP, default 10
1995
- }
1996
- marketIdField = 'symbol' if swap else 'currency'
1997
- request[marketIdField] = self.market_id(symbol)
1998
- orderIdField = 'orderId' if swap else 'id'
1999
- request[orderIdField] = str(id)
2000
- method = self.get_supported_mapping(market['type'], {
2001
- 'spot': 'spotV1PrivateGetGetOrder',
2002
- 'swap': 'contractV2PrivateGetTradeGetOrder',
2003
- })
2004
- response = getattr(self, method)(self.extend(request, params))
2005
- #
2006
- # Spot
2007
- #
2008
- # {
2009
- # 'total_amount': 0.01,
2010
- # 'id': '20180910244276459',
2011
- # 'price': 180.0,
2012
- # 'trade_date': 1536576744960,
2013
- # 'status': 2,
2014
- # 'trade_money': '1.96742',
2015
- # 'trade_amount': 0.01,
2016
- # 'type': 0,
2017
- # 'currency': 'eth_usdt'
2018
- # }
2019
- #
2020
- # Swap
2021
- #
2022
- # {
2023
- # "code": 10000,
2024
- # "data": {
2025
- # "action": 1,
2026
- # "amount": "0.002",
2027
- # "availableAmount": "0.002",
2028
- # "availableValue": "60",
2029
- # "avgPrice": "0",
2030
- # "canCancel": True,
2031
- # "cancelStatus": 20,
2032
- # "createTime": "1646185684379",
2033
- # "entrustType": 1,
2034
- # "id": "6904603200733782016",
2035
- # "leverage": 2,
2036
- # "margin": "30",
2037
- # "marketId": "100",
2038
- # "modifyTime": "1646185684416",
2039
- # "price": "30000",
2040
- # "priority": 0,
2041
- # "showStatus": 1,
2042
- # "side": 1,
2043
- # "sourceType": 4,
2044
- # "status": 12,
2045
- # "tradeAmount": "0",
2046
- # "tradeValue": "0",
2047
- # "type": 1,
2048
- # "userId": "6896693805014120448",
2049
- # "value": "60"
2050
- # },
2051
- # "desc":"操作成功"
2052
- # }
2053
- #
2054
- # Algo order
2055
- #
2056
- # {
2057
- # "code": 10000,
2058
- # "data": {
2059
- # "list": [
2060
- # {
2061
- # "action": 1,
2062
- # "algoPrice": "30000",
2063
- # "amount": "0.003",
2064
- # "bizType": 0,
2065
- # "canCancel": True,
2066
- # "createTime": "1649913941109",
2067
- # "errorCode": 0,
2068
- # "id": "6920240642849449984",
2069
- # "isLong": False,
2070
- # "leverage": 10,
2071
- # "marketId": "100",
2072
- # "modifyTime": "1649913941109",
2073
- # "orderType": 1,
2074
- # "priceType": 2,
2075
- # "side": 5,
2076
- # "sourceType": 4,
2077
- # "status": 1,
2078
- # "submitPrice": "41270.53",
2079
- # "symbol": "BTC_USDT",
2080
- # "tradedAmount": "0",
2081
- # "triggerCondition": "<=",
2082
- # "triggerPrice": "31000",
2083
- # "triggerTime": "0",
2084
- # "userId": "6896693805014120448"
2085
- # },
2086
- # ],
2087
- # "pageNum": 1,
2088
- # "pageSize": 10
2089
- # },
2090
- # "desc": "操作成功"
2091
- # }
2092
- #
2093
- result = response
2094
- if swap:
2095
- result = self.safe_value(response, 'data')
2096
- return self.parse_order(result, market)
2097
-
2098
- def fetch_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
2099
- """
2100
- fetches information on multiple orders made by the user
2101
- :param str symbol: unified market symbol of the market orders were made in
2102
- :param int|None since: the earliest time in ms to fetch orders for
2103
- :param int|None limit: the maximum number of orde structures to retrieve
2104
- :param dict params: extra parameters specific to the zb api endpoint
2105
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2106
- """
2107
- if symbol is None:
2108
- raise ArgumentsRequired(self.id + ' fetchOrders() requires a symbol argument')
2109
- self.load_markets()
2110
- market = self.market(symbol)
2111
- orderType = self.safe_integer(params, 'orderType')
2112
- swap = market['swap']
2113
- request = {
2114
- 'pageSize': limit, # default pageSize is 50 for spot, 30 for swap
2115
- # 'currency': market['id'], # only applicable to SPOT
2116
- # 'pageIndex': 1, # only applicable to SPOT
2117
- # 'type': params['type'], # only applicable to SWAP
2118
- # 'dateRange': params['dateRange'], # only applicable to SWAP
2119
- # 'action': params['action'], # only applicable to SWAP
2120
- # 'symbol': market['id'], # STOP and SWAP
2121
- # 'side': params['side'], # STOP and SWAP, for stop orders: 1 Open long(buy), 2 Open short(sell), 3 Close long(sell), 4 Close Short(Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
2122
- # 'orderType': 1, # STOP, 1: Plan order, 2: SP/SL
2123
- # 'bizType': 1, # Plan order, 1: TP, 2: SL
2124
- # 'status': 1, # STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
2125
- # 'startTime': since, # STOP and SWAP
2126
- # 'endTime': params['endTime'], # STOP and SWAP
2127
- # 'pageNum': 1, # STOP and SWAP, default 1
2128
- # 'pageSize': limit, # STOP, default 10
2129
- }
2130
- marketIdField = 'symbol' if market['swap'] else 'currency'
2131
- request[marketIdField] = market['id']
2132
- pageNumField = 'pageNum' if market['swap'] else 'pageIndex'
2133
- request[pageNumField] = 1
2134
- if swap:
2135
- request['startTime'] = since
2136
- method = self.get_supported_mapping(market['type'], {
2137
- 'spot': 'spotV1PrivateGetGetOrdersIgnoreTradeType',
2138
- 'swap': 'contractV2PrivateGetTradeGetAllOrders',
2139
- })
2140
- # tradeType 交易类型1/0[buy/sell]
2141
- if 'tradeType' in params:
2142
- method = 'spotV1PrivateGetGetOrdersNew'
2143
- if orderType is not None:
2144
- method = 'contractV2PrivateGetTradeGetOrderAlgos'
2145
- response = getattr(self, method)(self.extend(request, params))
2146
- # Spot
2147
- #
2148
- # [
2149
- # {
2150
- # "acctType": 0,
2151
- # "currency": "btc_usdt",
2152
- # "fees": 0,
2153
- # "id": "202202234857482656",
2154
- # "price": 30000.0,
2155
- # "status": 3,
2156
- # "total_amount": 0.0006,
2157
- # "trade_amount": 0.0000,
2158
- # "trade_date": 1645610254524,
2159
- # "trade_money": 0.000000,
2160
- # "type": 1,
2161
- # "useZbFee": False,
2162
- # "webId": 0
2163
- # }
2164
- # ]
2165
- #
2166
- # Swap
2167
- #
2168
- # {
2169
- # "code": 10000,
2170
- # "data": {
2171
- # "list": [
2172
- # {
2173
- # "action": 1,
2174
- # "amount": "0.004",
2175
- # "availableAmount": "0.004",
2176
- # "availableValue": "120",
2177
- # "avgPrice": "0",
2178
- # "canCancel": True,
2179
- # "cancelStatus": 20,
2180
- # "createTime": "1645609643885",
2181
- # "entrustType": 1,
2182
- # "id": "6902187111785635850",
2183
- # "leverage": 5,
2184
- # "margin": "24",
2185
- # "marketId": "100",
2186
- # "marketName": "BTC_USDT",
2187
- # "modifyTime": "1645609643889",
2188
- # "price": "30000",
2189
- # "showStatus": 1,
2190
- # "side": 1,
2191
- # "sourceType": 1,
2192
- # "status": 12,
2193
- # "tradeAmount": "0",
2194
- # "tradeValue": "0",
2195
- # "type": 1,
2196
- # "userId": "6896693805014120448",
2197
- # "value": "120"
2198
- # },
2199
- # ],
2200
- # "pageNum": 1,
2201
- # "pageSize": 10
2202
- # },
2203
- # "desc": "操作成功"
2204
- # }
2205
- #
2206
- # Algo order
2207
- #
2208
- # {
2209
- # "code": 10000,
2210
- # "data": {
2211
- # "list": [
2212
- # {
2213
- # "action": 1,
2214
- # "algoPrice": "30000",
2215
- # "amount": "0.003",
2216
- # "bizType": 0,
2217
- # "canCancel": True,
2218
- # "createTime": "1649913941109",
2219
- # "errorCode": 0,
2220
- # "id": "6920240642849449984",
2221
- # "isLong": False,
2222
- # "leverage": 10,
2223
- # "marketId": "100",
2224
- # "modifyTime": "1649913941109",
2225
- # "orderType": 1,
2226
- # "priceType": 2,
2227
- # "side": 5,
2228
- # "sourceType": 4,
2229
- # "status": 1,
2230
- # "submitPrice": "41270.53",
2231
- # "symbol": "BTC_USDT",
2232
- # "tradedAmount": "0",
2233
- # "triggerCondition": "<=",
2234
- # "triggerPrice": "31000",
2235
- # "triggerTime": "0",
2236
- # "userId": "6896693805014120448"
2237
- # },
2238
- # ],
2239
- # "pageNum": 1,
2240
- # "pageSize": 10
2241
- # },
2242
- # "desc": "操作成功"
2243
- # }
2244
- #
2245
- result = response
2246
- if swap:
2247
- data = self.safe_value(response, 'data', {})
2248
- result = self.safe_value(data, 'list', [])
2249
- return self.parse_orders(result, market, since, limit)
2250
-
2251
- def fetch_canceled_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit=10, params={}):
2252
- """
2253
- fetches information on multiple canceled orders made by the user
2254
- :param str symbol: unified market symbol of the market orders were made in
2255
- :param int|None since: timestamp in ms of the earliest order, default is None
2256
- :param int|None limit: max number of orders to return, default is None
2257
- :param dict params: extra parameters specific to the zb api endpoint
2258
- :returns dict: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2259
- """
2260
- if symbol is None:
2261
- raise ArgumentsRequired(self.id + ' fetchCanceledOrders() requires a symbol argument')
2262
- self.load_markets()
2263
- market = self.market(symbol)
2264
- reduceOnly = self.safe_value(params, 'reduceOnly')
2265
- stop = self.safe_value(params, 'stop')
2266
- request = {
2267
- 'pageSize': limit, # SPOT and STOP, default pageSize is 10, doesn't work with other values now
2268
- # 'currency': market['id'], # SPOT
2269
- # 'pageIndex': 1, # SPOT, default pageIndex is 1
2270
- # 'symbol': market['id'], # STOP
2271
- # 'side': params['side'], # STOP, for stop orders: 1 Open long(buy), 2 Open short(sell), 3 Close long(sell), 4 Close Short(Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
2272
- # 'orderType': 1, # STOP, 1: Plan order, 2: SP/SL
2273
- # 'bizType': 1, # Plan order, 1: TP, 2: SL
2274
- # 'status': 1, # STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
2275
- # 'startTime': since, # STOP
2276
- # 'endTime': params['endTime'], # STOP
2277
- # 'pageNum': 1, # STOP, default 1
2278
- }
2279
- marketIdField = 'currency' if market['spot'] else 'symbol'
2280
- request[marketIdField] = market['id']
2281
- pageNumField = 'pageIndex' if market['spot'] else 'pageNum'
2282
- request[pageNumField] = 1
2283
- method = 'spotV1PrivateGetGetOrdersIgnoreTradeType'
2284
- if stop:
2285
- method = 'contractV2PrivateGetTradeGetOrderAlgos'
2286
- orderType = self.safe_integer(params, 'orderType')
2287
- if orderType is None:
2288
- raise ArgumentsRequired(self.id + ' fetchCanceledOrders() requires an orderType parameter for stop orders')
2289
- side = self.safe_value(params, 'side')
2290
- bizType = self.safe_integer(params, 'bizType')
2291
- if side == 'sell' and reduceOnly:
2292
- request['side'] = 3 # close long
2293
- elif side == 'buy' and reduceOnly:
2294
- request['side'] = 4 # close short
2295
- elif side == 'buy':
2296
- request['side'] = 1 # open long
2297
- elif side == 'sell':
2298
- request['side'] = 2 # open short
2299
- elif side == 5:
2300
- request['side'] = 5 # one way position buy
2301
- elif side == 6:
2302
- request['side'] = 6 # one way position sell
2303
- elif side == 0:
2304
- request['side'] = 0 # one way position close only
2305
- if orderType == 1:
2306
- request['orderType'] = 1
2307
- elif orderType == 2 or bizType:
2308
- request['orderType'] = 2
2309
- request['bizType'] = bizType
2310
- request['status'] = 2
2311
- # tradeType 交易类型1/0[buy/sell]
2312
- if 'tradeType' in params:
2313
- method = 'spotV1PrivateGetGetOrdersNew'
2314
- response = None
2315
- try:
2316
- response = getattr(self, method)(self.extend(request, params))
2317
- except Exception as e:
2318
- if isinstance(e, OrderNotFound):
2319
- return []
2320
- raise e
2321
- query = self.omit(params, ['reduceOnly', 'stop', 'side', 'orderType', 'bizType'])
2322
- response = getattr(self, method)(self.extend(request, query))
2323
- #
2324
- # Spot
2325
- #
2326
- # [
2327
- # {
2328
- # "acctType": 0,
2329
- # "currency": "btc_usdt",
2330
- # "fees": 0,
2331
- # "id": "202202234857482656",
2332
- # "price": 30000.0,
2333
- # "status": 1,
2334
- # "total_amount": 0.0006,
2335
- # "trade_amount": 0.0000,
2336
- # "trade_date": 1645610254524,
2337
- # "trade_money": 0.000000,
2338
- # "type": 1,
2339
- # "useZbFee": False,
2340
- # "webId": 0
2341
- # }
2342
- # ]
2343
- #
2344
- # Algo order
2345
- #
2346
- # {
2347
- # "code": 10000,
2348
- # "data": {
2349
- # "list": [
2350
- # {
2351
- # "action": 1,
2352
- # "algoPrice": "30000",
2353
- # "amount": "0.003",
2354
- # "bizType": 0,
2355
- # "canCancel": True,
2356
- # "createTime": "1649913941109",
2357
- # "errorCode": 0,
2358
- # "id": "6920240642849449984",
2359
- # "isLong": False,
2360
- # "leverage": 10,
2361
- # "marketId": "100",
2362
- # "modifyTime": "1649913941109",
2363
- # "orderType": 1,
2364
- # "priceType": 2,
2365
- # "side": 5,
2366
- # "sourceType": 4,
2367
- # "status": 2,
2368
- # "submitPrice": "41270.53",
2369
- # "symbol": "BTC_USDT",
2370
- # "tradedAmount": "0",
2371
- # "triggerCondition": "<=",
2372
- # "triggerPrice": "31000",
2373
- # "triggerTime": "0",
2374
- # "userId": "6896693805014120448"
2375
- # },
2376
- # ],
2377
- # "pageNum": 1,
2378
- # "pageSize": 10
2379
- # },
2380
- # "desc": "操作成功"
2381
- # }
2382
- #
2383
- if stop:
2384
- data = self.safe_value(response, 'data', {})
2385
- response = self.safe_value(data, 'list', [])
2386
- result = []
2387
- if market['type'] == 'spot':
2388
- for i in range(0, len(response)):
2389
- entry = response[i]
2390
- status = self.safe_string(entry, 'status')
2391
- if status == '1':
2392
- result.append(entry)
2393
- response = result
2394
- return self.parse_orders(response, market, since, limit)
2395
-
2396
- def fetch_closed_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit=10, params={}):
2397
- """
2398
- fetches information on multiple closed orders made by the user
2399
- :param str symbol: unified market symbol of the market orders were made in
2400
- :param int|None since: the earliest time in ms to fetch orders for
2401
- :param int|None limit: the maximum number of orde structures to retrieve
2402
- :param dict params: extra parameters specific to the zb api endpoint
2403
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2404
- """
2405
- if symbol is None:
2406
- raise ArgumentsRequired(self.id + ' fetchClosedOrders() requires a symbol argument')
2407
- self.load_markets()
2408
- market = self.market(symbol)
2409
- swap = market['swap']
2410
- orderType = self.safe_integer(params, 'orderType')
2411
- request = {
2412
- 'pageSize': limit, # SPOT and STOP, default pageSize is 10, doesn't work with other values now
2413
- # 'currency': market['id'], # SPOT
2414
- # 'pageIndex': 1, # SPOT, default pageIndex is 1
2415
- # 'symbol': market['id'], # STOP
2416
- # 'side': params['side'], # STOP, for stop orders: 1 Open long(buy), 2 Open short(sell), 3 Close long(sell), 4 Close Short(Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
2417
- # 'orderType': 1, # STOP, 1: Plan order, 2: SP/SL
2418
- # 'bizType': 1, # Plan order, 1: TP, 2: SL
2419
- # 'status': 1, # STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
2420
- # 'startTime': since, # STOP
2421
- # 'endTime': params['endTime'], # STOP
2422
- # 'pageNum': 1, # STOP, default 1
2423
- }
2424
- marketIdField = 'currency' if market['spot'] else 'symbol'
2425
- request[marketIdField] = market['id']
2426
- pageNumField = 'pageIndex' if market['spot'] else 'pageNum'
2427
- request[pageNumField] = 1
2428
- if swap and (since is not None):
2429
- request['startTime'] = since
2430
- method = self.get_supported_mapping(market['type'], {
2431
- 'spot': 'spotV1PrivateGetGetFinishedAndPartialOrders',
2432
- 'swap': 'contractV2PrivateGetTradeGetOrderAlgos',
2433
- })
2434
- if swap and (orderType is None):
2435
- raise ExchangeError(self.id + ' fetchClosedOrders() can not fetch swap orders, use fetchOrders instead')
2436
- if swap:
2437
- # a status of 2 would mean canceled and could also be valid
2438
- request['status'] = 5 # complete
2439
- response = getattr(self, method)(self.extend(request, params))
2440
- #
2441
- # Spot
2442
- #
2443
- # [
2444
- # {
2445
- # "acctType": 0,
2446
- # "currency": "btc_usdt",
2447
- # "fees": 0.00823354,
2448
- # "id": "202204145086706337",
2449
- # "price": 41167.7,
2450
- # "status": 2,
2451
- # "total_amount": 0.0001,
2452
- # "trade_amount": 0.0001,
2453
- # "trade_date": 1649917867370,
2454
- # "trade_money": 4.116770,
2455
- # "type": 0,
2456
- # "useZbFee": False,
2457
- # "webId": 0
2458
- # },
2459
- # ]
2460
- #
2461
- # Algo order
2462
- #
2463
- # {
2464
- # "code": 10000,
2465
- # "data": {
2466
- # "list": [
2467
- # {
2468
- # "action": 1,
2469
- # "algoPrice": "30000",
2470
- # "amount": "0.003",
2471
- # "bizType": 0,
2472
- # "canCancel": True,
2473
- # "createTime": "1649913941109",
2474
- # "errorCode": 0,
2475
- # "id": "6920240642849449984",
2476
- # "isLong": False,
2477
- # "leverage": 10,
2478
- # "marketId": "100",
2479
- # "modifyTime": "1649913941109",
2480
- # "orderType": 1,
2481
- # "priceType": 2,
2482
- # "side": 5,
2483
- # "sourceType": 4,
2484
- # "status": 1,
2485
- # "submitPrice": "41270.53",
2486
- # "symbol": "BTC_USDT",
2487
- # "tradedAmount": "0",
2488
- # "triggerCondition": "<=",
2489
- # "triggerPrice": "31000",
2490
- # "triggerTime": "0",
2491
- # "userId": "6896693805014120448"
2492
- # },
2493
- # ],
2494
- # "pageNum": 1,
2495
- # "pageSize": 10
2496
- # },
2497
- # "desc": "操作成功"
2498
- # }
2499
- #
2500
- result = response
2501
- if swap:
2502
- data = self.safe_value(response, 'data', {})
2503
- result = self.safe_value(data, 'list', [])
2504
- return self.parse_orders(result, market, since, limit)
2505
-
2506
- def fetch_open_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
2507
- """
2508
- fetch all unfilled currently open orders
2509
- :param str symbol: unified market symbol
2510
- :param int|None since: the earliest time in ms to fetch open orders for
2511
- :param int|None limit: the maximum number of open orders structures to retrieve
2512
- :param dict params: extra parameters specific to the zb api endpoint
2513
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2514
- """
2515
- if symbol is None:
2516
- raise ArgumentsRequired(self.id + ' fetchOpenOrders() requires a symbol argument')
2517
- self.load_markets()
2518
- market = self.market(symbol)
2519
- orderType = self.safe_integer(params, 'orderType')
2520
- swap = market['swap']
2521
- request = {
2522
- # 'pageSize': limit, # default pageSize is 10 for spot, 30 for swap
2523
- # 'currency': market['id'], # SPOT
2524
- # 'pageIndex': 1, # SPOT
2525
- # 'symbol': market['id'], # SWAP and STOP
2526
- # 'pageNum': 1, # SWAP and STOP, default 1
2527
- # 'type': params['type'], # swap only
2528
- # 'side': params['side'], # SWAP and STOP, for stop orders: 1 Open long(buy), 2 Open short(sell), 3 Close long(sell), 4 Close Short(Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
2529
- # 'action': params['action'], # SWAP
2530
- # 'orderType': 1, # STOP, 1: Plan order, 2: SP/SL
2531
- # 'bizType': 1, # Plan order, 1: TP, 2: SL
2532
- # 'status': 1, # STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
2533
- # 'startTime': since, # SWAP and STOP
2534
- # 'endTime': params['endTime'], # STOP
2535
- }
2536
- if limit is not None:
2537
- request['pageSize'] = limit # default pageSize is 10 for spot, 30 for swap
2538
- marketIdField = 'symbol' if market['swap'] else 'currency'
2539
- request[marketIdField] = market['id']
2540
- pageNumField = 'pageNum' if market['swap'] else 'pageIndex'
2541
- request[pageNumField] = 1
2542
- if swap and (since is not None):
2543
- request['startTime'] = since
2544
- method = self.get_supported_mapping(market['type'], {
2545
- 'spot': 'spotV1PrivateGetGetUnfinishedOrdersIgnoreTradeType',
2546
- 'swap': 'contractV2PrivateGetTradeGetUndoneOrders',
2547
- })
2548
- if orderType is not None:
2549
- method = 'contractV2PrivateGetTradeGetOrderAlgos'
2550
- # value 3 would mean triggered but still open orders
2551
- request['status'] = 1 # untriggered
2552
- # tradeType 交易类型1/0[buy/sell]
2553
- if 'tradeType' in params:
2554
- method = 'spotV1PrivateGetGetOrdersNew'
2555
- response = getattr(self, method)(self.extend(request, params))
2556
- #
2557
- # Spot
2558
- #
2559
- # [
2560
- # {
2561
- # "currency": "btc_usdt",
2562
- # "id": "20150928158614292",
2563
- # "price": 1560,
2564
- # "status": 3,
2565
- # "total_amount": 0.1,
2566
- # "trade_amount": 0,
2567
- # "trade_date": 1443410396717,
2568
- # "trade_money": 0,
2569
- # "type": 0,
2570
- # "fees": "0.03",
2571
- # "useZbFee": True
2572
- # },
2573
- # ]
2574
- #
2575
- # Swap
2576
- #
2577
- # {
2578
- # "code": 10000,
2579
- # "data": {
2580
- # "list": [
2581
- # {
2582
- # "action": 1,
2583
- # "amount": "0.003",
2584
- # "availableAmount": "0.003",
2585
- # "availableValue": "90",
2586
- # "avgPrice": "0",
2587
- # "canCancel": True,
2588
- # "cancelStatus": 20,
2589
- # "createTime": "1645694610880",
2590
- # "entrustType": 1,
2591
- # "id": "6902543489192632320",
2592
- # "leverage": 5,
2593
- # "margin": "18",
2594
- # "marketId": "100",
2595
- # "modifyTime": "1645694610883",
2596
- # "price": "30000",
2597
- # "priority": 0,
2598
- # "showStatus": 1,
2599
- # "side": 1,
2600
- # "sourceType": 1,
2601
- # "status": 12,
2602
- # "tradeAmount": "0",
2603
- # "tradeValue": "0",
2604
- # "type": 1,
2605
- # "userId": "6896693805014120448",
2606
- # "value": "90"
2607
- # }
2608
- # ],
2609
- # "pageNum": 1,
2610
- # "pageSize": 30
2611
- # },
2612
- # "desc": "操作成功"
2613
- # }
2614
- #
2615
- # Algo order
2616
- #
2617
- # {
2618
- # "code": 10000,
2619
- # "data": {
2620
- # "list": [
2621
- # {
2622
- # "action": 1,
2623
- # "algoPrice": "30000",
2624
- # "amount": "0.003",
2625
- # "bizType": 0,
2626
- # "canCancel": True,
2627
- # "createTime": "1649913941109",
2628
- # "errorCode": 0,
2629
- # "id": "6920240642849449984",
2630
- # "isLong": False,
2631
- # "leverage": 10,
2632
- # "marketId": "100",
2633
- # "modifyTime": "1649913941109",
2634
- # "orderType": 1,
2635
- # "priceType": 2,
2636
- # "side": 5,
2637
- # "sourceType": 4,
2638
- # "status": 1,
2639
- # "submitPrice": "41270.53",
2640
- # "symbol": "BTC_USDT",
2641
- # "tradedAmount": "0",
2642
- # "triggerCondition": "<=",
2643
- # "triggerPrice": "31000",
2644
- # "triggerTime": "0",
2645
- # "userId": "6896693805014120448"
2646
- # },
2647
- # ],
2648
- # "pageNum": 1,
2649
- # "pageSize": 10
2650
- # },
2651
- # "desc": "操作成功"
2652
- # }
2653
- #
2654
- result = response
2655
- if swap:
2656
- data = self.safe_value(response, 'data', {})
2657
- result = self.safe_value(data, 'list', [])
2658
- return self.parse_orders(result, market, since, limit)
2659
-
2660
- def parse_order(self, order, market=None):
2661
- #
2662
- # Spot fetchOrder, fetchClosedOrders
2663
- #
2664
- # {
2665
- # acctType: 0,
2666
- # currency: 'btc_usdt',
2667
- # fees: 3.6e-7,
2668
- # id: '202102282829772463',
2669
- # price: 45177.5,
2670
- # status: 2,
2671
- # total_amount: 0.0002,
2672
- # trade_amount: 0.0002,
2673
- # trade_date: 1614515104998,
2674
- # trade_money: 8.983712,
2675
- # type: 1,
2676
- # useZbFee: False
2677
- # },
2678
- #
2679
- # Swap fetchOrder
2680
- #
2681
- # {
2682
- # "action": 1,
2683
- # "amount": "0.002",
2684
- # "availableAmount": "0.002",
2685
- # "availableValue": "60",
2686
- # "avgPrice": "0",
2687
- # "canCancel": True,
2688
- # "cancelStatus": 20,
2689
- # "createTime": "1646185684379",
2690
- # "entrustType": 1,
2691
- # "id": "6904603200733782016",
2692
- # "leverage": 2,
2693
- # "margin": "30",
2694
- # "marketId": "100",
2695
- # "modifyTime": "1646185684416",
2696
- # "price": "30000",
2697
- # "priority": 0,
2698
- # "showStatus": 1,
2699
- # "side": 1,
2700
- # "sourceType": 4,
2701
- # "status": 12,
2702
- # "tradeAmount": "0",
2703
- # "tradeValue": "0",
2704
- # "type": 1,
2705
- # "userId": "6896693805014120448",
2706
- # "value": "60"
2707
- # },
2708
- #
2709
- # Algo fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders
2710
- #
2711
- # {
2712
- # "action": 1,
2713
- # "algoPrice": "30000",
2714
- # "amount": "0.003",
2715
- # "bizType": 0,
2716
- # "canCancel": True,
2717
- # "createTime": "1649913941109",
2718
- # "errorCode": 0,
2719
- # "id": "6920240642849449984",
2720
- # "isLong": False,
2721
- # "leverage": 10,
2722
- # "marketId": "100",
2723
- # "modifyTime": "1649913941109",
2724
- # "orderType": 1,
2725
- # "priceType": 2,
2726
- # "side": 5,
2727
- # "sourceType": 4,
2728
- # "status": 1,
2729
- # "submitPrice": "41270.53",
2730
- # "symbol": "BTC_USDT",
2731
- # "tradedAmount": "0",
2732
- # "triggerCondition": "<=",
2733
- # "triggerPrice": "31000",
2734
- # "triggerTime": "0",
2735
- # "userId": "6896693805014120448"
2736
- # },
2737
- #
2738
- # Spot createOrder
2739
- #
2740
- # {
2741
- # code: '1000',
2742
- # message: '操作成功',
2743
- # id: '202202224851151555',
2744
- # type: '1',
2745
- # total_amount: 0.0002,
2746
- # price: 30000
2747
- # }
2748
- #
2749
- # Swap createOrder
2750
- #
2751
- # {
2752
- # orderId: '6901786759944937472',
2753
- # orderCode: null,
2754
- # timeInForce: 'IOC',
2755
- # total_amount: 0.0002,
2756
- # price: 30000
2757
- # }
2758
- #
2759
- # Algo createOrder
2760
- #
2761
- # {
2762
- # "code": 10000,
2763
- # "data": "6919884551305242624",
2764
- # "desc": "操作成功"
2765
- # }
2766
- #
2767
- orderId = self.safe_string_2(order, 'orderId', 'data') if market['swap'] else self.safe_string(order, 'id')
2768
- if orderId is None:
2769
- orderId = self.safe_value(order, 'id')
2770
- rawSide = self.safe_integer_2(order, 'type', 'side')
2771
- side = None
2772
- if rawSide is not None:
2773
- if market['spot']:
2774
- side = 'buy' if (rawSide == 1) else 'sell'
2775
- elif market['swap']:
2776
- if rawSide == 0:
2777
- side = None
2778
- elif (rawSide == 1) or (rawSide == 4) or (rawSide == 5):
2779
- side = 'buy'
2780
- elif (rawSide == 2) or (rawSide == 3) or (rawSide == 6):
2781
- side = 'sell'
2782
- timestamp = self.safe_integer(order, 'trade_date')
2783
- if timestamp is None:
2784
- timestamp = self.safe_integer(order, 'createTime')
2785
- marketId = self.safe_string(order, 'currency')
2786
- market = self.safe_market(marketId, market, '_')
2787
- price = self.safe_string_2(order, 'price', 'algoPrice')
2788
- filled = self.safe_string(order, 'tradeAmount') if market['swap'] else self.safe_string(order, 'trade_amount')
2789
- amount = self.safe_string(order, 'total_amount')
2790
- if amount is None:
2791
- amount = self.safe_string(order, 'amount')
2792
- cost = self.safe_string(order, 'trade_money')
2793
- status = self.parse_order_status(self.safe_string(order, 'status'), market)
2794
- timeInForce = self.safe_string(order, 'timeInForce')
2795
- postOnly = (timeInForce == 'PO')
2796
- feeCost = self.safe_number(order, 'fees')
2797
- fee = None
2798
- if feeCost is not None:
2799
- feeCurrency = None
2800
- zbFees = self.safe_value(order, 'useZbFee')
2801
- if zbFees is True:
2802
- feeCurrency = 'ZB'
2803
- else:
2804
- feeCurrency = market['quote'] if (side == 'sell') else market['base']
2805
- fee = {
2806
- 'cost': feeCost,
2807
- 'currency': feeCurrency,
2808
- }
2809
- return self.safe_order({
2810
- 'info': order,
2811
- 'id': orderId,
2812
- 'clientOrderId': self.safe_string(order, 'userId'),
2813
- 'timestamp': timestamp,
2814
- 'datetime': self.iso8601(timestamp),
2815
- 'lastTradeTimestamp': None,
2816
- 'symbol': market['symbol'],
2817
- 'type': 'limit', # market order is not available on ZB
2818
- 'timeInForce': timeInForce,
2819
- 'postOnly': postOnly,
2820
- 'side': side,
2821
- 'price': price,
2822
- 'stopPrice': self.safe_number(order, 'triggerPrice'),
2823
- 'triggerPrice': self.safe_number(order, 'triggerPrice'),
2824
- 'average': self.safe_string(order, 'avgPrice'),
2825
- 'cost': cost,
2826
- 'amount': amount,
2827
- 'filled': filled,
2828
- 'remaining': None,
2829
- 'status': status,
2830
- 'fee': fee,
2831
- 'trades': None,
2832
- }, market)
2833
-
2834
- def parse_order_status(self, status, market=None):
2835
- statuses = {}
2836
- if market['type'] == 'spot':
2837
- statuses = {
2838
- '0': 'open',
2839
- '1': 'canceled',
2840
- '2': 'closed',
2841
- '3': 'open', # partial
2842
- }
2843
- else:
2844
- statuses = {
2845
- '1': 'open',
2846
- '2': 'canceled',
2847
- '3': 'open', # stop order triggered
2848
- '4': 'rejected',
2849
- '5': 'closed',
2850
- }
2851
- return self.safe_string(statuses, status, status)
2852
-
2853
- def parse_transaction_status(self, status):
2854
- statuses = {
2855
- '0': 'pending', # submitted, pending confirmation
2856
- '1': 'failed',
2857
- '2': 'ok',
2858
- '3': 'canceled',
2859
- '5': 'ok', # confirmed
2860
- }
2861
- return self.safe_string(statuses, status, status)
2862
-
2863
- def parse_transaction(self, transaction, currency=None):
2864
- #
2865
- # withdraw
2866
- #
2867
- # {
2868
- # "code": 1000,
2869
- # "message": "success",
2870
- # "id": "withdrawalId"
2871
- # }
2872
- #
2873
- # fetchWithdrawals
2874
- #
2875
- # {
2876
- # "amount": 0.01,
2877
- # "fees": 0.001,
2878
- # "id": 2016042556231,
2879
- # "manageTime": 1461579340000,
2880
- # "status": 3,
2881
- # "submitTime": 1461579288000,
2882
- # "toAddress": "14fxEPirL9fyfw1i9EF439Pq6gQ5xijUmp",
2883
- # }
2884
- #
2885
- # fetchDeposits
2886
- #
2887
- # {
2888
- # "address": "1FKN1DZqCm8HaTujDioRL2Aezdh7Qj7xxx",
2889
- # "amount": "1.00000000",
2890
- # "confirmTimes": 1,
2891
- # "currency": "BTC",
2892
- # "description": "Successfully Confirm",
2893
- # "hash": "7ce842de187c379abafadd64a5fe66c5c61c8a21fb04edff9532234a1dae6xxx",
2894
- # "id": 558,
2895
- # "itransfer": 1,
2896
- # "status": 2,
2897
- # "submit_time": "2016-12-07 18:51:57",
2898
- # }
2899
- #
2900
- id = self.safe_string(transaction, 'id')
2901
- txid = self.safe_string(transaction, 'hash')
2902
- amount = self.safe_number(transaction, 'amount')
2903
- timestamp = self.parse8601(self.safe_string(transaction, 'submit_time'))
2904
- timestamp = self.safe_integer(transaction, 'submitTime', timestamp)
2905
- address = self.safe_string_2(transaction, 'toAddress', 'address')
2906
- tag = None
2907
- if address is not None:
2908
- parts = address.split('_')
2909
- address = self.safe_string(parts, 0)
2910
- tag = self.safe_string(parts, 1)
2911
- confirmTimes = self.safe_integer(transaction, 'confirmTimes')
2912
- updated = self.safe_integer(transaction, 'manageTime')
2913
- type = None
2914
- currencyId = self.safe_string(transaction, 'currency')
2915
- code = self.safe_currency_code(currencyId, currency)
2916
- if address is not None:
2917
- type = 'withdrawal' if (confirmTimes is None) else 'deposit'
2918
- status = self.parse_transaction_status(self.safe_string(transaction, 'status'))
2919
- fee = None
2920
- feeCost = self.safe_number(transaction, 'fees')
2921
- if feeCost is not None:
2922
- fee = {
2923
- 'cost': feeCost,
2924
- 'currency': code,
2925
- }
2926
- return {
2927
- 'info': transaction,
2928
- 'id': id,
2929
- 'txid': txid,
2930
- 'timestamp': timestamp,
2931
- 'datetime': self.iso8601(timestamp),
2932
- 'network': None,
2933
- 'addressFrom': None,
2934
- 'address': address,
2935
- 'addressTo': address,
2936
- 'tagFrom': None,
2937
- 'tag': tag,
2938
- 'tagTo': tag,
2939
- 'type': type,
2940
- 'amount': amount,
2941
- 'currency': code,
2942
- 'status': status,
2943
- 'updated': updated,
2944
- 'fee': fee,
2945
- }
2946
-
2947
- def set_leverage(self, leverage, symbol: Optional[str] = None, params={}):
2948
- """
2949
- set the level of leverage for a market
2950
- :param float leverage: the rate of leverage
2951
- :param str symbol: unified market symbol
2952
- :param dict params: extra parameters specific to the zb api endpoint
2953
- :returns dict: response from the exchange
2954
- """
2955
- self.load_markets()
2956
- if symbol is None:
2957
- raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
2958
- if (leverage < 1) or (leverage > 125):
2959
- raise BadRequest(self.id + ' setLeverage() leverage should be between 1 and 125')
2960
- market = self.market(symbol)
2961
- accountType = None
2962
- if not market['swap']:
2963
- raise BadSymbol(self.id + ' setLeverage() supports swap contracts only')
2964
- else:
2965
- accountType = 1
2966
- request = {
2967
- 'symbol': market['id'],
2968
- 'leverage': leverage,
2969
- 'futuresAccountType': accountType, # 1: USDT perpetual swaps
2970
- }
2971
- return self.contractV2PrivatePostSettingSetLeverage(self.extend(request, params))
2972
-
2973
- def fetch_funding_rate_history(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
2974
- """
2975
- fetches historical funding rate prices
2976
- :param str|None symbol: unified symbol of the market to fetch the funding rate history for
2977
- :param int|None since: timestamp in ms of the earliest funding rate to fetch
2978
- :param int|None limit: the maximum amount of `funding rate structures <https://docs.ccxt.com/en/latest/manual.html?#funding-rate-history-structure>` to fetch
2979
- :param dict params: extra parameters specific to the zb api endpoint
2980
- :param int|None params['until']: timestamp in ms of the latest funding rate to fetch
2981
- :returns [dict]: a list of `funding rate structures <https://docs.ccxt.com/en/latest/manual.html?#funding-rate-history-structure>`
2982
- """
2983
- self.load_markets()
2984
- request = {
2985
- # 'symbol': market['id'],
2986
- # 'startTime': since,
2987
- # 'endTime': endTime, # current time by default
2988
- # 'limit': limit, # default 100, max 1000
2989
- }
2990
- if symbol is not None:
2991
- market = self.market(symbol)
2992
- symbol = market['symbol']
2993
- request['symbol'] = market['id']
2994
- if since is not None:
2995
- request['startTime'] = since
2996
- until = self.safe_integer_2(params, 'until', 'till')
2997
- params = self.omit(params, ['endTime', 'till', 'until'])
2998
- if until is not None:
2999
- request['endTime'] = until
3000
- if limit is not None:
3001
- request['limit'] = limit
3002
- response = self.contractV2PublicGetFundingRate(self.extend(request, params))
3003
- #
3004
- # {
3005
- # "code": 10000,
3006
- # "data": [
3007
- # {
3008
- # "symbol": "BTC_USDT",
3009
- # "fundingRate": "0.0001",
3010
- # "fundingTime": "1645171200000"
3011
- # },
3012
- # ],
3013
- # "desc": "操作成功"
3014
- # }
3015
- #
3016
- data = self.safe_value(response, 'data', [])
3017
- rates = []
3018
- for i in range(0, len(data)):
3019
- entry = data[i]
3020
- marketId = self.safe_string(entry, 'symbol')
3021
- symbolInner = self.safe_symbol(marketId)
3022
- timestamp = self.safe_integer(entry, 'fundingTime')
3023
- rates.append({
3024
- 'info': entry,
3025
- 'symbol': symbolInner,
3026
- 'fundingRate': self.safe_number(entry, 'fundingRate'),
3027
- 'timestamp': timestamp,
3028
- 'datetime': self.iso8601(timestamp),
3029
- })
3030
- sorted = self.sort_by(rates, 'timestamp')
3031
- return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
3032
-
3033
- def fetch_funding_rate(self, symbol: str, params={}):
3034
- """
3035
- fetch the current funding rate
3036
- :param str symbol: unified market symbol
3037
- :param dict params: extra parameters specific to the zb api endpoint
3038
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
3039
- """
3040
- self.load_markets()
3041
- market = self.market(symbol)
3042
- if not market['swap']:
3043
- raise BadSymbol(self.id + ' fetchFundingRate() does not supports contracts only')
3044
- request = {
3045
- 'symbol': market['id'],
3046
- }
3047
- response = self.contractV1PublicGetFundingRate(self.extend(request, params))
3048
- #
3049
- # {
3050
- # "code": 10000,
3051
- # "desc": "操作成功",
3052
- # "data": {
3053
- # "fundingRate": "0.0001",
3054
- # "nextCalculateTime": "2022-02-19 00:00:00"
3055
- # }
3056
- # }
3057
- #
3058
- data = self.safe_value(response, 'data')
3059
- return self.parse_funding_rate(data, market)
3060
-
3061
- def parse_funding_rate(self, contract, market=None):
3062
- #
3063
- # fetchFundingRate
3064
- #
3065
- # {
3066
- # "fundingRate": "0.0001",
3067
- # "nextCalculateTime": "2022-02-19 00:00:00"
3068
- # }
3069
- #
3070
- # fetchFundingRates
3071
- #
3072
- # {
3073
- # "symbol": "BTC_USDT",
3074
- # "markPrice": "43254.42",
3075
- # "indexPrice": "43278.61",
3076
- # "lastFundingRate": "0.0001",
3077
- # "nextFundingTime": "1646121600000"
3078
- # }
3079
- #
3080
- marketId = self.safe_string(contract, 'symbol')
3081
- symbol = self.safe_symbol(marketId, market)
3082
- fundingRate = self.safe_number_2(contract, 'fundingRate', 'lastFundingRate')
3083
- nextFundingTimestamp = self.parse8601(self.safe_string(contract, 'nextCalculateTime'))
3084
- fundingTimestamp = self.safe_integer(contract, 'nextFundingTime')
3085
- return {
3086
- 'info': contract,
3087
- 'symbol': symbol,
3088
- 'markPrice': self.safe_string(contract, 'markPrice'),
3089
- 'indexPrice': self.safe_string(contract, 'indexPrice'),
3090
- 'interestRate': None,
3091
- 'estimatedSettlePrice': None,
3092
- 'timestamp': None,
3093
- 'datetime': None,
3094
- 'fundingRate': fundingRate,
3095
- 'fundingTimestamp': fundingTimestamp,
3096
- 'fundingDatetime': self.iso8601(fundingTimestamp),
3097
- 'nextFundingRate': None,
3098
- 'nextFundingTimestamp': nextFundingTimestamp,
3099
- 'nextFundingDatetime': self.iso8601(nextFundingTimestamp),
3100
- 'previousFundingRate': None,
3101
- 'previousFundingTimestamp': None,
3102
- 'previousFundingDatetime': None,
3103
- }
3104
-
3105
- def fetch_funding_rates(self, symbols: Optional[List[str]] = None, params={}):
3106
- """
3107
- fetch the funding rate for multiple markets
3108
- :param [str]|None symbols: list of unified market symbols
3109
- :param dict params: extra parameters specific to the zb api endpoint
3110
- :returns dict: a dictionary of `funding rates structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexe by market symbols
3111
- """
3112
- self.load_markets()
3113
- symbols = self.market_symbols(symbols)
3114
- response = self.contractV2PublicGetPremiumIndex(params)
3115
- #
3116
- # {
3117
- # "code": 10000,
3118
- # "data": [
3119
- # {
3120
- # "symbol": "BTC_USDT",
3121
- # "markPrice": "43254.42",
3122
- # "indexPrice": "43278.61",
3123
- # "lastFundingRate": "0.0001",
3124
- # "nextFundingTime": "1646121600000"
3125
- # },
3126
- # ],
3127
- # "desc":"操作成功"
3128
- # }
3129
- #
3130
- data = self.safe_value(response, 'data', [])
3131
- result = self.parse_funding_rates(data)
3132
- return self.filter_by_array(result, 'symbol', symbols)
3133
-
3134
- def withdraw(self, code: str, amount, address, tag=None, params={}):
3135
- """
3136
- make a withdrawal
3137
- :param str code: unified currency code
3138
- :param float amount: the amount to withdraw
3139
- :param str address: the address to withdraw to
3140
- :param str|None tag:
3141
- :param dict params: extra parameters specific to the zb api endpoint
3142
- :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
3143
- """
3144
- tag, params = self.handle_withdraw_tag_and_params(tag, params)
3145
- password = self.safe_string(params, 'safePwd', self.password)
3146
- if password is None:
3147
- raise ArgumentsRequired(self.id + ' withdraw() requires exchange.password or a safePwd parameter')
3148
- fees = self.safe_number(params, 'fees')
3149
- if fees is None:
3150
- raise ArgumentsRequired(self.id + ' withdraw() requires a fees parameter')
3151
- self.check_address(address)
3152
- self.load_markets()
3153
- currency = self.currency(code)
3154
- if tag is not None:
3155
- address += '_' + tag
3156
- request = {
3157
- 'amount': self.currency_to_precision(code, amount),
3158
- 'currency': currency['id'],
3159
- 'fees': self.currency_to_precision(code, fees),
3160
- # 'itransfer': 0, # agree for an internal transfer, 0 disagree, 1 agree, the default is to disagree
3161
- 'method': 'withdraw',
3162
- 'receiveAddr': address,
3163
- 'safePwd': password,
3164
- }
3165
- response = self.spotV1PrivateGetWithdraw(self.extend(request, params))
3166
- #
3167
- # {
3168
- # "code": 1000,
3169
- # "message": "success",
3170
- # "id": "withdrawalId"
3171
- # }
3172
- #
3173
- transaction = self.parse_transaction(response, currency)
3174
- return self.extend(transaction, {
3175
- 'type': 'withdrawal',
3176
- 'address': address,
3177
- 'addressTo': address,
3178
- 'amount': amount,
3179
- })
3180
-
3181
- def fetch_withdrawals(self, code: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
3182
- """
3183
- fetch all withdrawals made from an account
3184
- :param str|None code: unified currency code
3185
- :param int|None since: the earliest time in ms to fetch withdrawals for
3186
- :param int|None limit: the maximum number of withdrawals structures to retrieve
3187
- :param dict params: extra parameters specific to the zb api endpoint
3188
- :returns [dict]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
3189
- """
3190
- self.load_markets()
3191
- request = {
3192
- # 'currency': currency['id'],
3193
- # 'pageIndex': 1,
3194
- # 'pageSize': limit,
3195
- }
3196
- currency = None
3197
- if code is not None:
3198
- currency = self.currency(code)
3199
- request['currency'] = currency['id']
3200
- if limit is not None:
3201
- request['pageSize'] = limit
3202
- response = self.spotV1PrivateGetGetWithdrawRecord(self.extend(request, params))
3203
- #
3204
- # {
3205
- # "code": 1000,
3206
- # "message": {
3207
- # "des": "success",
3208
- # "isSuc": True,
3209
- # "datas": {
3210
- # "list": [
3211
- # {
3212
- # "amount": 0.01,
3213
- # "fees": 0.001,
3214
- # "id": 2016042556231,
3215
- # "manageTime": 1461579340000,
3216
- # "status": 3,
3217
- # "submitTime": 1461579288000,
3218
- # "toAddress": "14fxEPirL9fyfw1i9EF439Pq6gQ5xijUmp",
3219
- # },
3220
- # ],
3221
- # "pageIndex": 1,
3222
- # "pageSize": 10,
3223
- # "totalCount": 4,
3224
- # "totalPage": 1
3225
- # }
3226
- # }
3227
- # }
3228
- #
3229
- message = self.safe_value(response, 'message', {})
3230
- datas = self.safe_value(message, 'datas', {})
3231
- withdrawals = self.safe_value(datas, 'list', [])
3232
- return self.parse_transactions(withdrawals, currency, since, limit)
3233
-
3234
- def fetch_deposits(self, code: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
3235
- """
3236
- fetch all deposits made to an account
3237
- :param str|None code: unified currency code
3238
- :param int|None since: the earliest time in ms to fetch deposits for
3239
- :param int|None limit: the maximum number of deposits structures to retrieve
3240
- :param dict params: extra parameters specific to the zb api endpoint
3241
- :returns [dict]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
3242
- """
3243
- self.load_markets()
3244
- request = {
3245
- # 'currency': currency['id'],
3246
- # 'pageIndex': 1,
3247
- # 'pageSize': limit,
3248
- }
3249
- currency = None
3250
- if code is not None:
3251
- currency = self.currency(code)
3252
- request['currency'] = currency['id']
3253
- if limit is not None:
3254
- request['pageSize'] = limit
3255
- response = self.spotV1PrivateGetGetChargeRecord(self.extend(request, params))
3256
- #
3257
- # {
3258
- # "code": 1000,
3259
- # "message": {
3260
- # "des": "success",
3261
- # "isSuc": True,
3262
- # "datas": {
3263
- # "list": [
3264
- # {
3265
- # "address": "1FKN1DZqCm8HaTujDioRL2Aezdh7Qj7xxx",
3266
- # "amount": "1.00000000",
3267
- # "confirmTimes": 1,
3268
- # "currency": "BTC",
3269
- # "description": "Successfully Confirm",
3270
- # "hash": "7ce842de187c379abafadd64a5fe66c5c61c8a21fb04edff9532234a1dae6xxx",
3271
- # "id": 558,
3272
- # "itransfer": 1,
3273
- # "status": 2,
3274
- # "submit_time": "2016-12-07 18:51:57",
3275
- # },
3276
- # ],
3277
- # "pageIndex": 1,
3278
- # "pageSize": 10,
3279
- # "total": 8
3280
- # }
3281
- # }
3282
- # }
3283
- #
3284
- message = self.safe_value(response, 'message', {})
3285
- datas = self.safe_value(message, 'datas', {})
3286
- deposits = self.safe_value(datas, 'list', [])
3287
- return self.parse_transactions(deposits, currency, since, limit)
3288
-
3289
- def fetch_position(self, symbol: str, params={}):
3290
- """
3291
- fetch data on a single open contract trade position
3292
- :param str symbol: unified market symbol of the market the position is held in, default is None
3293
- :param dict params: extra parameters specific to the zb api endpoint
3294
- :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3295
- """
3296
- self.load_markets()
3297
- market = None
3298
- if symbol is not None:
3299
- market = self.market(symbol)
3300
- request = {
3301
- 'futuresAccountType': 1, # 1: USDT-M Perpetual Futures
3302
- # 'symbol': market['id'],
3303
- # 'marketId': market['id'],
3304
- # 'side': params['side'],
3305
- }
3306
- response = self.contractV2PrivateGetPositionsGetPositions(self.extend(request, params))
3307
- #
3308
- # {
3309
- # "code": 10000,
3310
- # "data": [
3311
- # {
3312
- # "amount": "0.002",
3313
- # "appendAmount": "0",
3314
- # "autoLightenRatio": "0",
3315
- # "avgPrice": "38570",
3316
- # "bankruptcyPrice": "46288.41",
3317
- # "contractType": 1,
3318
- # "createTime": "1645784751867",
3319
- # "freezeAmount": "0",
3320
- # "freezeList": [
3321
- # {
3322
- # "amount": "15.436832",
3323
- # "currencyId": "6",
3324
- # "currencyName": "usdt",
3325
- # "modifyTime": "1645784751867"
3326
- # }
3327
- # ],
3328
- # "id": "6902921567894972486",
3329
- # "lastAppendAmount": "0",
3330
- # "leverage": 5,
3331
- # "liquidateLevel": 1,
3332
- # "liquidatePrice": "46104",
3333
- # "maintainMargin": "0.30912384",
3334
- # "margin": "15.436832",
3335
- # "marginAppendCount": 0,
3336
- # "marginBalance": "15.295872",
3337
- # "marginMode": 1,
3338
- # "marginRate": "0.020209",
3339
- # "marketId": "100",
3340
- # "marketName": "BTC_USDT",
3341
- # "modifyTime": "1645784751867",
3342
- # "nominalValue": "77.14736",
3343
- # "originAppendAmount": "0",
3344
- # "originId": "6902921567894972591",
3345
- # "refreshType": "Timer",
3346
- # "returnRate": "-0.0091",
3347
- # "side": 0,
3348
- # "status": 1,
3349
- # "unrealizedPnl": "-0.14096",
3350
- # "userId": "6896693805014120448"
3351
- # }
3352
- # ],
3353
- # "desc": "操作成功"
3354
- # }
3355
- #
3356
- data = self.safe_value(response, 'data', [])
3357
- firstPosition = self.safe_value(data, 0)
3358
- return self.parse_position(firstPosition, market)
3359
-
3360
- def fetch_positions(self, symbols: Optional[List[str]] = None, params={}):
3361
- """
3362
- fetch all open positions
3363
- :param [str]|None symbols: list of unified market symbols
3364
- :param dict params: extra parameters specific to the zb api endpoint
3365
- :returns [dict]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3366
- """
3367
- self.load_markets()
3368
- request = {
3369
- 'futuresAccountType': 1, # 1: USDT-M Perpetual Futures
3370
- # 'symbol': market['id'],
3371
- # 'marketId': market['id'],
3372
- # 'side': params['side'],
3373
- }
3374
- response = self.contractV2PrivateGetPositionsGetPositions(self.extend(request, params))
3375
- #
3376
- # {
3377
- # "code": 10000,
3378
- # "data": [
3379
- # {
3380
- # "amount": "0.002",
3381
- # "appendAmount": "0",
3382
- # "autoLightenRatio": "0",
3383
- # "avgPrice": "38570",
3384
- # "bankruptcyPrice": "46288.41",
3385
- # "contractType": 1,
3386
- # "createTime": "1645784751867",
3387
- # "freezeAmount": "0",
3388
- # "freezeList": [
3389
- # {
3390
- # "amount": "15.436832",
3391
- # "currencyId": "6",
3392
- # "currencyName": "usdt",
3393
- # "modifyTime": "1645784751867"
3394
- # }
3395
- # ],
3396
- # "id": "6902921567894972486",
3397
- # "lastAppendAmount": "0",
3398
- # "leverage": 5,
3399
- # "liquidateLevel": 1,
3400
- # "liquidatePrice": "46104",
3401
- # "maintainMargin": "0.30912384",
3402
- # "margin": "15.436832",
3403
- # "marginAppendCount": 0,
3404
- # "marginBalance": "15.295872",
3405
- # "marginMode": 1,
3406
- # "marginRate": "0.020209",
3407
- # "marketId": "100",
3408
- # "marketName": "BTC_USDT",
3409
- # "modifyTime": "1645784751867",
3410
- # "nominalValue": "77.14736",
3411
- # "originAppendAmount": "0",
3412
- # "originId": "6902921567894972591",
3413
- # "refreshType": "Timer",
3414
- # "returnRate": "-0.0091",
3415
- # "side": 0,
3416
- # "status": 1,
3417
- # "unrealizedPnl": "-0.14096",
3418
- # "userId": "6896693805014120448"
3419
- # },
3420
- # ],
3421
- # "desc": "操作成功"
3422
- # }
3423
- #
3424
- data = self.safe_value(response, 'data', [])
3425
- return self.parse_positions(data, symbols)
3426
-
3427
- def parse_position(self, position, market=None):
3428
- #
3429
- # {
3430
- # "amount": "0.002",
3431
- # "appendAmount": "0",
3432
- # "autoLightenRatio": "0",
3433
- # "avgPrice": "38570",
3434
- # "bankruptcyPrice": "46288.41",
3435
- # "contractType": 1,
3436
- # "createTime": "1645784751867",
3437
- # "freezeAmount": "0",
3438
- # "freezeList": [
3439
- # {
3440
- # "amount": "15.436832",
3441
- # "currencyId": "6",
3442
- # "currencyName": "usdt",
3443
- # "modifyTime": "1645784751867"
3444
- # }
3445
- # ],
3446
- # "id": "6902921567894972486",
3447
- # "lastAppendAmount": "0",
3448
- # "leverage": 5,
3449
- # "liquidateLevel": 1,
3450
- # "liquidatePrice": "46104",
3451
- # "maintainMargin": "0.30912384",
3452
- # "margin": "15.436832",
3453
- # "marginAppendCount": 0,
3454
- # "marginBalance": "15.295872",
3455
- # "marginMode": 1,
3456
- # "marginRate": "0.020209",
3457
- # "marketId": "100",
3458
- # "marketName": "BTC_USDT",
3459
- # "modifyTime": "1645784751867",
3460
- # "nominalValue": "77.14736",
3461
- # "originAppendAmount": "0",
3462
- # "originId": "6902921567894972591",
3463
- # "refreshType": "Timer",
3464
- # "returnRate": "-0.0091",
3465
- # "side": 0,
3466
- # "status": 1,
3467
- # "unrealizedPnl": "-0.14096",
3468
- # "userId": "6896693805014120448"
3469
- # }
3470
- #
3471
- marketId = self.safe_string(position, 'marketName')
3472
- market = self.safe_market(marketId, market)
3473
- symbol = market['symbol']
3474
- contracts = self.safe_string(position, 'amount')
3475
- entryPrice = self.safe_number(position, 'avgPrice')
3476
- initialMargin = self.safe_string(position, 'margin')
3477
- rawSide = self.safe_string(position, 'side')
3478
- side = 'long' if (rawSide == '1') else 'short'
3479
- openType = self.safe_string(position, 'marginMode')
3480
- marginMode = 'isolated' if (openType == '1') else 'cross'
3481
- leverage = self.safe_string(position, 'leverage')
3482
- liquidationPrice = self.safe_number(position, 'liquidatePrice')
3483
- unrealizedProfit = self.safe_number(position, 'unrealizedPnl')
3484
- maintenanceMargin = self.safe_number(position, 'maintainMargin')
3485
- marginRatio = self.safe_number(position, 'marginRate')
3486
- notional = self.safe_number(position, 'nominalValue')
3487
- percentage = Precise.string_mul(self.safe_string(position, 'returnRate'), '100')
3488
- timestamp = self.safe_number(position, 'createTime')
3489
- return self.safe_position({
3490
- 'info': position,
3491
- 'id': None,
3492
- 'symbol': symbol,
3493
- 'contracts': self.parse_number(contracts),
3494
- 'contractSize': None,
3495
- 'entryPrice': entryPrice,
3496
- 'collateral': None,
3497
- 'side': side,
3498
- 'unrealizedProfit': unrealizedProfit,
3499
- 'leverage': self.parse_number(leverage),
3500
- 'percentage': percentage,
3501
- 'marginMode': marginMode,
3502
- 'notional': notional,
3503
- 'markPrice': None,
3504
- 'lastPrice': None,
3505
- 'liquidationPrice': liquidationPrice,
3506
- 'initialMargin': self.parse_number(initialMargin),
3507
- 'initialMarginPercentage': None,
3508
- 'maintenanceMargin': maintenanceMargin,
3509
- 'maintenanceMarginPercentage': None,
3510
- 'marginRatio': marginRatio,
3511
- 'timestamp': timestamp,
3512
- 'datetime': self.iso8601(timestamp),
3513
- 'lastUpdateTimestamp': None,
3514
- })
3515
-
3516
- def parse_ledger_entry_type(self, type):
3517
- types = {
3518
- '1': 'realized pnl',
3519
- '2': 'commission',
3520
- '3': 'funding fee subtract',
3521
- '4': 'funding fee addition',
3522
- '5': 'insurance clear',
3523
- '6': 'transfer in',
3524
- '7': 'transfer out',
3525
- '8': 'margin addition',
3526
- '9': 'margin subtraction',
3527
- '10': 'commission addition',
3528
- '11': 'bill type freeze',
3529
- '12': 'bill type unfreeze',
3530
- '13': 'system take over margin',
3531
- '14': 'transfer',
3532
- '15': 'realized pnl collection',
3533
- '16': 'funding fee collection',
3534
- '17': 'recommender return commission',
3535
- '18': 'by level subtract positions',
3536
- '19': 'system add',
3537
- '20': 'system subtract',
3538
- '23': 'trading competition take over fund',
3539
- '24': 'trading contest tickets',
3540
- '25': 'return of trading contest tickets',
3541
- '26': 'experience expired recall',
3542
- '50': 'test register gift',
3543
- '51': 'register gift',
3544
- '52': 'deposit gift',
3545
- '53': 'trading volume gift',
3546
- '54': 'awards gift',
3547
- '55': 'trading volume gift',
3548
- '56': 'awards gift expire',
3549
- '201': 'open positions',
3550
- '202': 'close positions',
3551
- '203': 'take over positions',
3552
- '204': 'trading competition take over positions',
3553
- '205': 'one way open long',
3554
- '206': 'one way open short',
3555
- '207': 'one way close long',
3556
- '208': 'one way close short',
3557
- '301': 'coupon deduction service charge',
3558
- '302': 'experience deduction',
3559
- '303': 'experience expired',
3560
- }
3561
- return self.safe_string(types, type, type)
3562
-
3563
- def parse_ledger_entry(self, item, currency=None):
3564
- #
3565
- # [
3566
- # {
3567
- # "type": 3,
3568
- # "changeAmount": "0.00434664",
3569
- # "isIn": 0,
3570
- # "beforeAmount": "30.53353135",
3571
- # "beforeFreezeAmount": "21.547",
3572
- # "createTime": "1646121604997",
3573
- # "available": "30.52918471",
3574
- # "unit": "usdt",
3575
- # "symbol": "BTC_USDT"
3576
- # },
3577
- # ],
3578
- #
3579
- timestamp = self.safe_integer(item, 'createTime')
3580
- direction = None
3581
- changeDirection = self.safe_number(item, 'isIn')
3582
- if changeDirection == 1:
3583
- direction = 'increase'
3584
- else:
3585
- direction = 'reduce'
3586
- fee = None
3587
- feeCost = self.safe_number(item, 'fee')
3588
- if feeCost is not None:
3589
- fee = {
3590
- 'cost': feeCost,
3591
- 'currency': self.safe_currency_code(self.safe_string(item, 'unit')),
3592
- }
3593
- return {
3594
- 'id': self.safe_string(item, 'id'),
3595
- 'info': item,
3596
- 'timestamp': timestamp,
3597
- 'datetime': self.iso8601(timestamp),
3598
- 'direction': direction,
3599
- 'account': self.safe_string(item, 'userId'),
3600
- 'referenceId': None,
3601
- 'referenceAccount': None,
3602
- 'type': self.parse_ledger_entry_type(self.safe_integer(item, 'type')),
3603
- 'currency': self.safe_currency_code(self.safe_string(item, 'unit')),
3604
- 'amount': self.safe_number(item, 'changeAmount'),
3605
- 'before': self.safe_number(item, 'beforeAmount'),
3606
- 'after': self.safe_number(item, 'available'),
3607
- 'status': None,
3608
- 'fee': fee,
3609
- }
3610
-
3611
- def fetch_ledger(self, code: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
3612
- """
3613
- fetch the history of changes, actions done by the user or operations that altered balance of the user
3614
- :param str code: unified currency code, default is None
3615
- :param int|None since: timestamp in ms of the earliest ledger entry, default is None
3616
- :param int|None limit: max number of ledger entrys to return, default is None
3617
- :param dict params: extra parameters specific to the zb api endpoint
3618
- :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
3619
- """
3620
- if code is None:
3621
- raise ArgumentsRequired(self.id + ' fetchLedger() requires a code argument')
3622
- self.load_markets()
3623
- currency = self.currency(code)
3624
- request = {
3625
- 'futuresAccountType': 1,
3626
- # 'currencyId': '11',
3627
- # 'type': 1,
3628
- # 'endTime': self.milliseconds(),
3629
- # 'pageNum': 1,
3630
- }
3631
- if code is not None:
3632
- request['currencyName'] = currency['id']
3633
- if since is not None:
3634
- request['startTime'] = since
3635
- if limit is not None:
3636
- request['pageSize'] = limit
3637
- response = self.contractV2PrivateGetFundGetBill(self.extend(request, params))
3638
- #
3639
- # {
3640
- # "code": 10000,
3641
- # "data": {
3642
- # "list": [
3643
- # {
3644
- # "type": 3,
3645
- # "changeAmount": "0.00434664",
3646
- # "isIn": 0,
3647
- # "beforeAmount": "30.53353135",
3648
- # "beforeFreezeAmount": "21.547",
3649
- # "createTime": "1646121604997",
3650
- # "available": "30.52918471",
3651
- # "unit": "usdt",
3652
- # "symbol": "BTC_USDT"
3653
- # },
3654
- # ],
3655
- # "pageNum": 1,
3656
- # "pageSize": 10
3657
- # },
3658
- # "desc": "操作成功"
3659
- # }
3660
- #
3661
- data = self.safe_value(response, 'data', {})
3662
- list = self.safe_value(data, 'list', [])
3663
- return self.parse_ledger(list, currency, since, limit)
3664
-
3665
- def transfer(self, code: str, amount, fromAccount, toAccount, params={}):
3666
- """
3667
- transfer currency internally between wallets on the same account
3668
- :param str code: unified currency code
3669
- :param float amount: amount to transfer
3670
- :param str fromAccount: account to transfer from
3671
- :param str toAccount: account to transfer to
3672
- :param dict params: extra parameters specific to the zb api endpoint
3673
- :param str params['marginMode']: 'cross' or 'isolated'
3674
- :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
3675
- """
3676
- self.load_markets()
3677
- marketType, marketTypeQuery = self.handle_market_type_and_params('transfer', None, params)
3678
- marginMode, query = self.handle_margin_mode_and_params('transfer', marketTypeQuery)
3679
- currency = self.currency(code)
3680
- swap = (marketType == 'swap')
3681
- amountToPrecision = self.currency_to_precision(code, amount)
3682
- request = {
3683
- 'amount': amountToPrecision, # Swap, Cross Margin, Isolated Margin
3684
- # 'coin': currency['id'], # Margin
3685
- # 'currencyName': currency['id'], # Swap
3686
- # 'clientId': self.safe_string(params, 'clientId'), # Swap "2sdfsdfsdf232342"
3687
- # 'side': side, # Swap, 1:Deposit(zb account -> futures account),0:Withdrawal(futures account -> zb account)
3688
- # 'marketName': self.safe_string(params, 'marketName'), # Isolated Margin
3689
- }
3690
- method = None
3691
- side = None
3692
- if swap:
3693
- method = 'contractV2PrivatePostFundTransferFund'
3694
- if fromAccount == 'spot' or toAccount == 'future':
3695
- side = 1
3696
- else:
3697
- side = 0
3698
- request['currencyName'] = currency['id']
3699
- request['clientId'] = self.safe_string(params, 'clientId')
3700
- request['side'] = side
3701
- else:
3702
- if (marginMode == 'isolated') or (toAccount == 'isolated') or (fromAccount == 'isolated'):
3703
- if fromAccount == 'spot' or toAccount == 'isolated':
3704
- method = 'spotV1PrivateGetTransferInLever'
3705
- else:
3706
- method = 'spotV1PrivateGetTransferOutLever'
3707
- symbol = self.safe_string_2(params, 'marketName', 'symbol')
3708
- if symbol is None:
3709
- raise ArgumentsRequired(self.id + ' transfer() requires a symbol argument for isolated margin')
3710
- marketInner = self.market(symbol)
3711
- request['marketName'] = self.safe_symbol(marketInner['id'], marketInner, '_')
3712
- elif (marginMode == 'cross') or (toAccount == 'cross') or (fromAccount == 'cross'):
3713
- if fromAccount == 'spot' or toAccount == 'cross':
3714
- method = 'spotV1PrivateGetTransferInCross'
3715
- else:
3716
- method = 'spotV1PrivateGetTransferOutCross'
3717
- request['coin'] = currency['id']
3718
- response = getattr(self, method)(self.extend(request, query))
3719
- #
3720
- # Swap
3721
- #
3722
- # {
3723
- # "code": 10000,
3724
- # "data": "2sdfsdfsdf232342",
3725
- # "desc": "Success"
3726
- # }
3727
- #
3728
- # Margin
3729
- #
3730
- # {
3731
- # "code": 1000,
3732
- # "message": "Success"
3733
- # }
3734
- #
3735
- return self.extend(self.parse_transfer(response, currency), {
3736
- 'amount': self.parse_number(amountToPrecision),
3737
- 'fromAccount': fromAccount,
3738
- 'toAccount': toAccount,
3739
- })
3740
-
3741
- def parse_transfer(self, transfer, currency=None):
3742
- # response samples in 'transfer'
3743
- timestamp = self.milliseconds()
3744
- return {
3745
- 'id': self.safe_string(transfer, 'data'),
3746
- 'timestamp': timestamp,
3747
- 'datetime': self.iso8601(timestamp),
3748
- 'currency': self.safe_currency_code(None, 'currency'),
3749
- 'amount': None,
3750
- 'fromAccount': None,
3751
- 'toAccount': None,
3752
- 'status': None,
3753
- }
3754
-
3755
- def modify_margin_helper(self, symbol: str, amount, type, params={}):
3756
- if params['positionsId'] is None:
3757
- raise ArgumentsRequired(self.id + ' modifyMarginHelper() requires a positionsId argument in the params')
3758
- self.load_markets()
3759
- market = self.market(symbol)
3760
- amount = self.amount_to_precision(symbol, amount)
3761
- position = self.safe_string(params, 'positionsId')
3762
- request = {
3763
- 'positionsId': position,
3764
- 'amount': amount,
3765
- 'type': type, # 1 increase, 0 reduce
3766
- 'futuresAccountType': 1, # 1: USDT Perpetual Futures
3767
- }
3768
- response = self.contractV2PrivatePostPositionsUpdateMargin(self.extend(request, params))
3769
- #
3770
- # {
3771
- # "code": 10000,
3772
- # "data": {
3773
- # "amount": "0.002",
3774
- # "appendAmount": "0",
3775
- # "avgPrice": "43927.23",
3776
- # "bankruptcyPrice": "41730.86",
3777
- # "createTime": "1646208695609",
3778
- # "freezeAmount": "0",
3779
- # "id": "6900781818669377576",
3780
- # "keyMark": "6896693805014120448-100-1-",
3781
- # "lastAppendAmount": "0",
3782
- # "lastTime": "1646209235505",
3783
- # "leverage": 20,
3784
- # "liquidateLevel": 1,
3785
- # "liquidatePrice": "41898.46",
3786
- # "maintainMargin": "0",
3787
- # "margin": "4.392723",
3788
- # "marginAppendCount": 0,
3789
- # "marginBalance": "0",
3790
- # "marginMode": 1,
3791
- # "marginRate": "0",
3792
- # "marketId": "100",
3793
- # "marketName": "BTC_USDT",
3794
- # "modifyTime": "1646209235505",
3795
- # "nominalValue": "87.88828",
3796
- # "originAppendAmount": "0",
3797
- # "originId": "6904699716827818029",
3798
- # "positionsMode": 2,
3799
- # "sellerCurrencyId": "1",
3800
- # "side": 1,
3801
- # "status": 1,
3802
- # "unrealizedPnl": "0.03382",
3803
- # "usable": True,
3804
- # "userId": "6896693805014120448"
3805
- # },
3806
- # "desc":"操作成功"
3807
- # }
3808
- #
3809
- return self.extend(self.parse_margin_modification(response, market), {
3810
- 'amount': self.parse_number(amount),
3811
- })
3812
-
3813
- def parse_margin_modification(self, data, market=None):
3814
- innerData = self.safe_value(data, 'data', {})
3815
- sideRaw = self.safe_integer(innerData, 'side')
3816
- side = 'add' if (sideRaw == 1) else 'reduce'
3817
- statusCode = self.safe_integer(innerData, 'status')
3818
- status = 'ok' if (statusCode == 1) else 'failed'
3819
- return {
3820
- 'info': data,
3821
- 'type': side,
3822
- 'amount': None,
3823
- 'code': market['quote'],
3824
- 'symbol': market['symbol'],
3825
- 'status': status,
3826
- }
3827
-
3828
- def add_margin(self, symbol: str, amount, params={}):
3829
- """
3830
- add margin
3831
- :param str symbol: unified market symbol
3832
- :param float amount: amount of margin to add
3833
- :param dict params: extra parameters specific to the zb api endpoint
3834
- :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
3835
- """
3836
- if params['positionsId'] is None:
3837
- raise ArgumentsRequired(self.id + ' addMargin() requires a positionsId argument in the params')
3838
- return self.modify_margin_helper(symbol, amount, 1, params)
3839
-
3840
- def reduce_margin(self, symbol: str, amount, params={}):
3841
- """
3842
- remove margin from a position
3843
- :param str symbol: unified market symbol
3844
- :param float amount: the amount of margin to remove
3845
- :param dict params: extra parameters specific to the zb api endpoint
3846
- :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
3847
- """
3848
- if params['positionsId'] is None:
3849
- raise ArgumentsRequired(self.id + ' reduceMargin() requires a positionsId argument in the params')
3850
- return self.modify_margin_helper(symbol, amount, 0, params)
3851
-
3852
- def fetch_borrow_rate(self, code: str, params={}):
3853
- """
3854
- fetch the rate of interest to borrow a currency for margin trading
3855
- :param str code: unified currency code
3856
- :param dict params: extra parameters specific to the zb api endpoint
3857
- :returns dict: a `borrow rate structure <https://docs.ccxt.com/#/?id=borrow-rate-structure>`
3858
- """
3859
- self.load_markets()
3860
- currency = self.currency(code)
3861
- request = {
3862
- 'coin': currency['id'],
3863
- }
3864
- response = self.spotV1PrivateGetGetLoans(self.extend(request, params))
3865
- #
3866
- # {
3867
- # code: '1000',
3868
- # message: '操作成功',
3869
- # result: [
3870
- # {
3871
- # interestRateOfDay: '0.0005',
3872
- # repaymentDay: '30',
3873
- # amount: '148804.4841',
3874
- # balance: '148804.4841',
3875
- # rateOfDayShow: '0.05 %',
3876
- # coinName: 'USDT',
3877
- # lowestAmount: '0.01'
3878
- # },
3879
- # ]
3880
- # }
3881
- #
3882
- timestamp = self.milliseconds()
3883
- data = self.safe_value(response, 'result', [])
3884
- rate = self.safe_value(data, 0, {})
3885
- return {
3886
- 'currency': self.safe_currency_code(self.safe_string(rate, 'coinName')),
3887
- 'rate': self.safe_number(rate, 'interestRateOfDay'),
3888
- 'period': self.safe_number(rate, 'repaymentDay'),
3889
- 'timestamp': timestamp,
3890
- 'datetime': self.iso8601(timestamp),
3891
- 'info': rate,
3892
- }
3893
-
3894
- def fetch_borrow_rates(self, params={}):
3895
- """
3896
- fetch the borrow interest rates of all currencies
3897
- :param dict params: extra parameters specific to the zb api endpoint
3898
- :returns dict: a list of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>`
3899
- """
3900
- if params['coin'] is None:
3901
- raise ArgumentsRequired(self.id + ' fetchBorrowRates() requires a coin argument in the params')
3902
- self.load_markets()
3903
- currency = self.currency(self.safe_string(params, 'coin'))
3904
- request = {
3905
- 'coin': currency['id'],
3906
- }
3907
- response = self.spotV1PrivateGetGetLoans(self.extend(request, params))
3908
- #
3909
- # {
3910
- # code: '1000',
3911
- # message: '操作成功',
3912
- # result: [
3913
- # {
3914
- # interestRateOfDay: '0.0005',
3915
- # repaymentDay: '30',
3916
- # amount: '148804.4841',
3917
- # balance: '148804.4841',
3918
- # rateOfDayShow: '0.05 %',
3919
- # coinName: 'USDT',
3920
- # lowestAmount: '0.01'
3921
- # },
3922
- # ]
3923
- # }
3924
- #
3925
- timestamp = self.milliseconds()
3926
- data = self.safe_value(response, 'result', [])
3927
- rates = []
3928
- for i in range(0, len(data)):
3929
- entry = data[i]
3930
- rates.append({
3931
- 'currency': self.safe_currency_code(self.safe_string(entry, 'coinName')),
3932
- 'rate': self.safe_number(entry, 'interestRateOfDay'),
3933
- 'period': self.safe_number(entry, 'repaymentDay'),
3934
- 'timestamp': timestamp,
3935
- 'datetime': self.iso8601(timestamp),
3936
- 'info': entry,
3937
- })
3938
- return rates
3939
-
3940
- def set_position_mode(self, hedged, symbol: Optional[str] = None, params={}):
3941
- """
3942
- set the level of leverage for a market
3943
- :param float leverage: the rate of leverage
3944
- :param str symbol: unified market symbol
3945
- :param dict params: extra parameters specific to the zb api endpoint
3946
- :returns dict: response from the exchange
3947
- """
3948
- self.load_markets()
3949
- if symbol is None:
3950
- raise ArgumentsRequired(self.id + ' setPositionMode() requires a symbol argument')
3951
- market = self.market(symbol)
3952
- accountType = None
3953
- if not market['swap']:
3954
- raise BadSymbol(self.id + ' setPositionMode() supports swap contracts only')
3955
- else:
3956
- accountType = 1
3957
- request = {
3958
- 'marketId': market['id'],
3959
- 'positionMode': 2 if hedged else 1,
3960
- 'futuresAccountType': accountType, # 1: USDT perpetual swaps, 2: QC perpetual futures
3961
- }
3962
- response = self.contractV2PrivatePostSettingSetPositionsMode(self.extend(request, params))
3963
- #
3964
- # {
3965
- # "code": 10000,
3966
- # "desc": "success",
3967
- # "data": {
3968
- # "userId": 111,
3969
- # "marketId": 100,
3970
- # "leverage": 20,
3971
- # "marginMode": 1,
3972
- # "positionsMode": 2,
3973
- # "enableAutoAppend": 1,
3974
- # "maxAppendAmount": "11212",
3975
- # "marginCoins": "qc,usdt,eth",
3976
- # "id": 6737268451833817088,
3977
- # "createTime": 1606289971312,
3978
- # "modifyTime": 0,
3979
- # "extend": null
3980
- # }
3981
- # }
3982
- #
3983
- return response
3984
-
3985
- def borrow_margin(self, code: str, amount, symbol: Optional[str] = None, params={}):
3986
- """
3987
- create a loan to borrow margin
3988
- :param str code: unified currency code of the currency to borrow
3989
- :param float amount: the amount to borrow
3990
- :param str|None symbol: unified market symbol, required for isolated margin
3991
- :param dict params: extra parameters specific to the zb api endpoint
3992
- :param str params['safePwd']: transaction password, extra parameter required for cross margin
3993
- :param str params['marginMode']: 'cross' or 'isolated'
3994
- :returns dict: a `margin loan structure <https://docs.ccxt.com/#/?id=margin-loan-structure>`
3995
- """
3996
- self.load_markets()
3997
- market = None
3998
- if symbol is not None:
3999
- market = self.market(symbol)
4000
- symbol = market['symbol']
4001
- marginMode = None
4002
- marginMode, params = self.handle_margin_mode_and_params('borrowMargin', params)
4003
- if marginMode is None:
4004
- if symbol is not None:
4005
- marginMode = 'isolated' # default to isolated if the symbol is defined
4006
- else:
4007
- marginMode = 'cross' # default to cross
4008
- password = self.safe_string(params, 'safePwd', self.password)
4009
- currency = self.currency(code)
4010
- request = {
4011
- 'coin': currency['id'],
4012
- 'amount': self.currency_to_precision(code, amount),
4013
- 'safePwd': password, # transaction password
4014
- }
4015
- method = None
4016
- if marginMode == 'isolated':
4017
- if symbol is None:
4018
- raise ArgumentsRequired(self.id + ' borrowMargin() requires a symbol argument for isolated margin')
4019
- marketInner = self.market(symbol)
4020
- request['marketName'] = self.safe_symbol(marketInner['id'], marketInner, '_')
4021
- method = 'spotV1PrivateGetBorrow'
4022
- elif marginMode == 'cross':
4023
- method = 'spotV1PrivateGetDoCrossLoan'
4024
- response = getattr(self, method)(self.extend(request, params))
4025
- #
4026
- # {
4027
- # "code": 1000,
4028
- # "message": "操作成功"
4029
- # }
4030
- #
4031
- transaction = self.parse_margin_loan(response, currency)
4032
- return self.extend(transaction, {
4033
- 'amount': amount,
4034
- 'symbol': symbol,
4035
- })
4036
-
4037
- def parse_margin_loan(self, info, currency=None):
4038
- #
4039
- # {
4040
- # "code": 1000,
4041
- # "message": "操作成功"
4042
- # }
4043
- #
4044
- return {
4045
- 'id': None,
4046
- 'currency': self.safe_currency_code(None, currency),
4047
- 'amount': None,
4048
- 'symbol': None,
4049
- 'timestamp': None,
4050
- 'datetime': None,
4051
- 'info': info,
4052
- }
4053
-
4054
- def nonce(self):
4055
- return self.milliseconds()
4056
-
4057
- def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
4058
- section = self.safe_string(api, 0)
4059
- version = self.safe_string(api, 1)
4060
- access = self.safe_string(api, 2)
4061
- url = self.implode_hostname(self.urls['api'][section][version][access])
4062
- if access == 'public':
4063
- if path == 'getFeeInfo':
4064
- url = self.implode_hostname(self.urls['api'][section][version]['private']) + '/' + path
4065
- else:
4066
- url += '/' + version + '/' + path
4067
- if params:
4068
- url += '?' + self.urlencode(params)
4069
- elif section == 'contract':
4070
- timestamp = self.milliseconds()
4071
- iso8601 = self.iso8601(timestamp)
4072
- signedString = iso8601 + method + '/Server/api/' + version + '/' + path
4073
- params = self.keysort(params)
4074
- headers = {
4075
- 'ZB-APIKEY': self.apiKey,
4076
- 'ZB-TIMESTAMP': iso8601,
4077
- # 'ZB-LAN': 'cn', # cn, en, kr
4078
- }
4079
- url += '/' + version + '/' + path
4080
- if method == 'POST':
4081
- headers['Content-Type'] = 'application/json'
4082
- body = self.json(params)
4083
- signedString += self.urlencode(params)
4084
- else:
4085
- if params:
4086
- query = self.urlencode(params)
4087
- url += '?' + query
4088
- signedString += query
4089
- secret = self.hash(self.encode(self.secret), 'sha1')
4090
- signature = self.hmac(self.encode(signedString), self.encode(secret), hashlib.sha256, 'base64')
4091
- headers['ZB-SIGN'] = signature
4092
- else:
4093
- query = self.keysort(self.extend({
4094
- 'method': path,
4095
- 'accesskey': self.apiKey,
4096
- }, params))
4097
- nonce = self.nonce()
4098
- query = self.keysort(query)
4099
- auth = self.rawencode(query)
4100
- secret = self.hash(self.encode(self.secret), 'sha1')
4101
- signature = self.hmac(self.encode(auth), self.encode(secret), hashlib.md5)
4102
- suffix = 'sign=' + signature + '&reqTime=' + str(nonce)
4103
- url += '/' + path + '?' + auth + '&' + suffix
4104
- return {'url': url, 'method': method, 'body': body, 'headers': headers}
4105
-
4106
- def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
4107
- if response is None:
4108
- return None # fallback to default error handler
4109
- if body[0] == '{':
4110
- feedback = self.id + ' ' + body
4111
- self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
4112
- if 'code' in response:
4113
- code = self.safe_string(response, 'code')
4114
- self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
4115
- if (code != '1000') and (code != '10000'):
4116
- raise ExchangeError(feedback)
4117
- # special case for {"result":false,"message":"服务端忙碌"}(a "Busy Server" reply)
4118
- result = self.safe_value(response, 'result')
4119
- if result is not None:
4120
- if not result:
4121
- message = self.safe_string(response, 'message')
4122
- if message == u'服务端忙碌':
4123
- raise ExchangeNotAvailable(feedback)
4124
- else:
4125
- raise ExchangeError(feedback)
4126
- return None