ccxt 4.2.20__py2.py3-none-any.whl → 4.2.22__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.
Potentially problematic release.
This version of ccxt might be problematic. Click here for more details.
- ccxt/__init__.py +1 -1
- ccxt/abstract/binance.py +3 -0
- ccxt/abstract/binancecoinm.py +3 -0
- ccxt/abstract/binanceus.py +16 -12
- ccxt/abstract/binanceusdm.py +3 -0
- ccxt/abstract/gate.py +1 -0
- ccxt/abstract/gateio.py +1 -0
- ccxt/abstract/novadax.py +22 -18
- ccxt/abstract/phemex.py +1 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +16 -4
- ccxt/async_support/bigone.py +1 -0
- ccxt/async_support/binance.py +14 -3
- ccxt/async_support/bitget.py +11 -1
- ccxt/async_support/bitrue.py +1 -0
- ccxt/async_support/bitvavo.py +250 -152
- ccxt/async_support/blockchaincom.py +3 -1
- ccxt/async_support/bybit.py +49 -10
- ccxt/async_support/coinbasepro.py +1 -0
- ccxt/async_support/coinex.py +34 -12
- ccxt/async_support/deribit.py +145 -0
- ccxt/async_support/gate.py +30 -1
- ccxt/async_support/novadax.py +27 -23
- ccxt/async_support/okcoin.py +3 -0
- ccxt/async_support/phemex.py +7 -3
- ccxt/async_support/poloniex.py +1 -0
- ccxt/async_support/woo.py +1 -1
- ccxt/base/exchange.py +17 -5
- ccxt/bigone.py +1 -0
- ccxt/binance.py +14 -3
- ccxt/bitget.py +11 -1
- ccxt/bitrue.py +1 -0
- ccxt/bitvavo.py +250 -152
- ccxt/blockchaincom.py +3 -1
- ccxt/bybit.py +49 -10
- ccxt/coinbasepro.py +1 -0
- ccxt/coinex.py +34 -12
- ccxt/deribit.py +145 -0
- ccxt/gate.py +30 -1
- ccxt/novadax.py +27 -23
- ccxt/okcoin.py +3 -0
- ccxt/phemex.py +7 -3
- ccxt/poloniex.py +1 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bequant.py +7 -1
- ccxt/pro/binance.py +7 -4
- ccxt/pro/binancecoinm.py +7 -1
- ccxt/pro/binanceus.py +7 -1
- ccxt/pro/bitcoincom.py +7 -1
- ccxt/pro/bitget.py +1 -1
- ccxt/pro/bitopro.py +7 -3
- ccxt/pro/bitrue.py +5 -1
- ccxt/pro/bitvavo.py +623 -19
- ccxt/pro/lbank.py +1 -1
- ccxt/pro/okx.py +10 -2
- ccxt/test/test_async.py +14 -1
- ccxt/test/test_sync.py +14 -1
- ccxt/woo.py +1 -1
- {ccxt-4.2.20.dist-info → ccxt-4.2.22.dist-info}/METADATA +4 -4
- {ccxt-4.2.20.dist-info → ccxt-4.2.22.dist-info}/RECORD +62 -62
- {ccxt-4.2.20.dist-info → ccxt-4.2.22.dist-info}/WHEEL +0 -0
- {ccxt-4.2.20.dist-info → ccxt-4.2.22.dist-info}/top_level.txt +0 -0
ccxt/bybit.py
CHANGED
@@ -52,7 +52,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
52
52
|
'closeAllPositions': False,
|
53
53
|
'closePosition': False,
|
54
54
|
'createMarketBuyOrderWithCost': True,
|
55
|
-
'createMarketSellOrderWithCost':
|
55
|
+
'createMarketSellOrderWithCost': True,
|
56
56
|
'createOrder': True,
|
57
57
|
'createOrders': True,
|
58
58
|
'createOrderWithTakeProfitAndStopLoss': True,
|
@@ -972,7 +972,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
972
972
|
'fetchMarkets': ['spot', 'linear', 'inverse', 'option'],
|
973
973
|
'enableUnifiedMargin': None,
|
974
974
|
'enableUnifiedAccount': None,
|
975
|
-
'createMarketBuyOrderRequiresPrice': True,
|
975
|
+
'createMarketBuyOrderRequiresPrice': True, # only True for classic accounts
|
976
976
|
'createUnifiedMarginAccount': False,
|
977
977
|
'defaultType': 'swap', # 'swap', 'future', 'option', 'spot'
|
978
978
|
'defaultSubType': 'linear', # 'linear', 'inverse'
|
@@ -3301,8 +3301,26 @@ class bybit(Exchange, ImplicitAPI):
|
|
3301
3301
|
market = self.market(symbol)
|
3302
3302
|
if not market['spot']:
|
3303
3303
|
raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
|
3304
|
-
|
3305
|
-
|
3304
|
+
return self.create_order(symbol, 'market', 'buy', cost, 1, params)
|
3305
|
+
|
3306
|
+
def create_market_sell_order_with_cost(self, symbol: str, cost, params={}):
|
3307
|
+
"""
|
3308
|
+
:see: https://bybit-exchange.github.io/docs/v5/order/create-order
|
3309
|
+
create a market sell order by providing the symbol and cost
|
3310
|
+
:param str symbol: unified symbol of the market to create an order in
|
3311
|
+
:param float cost: how much you want to trade in units of the quote currency
|
3312
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3313
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
3314
|
+
"""
|
3315
|
+
self.load_markets()
|
3316
|
+
types = self.is_unified_enabled()
|
3317
|
+
enableUnifiedAccount = types[1]
|
3318
|
+
if not enableUnifiedAccount:
|
3319
|
+
raise NotSupported(self.id + ' createMarketSellOrderWithCost() supports UTA accounts only')
|
3320
|
+
market = self.market(symbol)
|
3321
|
+
if not market['spot']:
|
3322
|
+
raise NotSupported(self.id + ' createMarketSellOrderWithCost() supports spot orders only')
|
3323
|
+
return self.create_order(symbol, 'market', 'sell', cost, 1, params)
|
3306
3324
|
|
3307
3325
|
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
|
3308
3326
|
"""
|
@@ -3343,7 +3361,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
3343
3361
|
return self.create_usdc_order(symbol, type, side, amount, price, params)
|
3344
3362
|
trailingAmount = self.safe_string_2(params, 'trailingAmount', 'trailingStop')
|
3345
3363
|
isTrailingAmountOrder = trailingAmount is not None
|
3346
|
-
orderRequest = self.create_order_request(symbol, type, side, amount, price, params)
|
3364
|
+
orderRequest = self.create_order_request(symbol, type, side, amount, price, params, enableUnifiedAccount)
|
3347
3365
|
response = None
|
3348
3366
|
if isTrailingAmountOrder:
|
3349
3367
|
response = self.privatePostV5PositionTradingStop(orderRequest)
|
@@ -3364,7 +3382,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
3364
3382
|
order = self.safe_value(response, 'result', {})
|
3365
3383
|
return self.parse_order(order, market)
|
3366
3384
|
|
3367
|
-
def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
|
3385
|
+
def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}, isUTA=True):
|
3368
3386
|
market = self.market(symbol)
|
3369
3387
|
symbol = market['symbol']
|
3370
3388
|
lowerCaseType = type.lower()
|
@@ -3403,12 +3421,31 @@ class bybit(Exchange, ImplicitAPI):
|
|
3403
3421
|
request['category'] = 'inverse'
|
3404
3422
|
elif market['option']:
|
3405
3423
|
request['category'] = 'option'
|
3406
|
-
|
3424
|
+
cost = self.safe_string(params, 'cost')
|
3425
|
+
params = self.omit(params, 'cost')
|
3426
|
+
# if the cost is inferable, let's keep the old logic and ignore marketUnit, to minimize the impact of the changes
|
3427
|
+
isMarketBuyAndCostInferable = (lowerCaseType == 'market') and (side == 'buy') and ((price is not None) or (cost is not None))
|
3428
|
+
if market['spot'] and (type == 'market') and isUTA and not isMarketBuyAndCostInferable:
|
3429
|
+
# UTA account can specify the cost of the order on both sides
|
3430
|
+
if (cost is not None) or (price is not None):
|
3431
|
+
request['marketUnit'] = 'quoteCoin'
|
3432
|
+
orderCost = None
|
3433
|
+
if cost is not None:
|
3434
|
+
orderCost = cost
|
3435
|
+
else:
|
3436
|
+
amountString = self.number_to_string(amount)
|
3437
|
+
priceString = self.number_to_string(price)
|
3438
|
+
quoteAmount = Precise.string_mul(amountString, priceString)
|
3439
|
+
orderCost = quoteAmount
|
3440
|
+
request['qty'] = self.cost_to_precision(symbol, orderCost)
|
3441
|
+
else:
|
3442
|
+
request['marketUnit'] = 'baseCoin'
|
3443
|
+
request['qty'] = self.amount_to_precision(symbol, amount)
|
3444
|
+
elif market['spot'] and (type == 'market') and (side == 'buy'):
|
3445
|
+
# classic accounts
|
3407
3446
|
# for market buy it requires the amount of quote currency to spend
|
3408
3447
|
createMarketBuyOrderRequiresPrice = True
|
3409
3448
|
createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
|
3410
|
-
cost = self.safe_number(params, 'cost')
|
3411
|
-
params = self.omit(params, 'cost')
|
3412
3449
|
if createMarketBuyOrderRequiresPrice:
|
3413
3450
|
if (price is None) and (cost is None):
|
3414
3451
|
raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend in the amount argument')
|
@@ -3504,6 +3541,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
3504
3541
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
3505
3542
|
"""
|
3506
3543
|
self.load_markets()
|
3544
|
+
accounts = self.is_unified_enabled()
|
3545
|
+
isUta = accounts[1]
|
3507
3546
|
ordersRequests = []
|
3508
3547
|
orderSymbols = []
|
3509
3548
|
for i in range(0, len(orders)):
|
@@ -3515,7 +3554,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
3515
3554
|
amount = self.safe_value(rawOrder, 'amount')
|
3516
3555
|
price = self.safe_value(rawOrder, 'price')
|
3517
3556
|
orderParams = self.safe_value(rawOrder, 'params', {})
|
3518
|
-
orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
|
3557
|
+
orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams, isUta)
|
3519
3558
|
ordersRequests.append(orderRequest)
|
3520
3559
|
symbols = self.market_symbols(orderSymbols, None, False, True, True)
|
3521
3560
|
market = self.market(symbols[0])
|
ccxt/coinbasepro.py
CHANGED
@@ -53,6 +53,7 @@ class coinbasepro(Exchange, ImplicitAPI):
|
|
53
53
|
'fetchDepositAddress': False, # the exchange does not have self method, only createDepositAddress, see https://github.com/ccxt/ccxt/pull/7405
|
54
54
|
'fetchDeposits': True,
|
55
55
|
'fetchDepositsWithdrawals': True,
|
56
|
+
'fetchFundingRate': False,
|
56
57
|
'fetchLedger': True,
|
57
58
|
'fetchMarginMode': False,
|
58
59
|
'fetchMarkets': True,
|
ccxt/coinex.py
CHANGED
@@ -1530,8 +1530,9 @@ class coinex(Exchange, ImplicitAPI):
|
|
1530
1530
|
"""
|
1531
1531
|
marketType = None
|
1532
1532
|
marketType, params = self.handle_market_type_and_params('fetchBalance', None, params)
|
1533
|
-
|
1534
|
-
|
1533
|
+
marginMode = None
|
1534
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchBalance', params)
|
1535
|
+
marketType = 'margin' if (marginMode is not None) else marketType
|
1535
1536
|
params = self.omit(params, 'margin')
|
1536
1537
|
if marketType == 'margin':
|
1537
1538
|
return self.fetch_margin_balance(params)
|
@@ -2005,8 +2006,9 @@ class coinex(Exchange, ImplicitAPI):
|
|
2005
2006
|
if timeInForceRaw is not None:
|
2006
2007
|
request['option'] = timeInForceRaw # exchange takes 'IOC' and 'FOK'
|
2007
2008
|
accountId = self.safe_integer(params, 'account_id')
|
2008
|
-
|
2009
|
-
|
2009
|
+
marginMode = None
|
2010
|
+
marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
|
2011
|
+
if marginMode is not None:
|
2010
2012
|
if accountId is None:
|
2011
2013
|
raise BadRequest(self.id + ' createOrder() requires an account_id parameter for margin orders')
|
2012
2014
|
request['account_id'] = accountId
|
@@ -2473,9 +2475,10 @@ class coinex(Exchange, ImplicitAPI):
|
|
2473
2475
|
'market': market['id'],
|
2474
2476
|
}
|
2475
2477
|
accountId = self.safe_integer(params, 'account_id')
|
2476
|
-
|
2478
|
+
marginMode = None
|
2479
|
+
marginMode, params = self.handle_margin_mode_and_params('cancelOrder', params)
|
2477
2480
|
clientOrderId = self.safe_string_2(params, 'client_id', 'clientOrderId')
|
2478
|
-
if
|
2481
|
+
if marginMode is not None:
|
2479
2482
|
if accountId is None:
|
2480
2483
|
raise BadRequest(self.id + ' cancelOrder() requires an account_id parameter for margin orders')
|
2481
2484
|
request['account_id'] = accountId
|
@@ -2814,8 +2817,9 @@ class coinex(Exchange, ImplicitAPI):
|
|
2814
2817
|
request['market'] = market['id']
|
2815
2818
|
marketType, query = self.handle_market_type_and_params('fetchOrdersByStatus', market, params)
|
2816
2819
|
accountId = self.safe_integer(params, 'account_id')
|
2817
|
-
|
2818
|
-
|
2820
|
+
marginMode = None
|
2821
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchOrdersByStatus', params)
|
2822
|
+
if marginMode is not None:
|
2819
2823
|
if accountId is None:
|
2820
2824
|
raise BadRequest(self.id + ' fetchOpenOrders() and fetchClosedOrders() require an account_id parameter for margin orders')
|
2821
2825
|
request['account_id'] = accountId
|
@@ -3179,8 +3183,9 @@ class coinex(Exchange, ImplicitAPI):
|
|
3179
3183
|
raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument for non-spot markets')
|
3180
3184
|
swap = (type == 'swap')
|
3181
3185
|
accountId = self.safe_integer(params, 'account_id')
|
3182
|
-
|
3183
|
-
|
3186
|
+
marginMode = None
|
3187
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
|
3188
|
+
if marginMode is not None:
|
3184
3189
|
if accountId is None:
|
3185
3190
|
raise BadRequest(self.id + ' fetchMyTrades() requires an account_id parameter for margin trades')
|
3186
3191
|
request['account_id'] = accountId
|
@@ -4418,9 +4423,10 @@ class coinex(Exchange, ImplicitAPI):
|
|
4418
4423
|
else:
|
4419
4424
|
request['limit'] = 100
|
4420
4425
|
params = self.omit(params, 'page')
|
4421
|
-
|
4426
|
+
marginMode = None
|
4427
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchTransfers', params)
|
4422
4428
|
response = None
|
4423
|
-
if
|
4429
|
+
if marginMode is not None:
|
4424
4430
|
response = self.privateGetMarginTransferHistory(self.extend(request, params))
|
4425
4431
|
else:
|
4426
4432
|
response = self.privateGetContractTransferHistory(self.extend(request, params))
|
@@ -4967,6 +4973,22 @@ class coinex(Exchange, ImplicitAPI):
|
|
4967
4973
|
depositWithdrawFees[code] = self.assign_default_deposit_withdraw_fees(depositWithdrawFees[code], currency)
|
4968
4974
|
return depositWithdrawFees
|
4969
4975
|
|
4976
|
+
def handle_margin_mode_and_params(self, methodName, params={}, defaultValue=None):
|
4977
|
+
"""
|
4978
|
+
* @ignore
|
4979
|
+
marginMode specified by params["marginMode"], self.options["marginMode"], self.options["defaultMarginMode"], params["margin"] = True or self.options["defaultType"] = 'margin'
|
4980
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
4981
|
+
:returns Array: the marginMode in lowercase
|
4982
|
+
"""
|
4983
|
+
defaultType = self.safe_string(self.options, 'defaultType')
|
4984
|
+
isMargin = self.safe_value(params, 'margin', False)
|
4985
|
+
marginMode = None
|
4986
|
+
marginMode, params = super(coinex, self).handle_margin_mode_and_params(methodName, params, defaultValue)
|
4987
|
+
if marginMode is None:
|
4988
|
+
if (defaultType == 'margin') or (isMargin is True):
|
4989
|
+
marginMode = 'isolated'
|
4990
|
+
return [marginMode, params]
|
4991
|
+
|
4970
4992
|
def nonce(self):
|
4971
4993
|
return self.milliseconds()
|
4972
4994
|
|
ccxt/deribit.py
CHANGED
@@ -415,6 +415,151 @@ class deribit(Exchange, ImplicitAPI):
|
|
415
415
|
},
|
416
416
|
})
|
417
417
|
|
418
|
+
def convert_expire_date(self, date):
|
419
|
+
# parse YYMMDD to timestamp
|
420
|
+
year = date[0:2]
|
421
|
+
month = date[2:4]
|
422
|
+
day = date[4:6]
|
423
|
+
reconstructedDate = '20' + year + '-' + month + '-' + day + 'T00:00:00Z'
|
424
|
+
return reconstructedDate
|
425
|
+
|
426
|
+
def convert_market_id_expire_date(self, date):
|
427
|
+
# parse 19JAN24 to 240119
|
428
|
+
monthMappping = {
|
429
|
+
'JAN': '01',
|
430
|
+
'FEB': '02',
|
431
|
+
'MAR': '03',
|
432
|
+
'APR': '04',
|
433
|
+
'MAY': '05',
|
434
|
+
'JUN': '06',
|
435
|
+
'JUL': '07',
|
436
|
+
'AUG': '08',
|
437
|
+
'SEP': '09',
|
438
|
+
'OCT': '10',
|
439
|
+
'NOV': '11',
|
440
|
+
'DEC': '12',
|
441
|
+
}
|
442
|
+
year = date[0:2]
|
443
|
+
monthName = date[2:5]
|
444
|
+
month = self.safe_string(monthMappping, monthName)
|
445
|
+
day = date[5:7]
|
446
|
+
reconstructedDate = day + month + year
|
447
|
+
return reconstructedDate
|
448
|
+
|
449
|
+
def convert_expire_date_to_market_id_date(self, date):
|
450
|
+
# parse 240119 to 19JAN24
|
451
|
+
year = date[0:2]
|
452
|
+
monthRaw = date[2:4]
|
453
|
+
month = None
|
454
|
+
day = date[4:6]
|
455
|
+
if monthRaw == '01':
|
456
|
+
month = 'JAN'
|
457
|
+
elif monthRaw == '02':
|
458
|
+
month = 'FEB'
|
459
|
+
elif monthRaw == '03':
|
460
|
+
month = 'MAR'
|
461
|
+
elif monthRaw == '04':
|
462
|
+
month = 'APR'
|
463
|
+
elif monthRaw == '05':
|
464
|
+
month = 'MAY'
|
465
|
+
elif monthRaw == '06':
|
466
|
+
month = 'JUN'
|
467
|
+
elif monthRaw == '07':
|
468
|
+
month = 'JUL'
|
469
|
+
elif monthRaw == '08':
|
470
|
+
month = 'AUG'
|
471
|
+
elif monthRaw == '09':
|
472
|
+
month = 'SEP'
|
473
|
+
elif monthRaw == '10':
|
474
|
+
month = 'OCT'
|
475
|
+
elif monthRaw == '11':
|
476
|
+
month = 'NOV'
|
477
|
+
elif monthRaw == '12':
|
478
|
+
month = 'DEC'
|
479
|
+
reconstructedDate = day + month + year
|
480
|
+
return reconstructedDate
|
481
|
+
|
482
|
+
def create_expired_option_market(self, symbol):
|
483
|
+
# support expired option contracts
|
484
|
+
quote = 'USD'
|
485
|
+
settle = None
|
486
|
+
optionParts = symbol.split('-')
|
487
|
+
symbolBase = symbol.split('/')
|
488
|
+
base = None
|
489
|
+
expiry = None
|
490
|
+
if symbol.find('/') > -1:
|
491
|
+
base = self.safe_string(symbolBase, 0)
|
492
|
+
expiry = self.safe_string(optionParts, 1)
|
493
|
+
if symbol.find('USDC') > -1:
|
494
|
+
base = base + '_USDC'
|
495
|
+
else:
|
496
|
+
base = self.safe_string(optionParts, 0)
|
497
|
+
expiry = self.convert_market_id_expire_date(self.safe_string(optionParts, 1))
|
498
|
+
if symbol.find('USDC') > -1:
|
499
|
+
quote = 'USDC'
|
500
|
+
settle = 'USDC'
|
501
|
+
else:
|
502
|
+
settle = base
|
503
|
+
splitBase = base
|
504
|
+
if base.find('_') > -1:
|
505
|
+
splitSymbol = base.split('_')
|
506
|
+
splitBase = self.safe_string(splitSymbol, 0)
|
507
|
+
strike = self.safe_string(optionParts, 2)
|
508
|
+
optionType = self.safe_string(optionParts, 3)
|
509
|
+
datetime = self.convert_expire_date(expiry)
|
510
|
+
timestamp = self.parse8601(datetime)
|
511
|
+
return {
|
512
|
+
'id': base + '-' + self.convert_expire_date_to_market_id_date(expiry) + '-' + strike + '-' + optionType,
|
513
|
+
'symbol': splitBase + '/' + quote + ':' + settle + '-' + expiry + '-' + strike + '-' + optionType,
|
514
|
+
'base': base,
|
515
|
+
'quote': quote,
|
516
|
+
'settle': settle,
|
517
|
+
'baseId': base,
|
518
|
+
'quoteId': quote,
|
519
|
+
'settleId': settle,
|
520
|
+
'active': False,
|
521
|
+
'type': 'option',
|
522
|
+
'linear': None,
|
523
|
+
'inverse': None,
|
524
|
+
'spot': False,
|
525
|
+
'swap': False,
|
526
|
+
'future': False,
|
527
|
+
'option': True,
|
528
|
+
'margin': False,
|
529
|
+
'contract': True,
|
530
|
+
'contractSize': None,
|
531
|
+
'expiry': timestamp,
|
532
|
+
'expiryDatetime': datetime,
|
533
|
+
'optionType': 'call' if (optionType == 'C') else 'put',
|
534
|
+
'strike': self.parse_number(strike),
|
535
|
+
'precision': {
|
536
|
+
'amount': None,
|
537
|
+
'price': None,
|
538
|
+
},
|
539
|
+
'limits': {
|
540
|
+
'amount': {
|
541
|
+
'min': None,
|
542
|
+
'max': None,
|
543
|
+
},
|
544
|
+
'price': {
|
545
|
+
'min': None,
|
546
|
+
'max': None,
|
547
|
+
},
|
548
|
+
'cost': {
|
549
|
+
'min': None,
|
550
|
+
'max': None,
|
551
|
+
},
|
552
|
+
},
|
553
|
+
'info': None,
|
554
|
+
}
|
555
|
+
|
556
|
+
def safe_market(self, marketId=None, market=None, delimiter=None, marketType=None):
|
557
|
+
isOption = (marketId is not None) and ((marketId.endswith('-C')) or (marketId.endswith('-P')))
|
558
|
+
if isOption and not (marketId in self.markets_by_id):
|
559
|
+
# handle expired option contracts
|
560
|
+
return self.create_expired_option_market(marketId)
|
561
|
+
return super(deribit, self).safe_market(marketId, market, delimiter, marketType)
|
562
|
+
|
418
563
|
def fetch_time(self, params={}):
|
419
564
|
"""
|
420
565
|
fetches the current integer timestamp in milliseconds from the exchange server
|
ccxt/gate.py
CHANGED
@@ -547,6 +547,7 @@ class gate(Exchange, ImplicitAPI):
|
|
547
547
|
'multi_collateral/currency_quota': 20 / 15,
|
548
548
|
'multi_collateral/currencies': 20 / 15,
|
549
549
|
'multi_collateral/ltv': 20 / 15,
|
550
|
+
'multi_collateral/fixed_rate': 20 / 15,
|
550
551
|
},
|
551
552
|
'post': {
|
552
553
|
'collateral/orders': 20 / 15,
|
@@ -5168,7 +5169,7 @@ class gate(Exchange, ImplicitAPI):
|
|
5168
5169
|
retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
|
5169
5170
|
:see: https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts
|
5170
5171
|
:see: https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts-2
|
5171
|
-
:param str[]
|
5172
|
+
:param str[] [symbols]: list of unified market symbols
|
5172
5173
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
5173
5174
|
:returns dict: a dictionary of `leverage tiers structures <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`, indexed by market symbols
|
5174
5175
|
"""
|
@@ -5306,6 +5307,32 @@ class gate(Exchange, ImplicitAPI):
|
|
5306
5307
|
#
|
5307
5308
|
return self.parse_market_leverage_tiers(response, market)
|
5308
5309
|
|
5310
|
+
def parse_emulated_leverage_tiers(self, info, market=None):
|
5311
|
+
maintenanceMarginUnit = self.safe_string(info, 'maintenance_rate') # '0.005',
|
5312
|
+
leverageMax = self.safe_string(info, 'leverage_max') # '100',
|
5313
|
+
riskLimitStep = self.safe_string(info, 'risk_limit_step') # '1000000',
|
5314
|
+
riskLimitMax = self.safe_string(info, 'risk_limit_max') # '16000000',
|
5315
|
+
initialMarginUnit = Precise.string_div('1', leverageMax)
|
5316
|
+
maintenanceMarginRate = maintenanceMarginUnit
|
5317
|
+
initialMarginRatio = initialMarginUnit
|
5318
|
+
floor = '0'
|
5319
|
+
tiers = []
|
5320
|
+
while(Precise.string_lt(floor, riskLimitMax)):
|
5321
|
+
cap = Precise.string_add(floor, riskLimitStep)
|
5322
|
+
tiers.append({
|
5323
|
+
'tier': self.parse_number(Precise.string_div(cap, riskLimitStep)),
|
5324
|
+
'currency': self.safe_string(market, 'settle'),
|
5325
|
+
'minNotional': self.parse_number(floor),
|
5326
|
+
'maxNotional': self.parse_number(cap),
|
5327
|
+
'maintenanceMarginRate': self.parse_number(maintenanceMarginRate),
|
5328
|
+
'maxLeverage': self.parse_number(Precise.string_div('1', initialMarginRatio)),
|
5329
|
+
'info': info,
|
5330
|
+
})
|
5331
|
+
maintenanceMarginRate = Precise.string_add(maintenanceMarginRate, maintenanceMarginUnit)
|
5332
|
+
initialMarginRatio = Precise.string_add(initialMarginRatio, initialMarginUnit)
|
5333
|
+
floor = cap
|
5334
|
+
return tiers
|
5335
|
+
|
5309
5336
|
def parse_market_leverage_tiers(self, info, market: Market = None):
|
5310
5337
|
#
|
5311
5338
|
# [
|
@@ -5318,6 +5345,8 @@ class gate(Exchange, ImplicitAPI):
|
|
5318
5345
|
# }
|
5319
5346
|
# ]
|
5320
5347
|
#
|
5348
|
+
if not isinstance(info, list):
|
5349
|
+
return self.parse_emulated_leverage_tiers(info, market)
|
5321
5350
|
minNotional = 0
|
5322
5351
|
tiers = []
|
5323
5352
|
for i in range(0, len(info)):
|
ccxt/novadax.py
CHANGED
@@ -33,9 +33,9 @@ class novadax(Exchange, ImplicitAPI):
|
|
33
33
|
'id': 'novadax',
|
34
34
|
'name': 'NovaDAX',
|
35
35
|
'countries': ['BR'], # Brazil
|
36
|
-
#
|
37
|
-
#
|
38
|
-
'rateLimit':
|
36
|
+
# 6000 weight per min => 100 weight per second => min weight = 1
|
37
|
+
# 100 requests per second =>( 1000ms / 100 ) = 10 ms between requests on average
|
38
|
+
'rateLimit': 10,
|
39
39
|
'version': 'v1',
|
40
40
|
# new metainfo interface
|
41
41
|
'has': {
|
@@ -133,33 +133,37 @@ class novadax(Exchange, ImplicitAPI):
|
|
133
133
|
'api': {
|
134
134
|
'public': {
|
135
135
|
'get': {
|
136
|
-
'common/symbol': 1
|
137
|
-
'common/symbols': 1
|
138
|
-
'common/timestamp': 1
|
139
|
-
'market/tickers':
|
140
|
-
'market/ticker': 1
|
141
|
-
'market/depth': 1
|
142
|
-
'market/trades':
|
143
|
-
'market/kline/history':
|
136
|
+
'common/symbol': 1,
|
137
|
+
'common/symbols': 1,
|
138
|
+
'common/timestamp': 1,
|
139
|
+
'market/tickers': 5,
|
140
|
+
'market/ticker': 1,
|
141
|
+
'market/depth': 1,
|
142
|
+
'market/trades': 5,
|
143
|
+
'market/kline/history': 5,
|
144
144
|
},
|
145
145
|
},
|
146
146
|
'private': {
|
147
147
|
'get': {
|
148
|
-
'orders/get':
|
149
|
-
'orders/list':
|
150
|
-
'orders/fill': 3,
|
151
|
-
'orders/fills':
|
152
|
-
'account/getBalance':
|
153
|
-
'account/subs':
|
154
|
-
'account/subs/balance':
|
155
|
-
'account/subs/transfer/record':
|
148
|
+
'orders/get': 1,
|
149
|
+
'orders/list': 10,
|
150
|
+
'orders/fill': 3, # not found in doc
|
151
|
+
'orders/fills': 10,
|
152
|
+
'account/getBalance': 1,
|
153
|
+
'account/subs': 1,
|
154
|
+
'account/subs/balance': 1,
|
155
|
+
'account/subs/transfer/record': 10,
|
156
156
|
'wallet/query/deposit-withdraw': 3,
|
157
157
|
},
|
158
158
|
'post': {
|
159
|
-
'orders/create':
|
160
|
-
'orders/
|
161
|
-
'
|
162
|
-
'
|
159
|
+
'orders/create': 5,
|
160
|
+
'orders/batch-create': 50,
|
161
|
+
'orders/cancel': 1,
|
162
|
+
'orders/batch-cancel': 10,
|
163
|
+
'orders/cancel-by-symbol': 10,
|
164
|
+
'account/subs/transfer': 5,
|
165
|
+
'wallet/withdraw/coin': 3,
|
166
|
+
'account/withdraw/coin': 3, # not found in doc
|
163
167
|
},
|
164
168
|
},
|
165
169
|
},
|
ccxt/okcoin.py
CHANGED
@@ -67,6 +67,9 @@ class okcoin(Exchange, ImplicitAPI):
|
|
67
67
|
'fetchCurrencies': True, # see below
|
68
68
|
'fetchDepositAddress': True,
|
69
69
|
'fetchDeposits': True,
|
70
|
+
'fetchFundingHistory': False,
|
71
|
+
'fetchFundingRate': False,
|
72
|
+
'fetchFundingRateHistory': False,
|
70
73
|
'fetchLedger': True,
|
71
74
|
'fetchMarkets': True,
|
72
75
|
'fetchMyTrades': True,
|
ccxt/phemex.py
CHANGED
@@ -207,6 +207,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
207
207
|
'api-data/g-futures/trades': 5, # ?symbol=<symbol>
|
208
208
|
'api-data/futures/trading-fees': 5, # ?symbol=<symbol>
|
209
209
|
'api-data/g-futures/trading-fees': 5, # ?symbol=<symbol>
|
210
|
+
'api-data/futures/v2/tradeAccountDetail': 5, # ?currency=<currecny>&type=<type>&limit=<limit>&offset=<offset>&start=<start>&end=<end>&withCount=<withCount>
|
210
211
|
'g-orders/activeList': 1, # ?symbol=<symbol>
|
211
212
|
'orders/activeList': 1, # ?symbol=<symbol>
|
212
213
|
'exchange/order/list': 5, # ?symbol=<symbol>&start=<start>&end=<end>&offset=<offset>&limit=<limit>&ordStatus=<ordStatus>&withCount=<withCount>
|
@@ -1849,23 +1850,26 @@ class phemex(Exchange, ImplicitAPI):
|
|
1849
1850
|
def fetch_balance(self, params={}) -> Balances:
|
1850
1851
|
"""
|
1851
1852
|
query for balance and get the amount of funds available for trading or funds locked in orders
|
1853
|
+
:see: https://phemex-docs.github.io/#query-wallets
|
1852
1854
|
:see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
|
1855
|
+
:see: https://phemex-docs.github.io/#query-trading-account-and-positions
|
1853
1856
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1854
1857
|
:param str [params.type]: spot or swap
|
1858
|
+
:param str [params.code]: *swap only* currency code of the balance to query(USD, USDT, etc), default is USDT
|
1855
1859
|
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
1856
1860
|
"""
|
1857
1861
|
self.load_markets()
|
1858
1862
|
type = None
|
1859
1863
|
type, params = self.handle_market_type_and_params('fetchBalance', None, params)
|
1860
1864
|
code = self.safe_string(params, 'code')
|
1861
|
-
params = self.omit(params, ['
|
1865
|
+
params = self.omit(params, ['code'])
|
1862
1866
|
response = None
|
1863
1867
|
request = {}
|
1864
1868
|
if (type != 'spot') and (type != 'swap'):
|
1865
1869
|
raise BadRequest(self.id + ' does not support ' + type + ' markets, only spot and swap')
|
1866
1870
|
if type == 'swap':
|
1867
1871
|
settle = None
|
1868
|
-
settle, params = self.handle_option_and_params(params, 'fetchBalance', 'settle')
|
1872
|
+
settle, params = self.handle_option_and_params(params, 'fetchBalance', 'settle', 'USDT')
|
1869
1873
|
if code is not None or settle is not None:
|
1870
1874
|
coin = None
|
1871
1875
|
if code is not None:
|
@@ -2623,7 +2627,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
2623
2627
|
request['baseQtyEV'] = finalQty
|
2624
2628
|
elif amount is not None:
|
2625
2629
|
if isUSDTSettled:
|
2626
|
-
request['
|
2630
|
+
request['orderQtyRq'] = self.amount_to_precision(market['symbol'], amount)
|
2627
2631
|
else:
|
2628
2632
|
request['baseQtyEV'] = self.to_ev(amount, market)
|
2629
2633
|
stopPrice = self.safe_string_2(params, 'stopPx', 'stopPrice')
|
ccxt/poloniex.py
CHANGED
@@ -60,6 +60,7 @@ class poloniex(Exchange, ImplicitAPI):
|
|
60
60
|
'fetchDepositsWithdrawals': True,
|
61
61
|
'fetchDepositWithdrawFee': 'emulated',
|
62
62
|
'fetchDepositWithdrawFees': True,
|
63
|
+
'fetchFundingRate': False,
|
63
64
|
'fetchMarginMode': False,
|
64
65
|
'fetchMarkets': True,
|
65
66
|
'fetchMyTrades': True,
|
ccxt/pro/__init__.py
CHANGED
ccxt/pro/bequant.py
CHANGED
@@ -5,11 +5,17 @@
|
|
5
5
|
|
6
6
|
from ccxt.pro.hitbtc import hitbtc
|
7
7
|
|
8
|
+
import ccxt.async_support.bequant as bequantRest
|
9
|
+
|
8
10
|
|
9
11
|
class bequant(hitbtc):
|
10
12
|
|
11
13
|
def describe(self):
|
12
|
-
|
14
|
+
# eslint-disable-next-line new-cap
|
15
|
+
restInstance = bequantRest()
|
16
|
+
restDescribe = restInstance.describe()
|
17
|
+
extended = self.deep_extend(super(bequant, self).describe(), restDescribe)
|
18
|
+
return self.deep_extend(extended, {
|
13
19
|
'id': 'bequant',
|
14
20
|
'name': 'Bequant',
|
15
21
|
'countries': ['MT'], # Malta
|
ccxt/pro/binance.py
CHANGED
@@ -49,7 +49,7 @@ class binance(ccxt.async_support.binance):
|
|
49
49
|
'ws': {
|
50
50
|
'spot': 'wss://testnet.binance.vision/ws',
|
51
51
|
'margin': 'wss://testnet.binance.vision/ws',
|
52
|
-
'future': 'wss://
|
52
|
+
'future': 'wss://fstream.binancefuture.com/ws',
|
53
53
|
'delivery': 'wss://dstream.binancefuture.com/ws',
|
54
54
|
'ws': 'wss://testnet.binance.vision/ws-api/v3',
|
55
55
|
},
|
@@ -1811,12 +1811,13 @@ class binance(ccxt.async_support.binance):
|
|
1811
1811
|
|
1812
1812
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1813
1813
|
"""
|
1814
|
-
:see: https://binance-docs.github.io/apidocs/spot/en/#payload-order-update
|
1815
1814
|
watches information on multiple orders made by the user
|
1816
|
-
:
|
1815
|
+
:see: https://binance-docs.github.io/apidocs/spot/en/#payload-order-update
|
1816
|
+
:param str symbol: unified market symbol of the market the orders were made in
|
1817
1817
|
:param int [since]: the earliest time in ms to fetch orders for
|
1818
1818
|
:param int [limit]: the maximum number of order structures to retrieve
|
1819
1819
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1820
|
+
:param str|None [params.marginMode]: 'cross' or 'isolated', for spot margin
|
1820
1821
|
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1821
1822
|
"""
|
1822
1823
|
await self.load_markets()
|
@@ -1836,8 +1837,10 @@ class binance(ccxt.async_support.binance):
|
|
1836
1837
|
type = 'delivery'
|
1837
1838
|
params = self.extend(params, {'type': type, 'symbol': symbol}) # needed inside authenticate for isolated margin
|
1838
1839
|
await self.authenticate(params)
|
1840
|
+
marginMode = None
|
1841
|
+
marginMode, params = self.handle_margin_mode_and_params('watchOrders', params)
|
1839
1842
|
urlType = type
|
1840
|
-
if type == 'margin':
|
1843
|
+
if (type == 'margin') or ((type == 'spot') and (marginMode is not None)):
|
1841
1844
|
urlType = 'spot' # spot-margin shares the same stream spot
|
1842
1845
|
url = self.urls['api']['ws'][urlType] + '/' + self.options[type]['listenKey']
|
1843
1846
|
client = self.client(url)
|