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