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/async_support/bybit.py
CHANGED
@@ -53,7 +53,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
53
53
|
'closeAllPositions': False,
|
54
54
|
'closePosition': False,
|
55
55
|
'createMarketBuyOrderWithCost': True,
|
56
|
-
'createMarketSellOrderWithCost':
|
56
|
+
'createMarketSellOrderWithCost': True,
|
57
57
|
'createOrder': True,
|
58
58
|
'createOrders': True,
|
59
59
|
'createOrderWithTakeProfitAndStopLoss': True,
|
@@ -973,7 +973,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
973
973
|
'fetchMarkets': ['spot', 'linear', 'inverse', 'option'],
|
974
974
|
'enableUnifiedMargin': None,
|
975
975
|
'enableUnifiedAccount': None,
|
976
|
-
'createMarketBuyOrderRequiresPrice': True,
|
976
|
+
'createMarketBuyOrderRequiresPrice': True, # only True for classic accounts
|
977
977
|
'createUnifiedMarginAccount': False,
|
978
978
|
'defaultType': 'swap', # 'swap', 'future', 'option', 'spot'
|
979
979
|
'defaultSubType': 'linear', # 'linear', 'inverse'
|
@@ -3302,8 +3302,26 @@ class bybit(Exchange, ImplicitAPI):
|
|
3302
3302
|
market = self.market(symbol)
|
3303
3303
|
if not market['spot']:
|
3304
3304
|
raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
|
3305
|
-
|
3306
|
-
|
3305
|
+
return await self.create_order(symbol, 'market', 'buy', cost, 1, params)
|
3306
|
+
|
3307
|
+
async def create_market_sell_order_with_cost(self, symbol: str, cost, params={}):
|
3308
|
+
"""
|
3309
|
+
:see: https://bybit-exchange.github.io/docs/v5/order/create-order
|
3310
|
+
create a market sell order by providing the symbol and cost
|
3311
|
+
:param str symbol: unified symbol of the market to create an order in
|
3312
|
+
:param float cost: how much you want to trade in units of the quote currency
|
3313
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3314
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
3315
|
+
"""
|
3316
|
+
await self.load_markets()
|
3317
|
+
types = await self.is_unified_enabled()
|
3318
|
+
enableUnifiedAccount = types[1]
|
3319
|
+
if not enableUnifiedAccount:
|
3320
|
+
raise NotSupported(self.id + ' createMarketSellOrderWithCost() supports UTA accounts only')
|
3321
|
+
market = self.market(symbol)
|
3322
|
+
if not market['spot']:
|
3323
|
+
raise NotSupported(self.id + ' createMarketSellOrderWithCost() supports spot orders only')
|
3324
|
+
return await self.create_order(symbol, 'market', 'sell', cost, 1, params)
|
3307
3325
|
|
3308
3326
|
async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
|
3309
3327
|
"""
|
@@ -3344,7 +3362,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
3344
3362
|
return await self.create_usdc_order(symbol, type, side, amount, price, params)
|
3345
3363
|
trailingAmount = self.safe_string_2(params, 'trailingAmount', 'trailingStop')
|
3346
3364
|
isTrailingAmountOrder = trailingAmount is not None
|
3347
|
-
orderRequest = self.create_order_request(symbol, type, side, amount, price, params)
|
3365
|
+
orderRequest = self.create_order_request(symbol, type, side, amount, price, params, enableUnifiedAccount)
|
3348
3366
|
response = None
|
3349
3367
|
if isTrailingAmountOrder:
|
3350
3368
|
response = await self.privatePostV5PositionTradingStop(orderRequest)
|
@@ -3365,7 +3383,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
3365
3383
|
order = self.safe_value(response, 'result', {})
|
3366
3384
|
return self.parse_order(order, market)
|
3367
3385
|
|
3368
|
-
def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
|
3386
|
+
def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}, isUTA=True):
|
3369
3387
|
market = self.market(symbol)
|
3370
3388
|
symbol = market['symbol']
|
3371
3389
|
lowerCaseType = type.lower()
|
@@ -3404,12 +3422,31 @@ class bybit(Exchange, ImplicitAPI):
|
|
3404
3422
|
request['category'] = 'inverse'
|
3405
3423
|
elif market['option']:
|
3406
3424
|
request['category'] = 'option'
|
3407
|
-
|
3425
|
+
cost = self.safe_string(params, 'cost')
|
3426
|
+
params = self.omit(params, 'cost')
|
3427
|
+
# if the cost is inferable, let's keep the old logic and ignore marketUnit, to minimize the impact of the changes
|
3428
|
+
isMarketBuyAndCostInferable = (lowerCaseType == 'market') and (side == 'buy') and ((price is not None) or (cost is not None))
|
3429
|
+
if market['spot'] and (type == 'market') and isUTA and not isMarketBuyAndCostInferable:
|
3430
|
+
# UTA account can specify the cost of the order on both sides
|
3431
|
+
if (cost is not None) or (price is not None):
|
3432
|
+
request['marketUnit'] = 'quoteCoin'
|
3433
|
+
orderCost = None
|
3434
|
+
if cost is not None:
|
3435
|
+
orderCost = cost
|
3436
|
+
else:
|
3437
|
+
amountString = self.number_to_string(amount)
|
3438
|
+
priceString = self.number_to_string(price)
|
3439
|
+
quoteAmount = Precise.string_mul(amountString, priceString)
|
3440
|
+
orderCost = quoteAmount
|
3441
|
+
request['qty'] = self.cost_to_precision(symbol, orderCost)
|
3442
|
+
else:
|
3443
|
+
request['marketUnit'] = 'baseCoin'
|
3444
|
+
request['qty'] = self.amount_to_precision(symbol, amount)
|
3445
|
+
elif market['spot'] and (type == 'market') and (side == 'buy'):
|
3446
|
+
# classic accounts
|
3408
3447
|
# for market buy it requires the amount of quote currency to spend
|
3409
3448
|
createMarketBuyOrderRequiresPrice = True
|
3410
3449
|
createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
|
3411
|
-
cost = self.safe_number(params, 'cost')
|
3412
|
-
params = self.omit(params, 'cost')
|
3413
3450
|
if createMarketBuyOrderRequiresPrice:
|
3414
3451
|
if (price is None) and (cost is None):
|
3415
3452
|
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')
|
@@ -3505,6 +3542,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
3505
3542
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
3506
3543
|
"""
|
3507
3544
|
await self.load_markets()
|
3545
|
+
accounts = await self.is_unified_enabled()
|
3546
|
+
isUta = accounts[1]
|
3508
3547
|
ordersRequests = []
|
3509
3548
|
orderSymbols = []
|
3510
3549
|
for i in range(0, len(orders)):
|
@@ -3516,7 +3555,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
3516
3555
|
amount = self.safe_value(rawOrder, 'amount')
|
3517
3556
|
price = self.safe_value(rawOrder, 'price')
|
3518
3557
|
orderParams = self.safe_value(rawOrder, 'params', {})
|
3519
|
-
orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
|
3558
|
+
orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams, isUta)
|
3520
3559
|
ordersRequests.append(orderRequest)
|
3521
3560
|
symbols = self.market_symbols(orderSymbols, None, False, True, True)
|
3522
3561
|
market = self.market(symbols[0])
|
@@ -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/async_support/coinex.py
CHANGED
@@ -1531,8 +1531,9 @@ class coinex(Exchange, ImplicitAPI):
|
|
1531
1531
|
"""
|
1532
1532
|
marketType = None
|
1533
1533
|
marketType, params = self.handle_market_type_and_params('fetchBalance', None, params)
|
1534
|
-
|
1535
|
-
|
1534
|
+
marginMode = None
|
1535
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchBalance', params)
|
1536
|
+
marketType = 'margin' if (marginMode is not None) else marketType
|
1536
1537
|
params = self.omit(params, 'margin')
|
1537
1538
|
if marketType == 'margin':
|
1538
1539
|
return await self.fetch_margin_balance(params)
|
@@ -2006,8 +2007,9 @@ class coinex(Exchange, ImplicitAPI):
|
|
2006
2007
|
if timeInForceRaw is not None:
|
2007
2008
|
request['option'] = timeInForceRaw # exchange takes 'IOC' and 'FOK'
|
2008
2009
|
accountId = self.safe_integer(params, 'account_id')
|
2009
|
-
|
2010
|
-
|
2010
|
+
marginMode = None
|
2011
|
+
marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
|
2012
|
+
if marginMode is not None:
|
2011
2013
|
if accountId is None:
|
2012
2014
|
raise BadRequest(self.id + ' createOrder() requires an account_id parameter for margin orders')
|
2013
2015
|
request['account_id'] = accountId
|
@@ -2474,9 +2476,10 @@ class coinex(Exchange, ImplicitAPI):
|
|
2474
2476
|
'market': market['id'],
|
2475
2477
|
}
|
2476
2478
|
accountId = self.safe_integer(params, 'account_id')
|
2477
|
-
|
2479
|
+
marginMode = None
|
2480
|
+
marginMode, params = self.handle_margin_mode_and_params('cancelOrder', params)
|
2478
2481
|
clientOrderId = self.safe_string_2(params, 'client_id', 'clientOrderId')
|
2479
|
-
if
|
2482
|
+
if marginMode is not None:
|
2480
2483
|
if accountId is None:
|
2481
2484
|
raise BadRequest(self.id + ' cancelOrder() requires an account_id parameter for margin orders')
|
2482
2485
|
request['account_id'] = accountId
|
@@ -2815,8 +2818,9 @@ class coinex(Exchange, ImplicitAPI):
|
|
2815
2818
|
request['market'] = market['id']
|
2816
2819
|
marketType, query = self.handle_market_type_and_params('fetchOrdersByStatus', market, params)
|
2817
2820
|
accountId = self.safe_integer(params, 'account_id')
|
2818
|
-
|
2819
|
-
|
2821
|
+
marginMode = None
|
2822
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchOrdersByStatus', params)
|
2823
|
+
if marginMode is not None:
|
2820
2824
|
if accountId is None:
|
2821
2825
|
raise BadRequest(self.id + ' fetchOpenOrders() and fetchClosedOrders() require an account_id parameter for margin orders')
|
2822
2826
|
request['account_id'] = accountId
|
@@ -3180,8 +3184,9 @@ class coinex(Exchange, ImplicitAPI):
|
|
3180
3184
|
raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument for non-spot markets')
|
3181
3185
|
swap = (type == 'swap')
|
3182
3186
|
accountId = self.safe_integer(params, 'account_id')
|
3183
|
-
|
3184
|
-
|
3187
|
+
marginMode = None
|
3188
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
|
3189
|
+
if marginMode is not None:
|
3185
3190
|
if accountId is None:
|
3186
3191
|
raise BadRequest(self.id + ' fetchMyTrades() requires an account_id parameter for margin trades')
|
3187
3192
|
request['account_id'] = accountId
|
@@ -4419,9 +4424,10 @@ class coinex(Exchange, ImplicitAPI):
|
|
4419
4424
|
else:
|
4420
4425
|
request['limit'] = 100
|
4421
4426
|
params = self.omit(params, 'page')
|
4422
|
-
|
4427
|
+
marginMode = None
|
4428
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchTransfers', params)
|
4423
4429
|
response = None
|
4424
|
-
if
|
4430
|
+
if marginMode is not None:
|
4425
4431
|
response = await self.privateGetMarginTransferHistory(self.extend(request, params))
|
4426
4432
|
else:
|
4427
4433
|
response = await self.privateGetContractTransferHistory(self.extend(request, params))
|
@@ -4968,6 +4974,22 @@ class coinex(Exchange, ImplicitAPI):
|
|
4968
4974
|
depositWithdrawFees[code] = self.assign_default_deposit_withdraw_fees(depositWithdrawFees[code], currency)
|
4969
4975
|
return depositWithdrawFees
|
4970
4976
|
|
4977
|
+
def handle_margin_mode_and_params(self, methodName, params={}, defaultValue=None):
|
4978
|
+
"""
|
4979
|
+
* @ignore
|
4980
|
+
marginMode specified by params["marginMode"], self.options["marginMode"], self.options["defaultMarginMode"], params["margin"] = True or self.options["defaultType"] = 'margin'
|
4981
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
4982
|
+
:returns Array: the marginMode in lowercase
|
4983
|
+
"""
|
4984
|
+
defaultType = self.safe_string(self.options, 'defaultType')
|
4985
|
+
isMargin = self.safe_value(params, 'margin', False)
|
4986
|
+
marginMode = None
|
4987
|
+
marginMode, params = super(coinex, self).handle_margin_mode_and_params(methodName, params, defaultValue)
|
4988
|
+
if marginMode is None:
|
4989
|
+
if (defaultType == 'margin') or (isMargin is True):
|
4990
|
+
marginMode = 'isolated'
|
4991
|
+
return [marginMode, params]
|
4992
|
+
|
4971
4993
|
def nonce(self):
|
4972
4994
|
return self.milliseconds()
|
4973
4995
|
|
ccxt/async_support/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
|
async def fetch_time(self, params={}):
|
419
564
|
"""
|
420
565
|
fetches the current integer timestamp in milliseconds from the exchange server
|
ccxt/async_support/gate.py
CHANGED
@@ -548,6 +548,7 @@ class gate(Exchange, ImplicitAPI):
|
|
548
548
|
'multi_collateral/currency_quota': 20 / 15,
|
549
549
|
'multi_collateral/currencies': 20 / 15,
|
550
550
|
'multi_collateral/ltv': 20 / 15,
|
551
|
+
'multi_collateral/fixed_rate': 20 / 15,
|
551
552
|
},
|
552
553
|
'post': {
|
553
554
|
'collateral/orders': 20 / 15,
|
@@ -5169,7 +5170,7 @@ class gate(Exchange, ImplicitAPI):
|
|
5169
5170
|
retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
|
5170
5171
|
:see: https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts
|
5171
5172
|
:see: https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts-2
|
5172
|
-
:param str[]
|
5173
|
+
:param str[] [symbols]: list of unified market symbols
|
5173
5174
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
5174
5175
|
:returns dict: a dictionary of `leverage tiers structures <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`, indexed by market symbols
|
5175
5176
|
"""
|
@@ -5307,6 +5308,32 @@ class gate(Exchange, ImplicitAPI):
|
|
5307
5308
|
#
|
5308
5309
|
return self.parse_market_leverage_tiers(response, market)
|
5309
5310
|
|
5311
|
+
def parse_emulated_leverage_tiers(self, info, market=None):
|
5312
|
+
maintenanceMarginUnit = self.safe_string(info, 'maintenance_rate') # '0.005',
|
5313
|
+
leverageMax = self.safe_string(info, 'leverage_max') # '100',
|
5314
|
+
riskLimitStep = self.safe_string(info, 'risk_limit_step') # '1000000',
|
5315
|
+
riskLimitMax = self.safe_string(info, 'risk_limit_max') # '16000000',
|
5316
|
+
initialMarginUnit = Precise.string_div('1', leverageMax)
|
5317
|
+
maintenanceMarginRate = maintenanceMarginUnit
|
5318
|
+
initialMarginRatio = initialMarginUnit
|
5319
|
+
floor = '0'
|
5320
|
+
tiers = []
|
5321
|
+
while(Precise.string_lt(floor, riskLimitMax)):
|
5322
|
+
cap = Precise.string_add(floor, riskLimitStep)
|
5323
|
+
tiers.append({
|
5324
|
+
'tier': self.parse_number(Precise.string_div(cap, riskLimitStep)),
|
5325
|
+
'currency': self.safe_string(market, 'settle'),
|
5326
|
+
'minNotional': self.parse_number(floor),
|
5327
|
+
'maxNotional': self.parse_number(cap),
|
5328
|
+
'maintenanceMarginRate': self.parse_number(maintenanceMarginRate),
|
5329
|
+
'maxLeverage': self.parse_number(Precise.string_div('1', initialMarginRatio)),
|
5330
|
+
'info': info,
|
5331
|
+
})
|
5332
|
+
maintenanceMarginRate = Precise.string_add(maintenanceMarginRate, maintenanceMarginUnit)
|
5333
|
+
initialMarginRatio = Precise.string_add(initialMarginRatio, initialMarginUnit)
|
5334
|
+
floor = cap
|
5335
|
+
return tiers
|
5336
|
+
|
5310
5337
|
def parse_market_leverage_tiers(self, info, market: Market = None):
|
5311
5338
|
#
|
5312
5339
|
# [
|
@@ -5319,6 +5346,8 @@ class gate(Exchange, ImplicitAPI):
|
|
5319
5346
|
# }
|
5320
5347
|
# ]
|
5321
5348
|
#
|
5349
|
+
if not isinstance(info, list):
|
5350
|
+
return self.parse_emulated_leverage_tiers(info, market)
|
5322
5351
|
minNotional = 0
|
5323
5352
|
tiers = []
|
5324
5353
|
for i in range(0, len(info)):
|
ccxt/async_support/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/async_support/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/async_support/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
|
async 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
|
await 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/async_support/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/async_support/woo.py
CHANGED
@@ -66,7 +66,7 @@ class woo(Exchange, ImplicitAPI):
|
|
66
66
|
'fetchClosedOrder': False,
|
67
67
|
'fetchClosedOrders': False,
|
68
68
|
'fetchCurrencies': True,
|
69
|
-
'fetchDepositAddress':
|
69
|
+
'fetchDepositAddress': True,
|
70
70
|
'fetchDeposits': True,
|
71
71
|
'fetchDepositsWithdrawals': True,
|
72
72
|
'fetchFundingHistory': True,
|
ccxt/base/exchange.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
__version__ = '4.2.
|
7
|
+
__version__ = '4.2.22'
|
8
8
|
|
9
9
|
# -----------------------------------------------------------------------------
|
10
10
|
|
@@ -2902,6 +2902,12 @@ class Exchange(object):
|
|
2902
2902
|
message = '. If you want to build OHLCV candles from trade executions data, visit https://github.com/ccxt/ccxt/tree/master/examples/ and see "build-ohlcv-bars" file'
|
2903
2903
|
raise NotSupported(self.id + ' fetchOHLCV() is not supported yet' + message)
|
2904
2904
|
|
2905
|
+
def fetch_ohlcv_ws(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
|
2906
|
+
message = ''
|
2907
|
+
if self.has['fetchTradesWs']:
|
2908
|
+
message = '. If you want to build OHLCV candles from trade executions data, visit https://github.com/ccxt/ccxt/tree/master/examples/ and see "build-ohlcv-bars" file'
|
2909
|
+
raise NotSupported(self.id + ' fetchOHLCVWs() is not supported yet. Try using fetchOHLCV instead.' + message)
|
2910
|
+
|
2905
2911
|
def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
|
2906
2912
|
raise NotSupported(self.id + ' watchOHLCV() is not supported yet')
|
2907
2913
|
|
@@ -3198,7 +3204,7 @@ class Exchange(object):
|
|
3198
3204
|
for i in range(0, len(response)):
|
3199
3205
|
item = response[i]
|
3200
3206
|
id = self.safe_string(item, marketIdKey)
|
3201
|
-
market = self.safe_market(id, None, None,
|
3207
|
+
market = self.safe_market(id, None, None, 'swap')
|
3202
3208
|
symbol = market['symbol']
|
3203
3209
|
contract = self.safe_value(market, 'contract', False)
|
3204
3210
|
if contract and ((symbols is None) or self.in_array(symbol, symbols)):
|
@@ -4050,9 +4056,6 @@ class Exchange(object):
|
|
4050
4056
|
def watch_my_trades(self, symbol: str = None, since: Int = None, limit: Int = None, params={}):
|
4051
4057
|
raise NotSupported(self.id + ' watchMyTrades() is not supported yet')
|
4052
4058
|
|
4053
|
-
def fetch_ohlcv_ws(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
|
4054
|
-
raise NotSupported(self.id + ' fetchOHLCVWs() is not supported yet')
|
4055
|
-
|
4056
4059
|
def fetch_greeks(self, symbol: str, params={}):
|
4057
4060
|
raise NotSupported(self.id + ' fetchGreeks() is not supported yet')
|
4058
4061
|
|
@@ -4070,9 +4073,15 @@ class Exchange(object):
|
|
4070
4073
|
def fetch_deposits(self, code: str = None, since: Int = None, limit: Int = None, params={}):
|
4071
4074
|
raise NotSupported(self.id + ' fetchDeposits() is not supported yet')
|
4072
4075
|
|
4076
|
+
def fetch_deposits_ws(self, code: str = None, since: Int = None, limit: Int = None, params={}):
|
4077
|
+
raise NotSupported(self.id + ' fetchDepositsWs() is not supported yet')
|
4078
|
+
|
4073
4079
|
def fetch_withdrawals(self, code: str = None, since: Int = None, limit: Int = None, params={}):
|
4074
4080
|
raise NotSupported(self.id + ' fetchWithdrawals() is not supported yet')
|
4075
4081
|
|
4082
|
+
def fetch_withdrawals_ws(self, code: str = None, since: Int = None, limit: Int = None, params={}):
|
4083
|
+
raise NotSupported(self.id + ' fetchWithdrawalsWs() is not supported yet')
|
4084
|
+
|
4076
4085
|
def fetch_open_interest(self, symbol: str, params={}):
|
4077
4086
|
raise NotSupported(self.id + ' fetchOpenInterest() is not supported yet')
|
4078
4087
|
|
@@ -4488,6 +4497,9 @@ class Exchange(object):
|
|
4488
4497
|
def fetch_trading_fees(self, params={}):
|
4489
4498
|
raise NotSupported(self.id + ' fetchTradingFees() is not supported yet')
|
4490
4499
|
|
4500
|
+
def fetch_trading_fees_ws(self, params={}):
|
4501
|
+
raise NotSupported(self.id + ' fetchTradingFeesWs() is not supported yet')
|
4502
|
+
|
4491
4503
|
def fetch_trading_fee(self, symbol: str, params={}):
|
4492
4504
|
if not self.has['fetchTradingFees']:
|
4493
4505
|
raise NotSupported(self.id + ' fetchTradingFee() is not supported yet')
|