ccxt 4.2.58__py2.py3-none-any.whl → 4.2.60__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.

Files changed (68) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/blofin.py +1 -0
  3. ccxt/abstract/kraken.py +37 -37
  4. ccxt/abstract/wazirx.py +6 -1
  5. ccxt/ascendex.py +10 -12
  6. ccxt/async_support/__init__.py +1 -1
  7. ccxt/async_support/ascendex.py +10 -12
  8. ccxt/async_support/base/exchange.py +1 -1
  9. ccxt/async_support/binance.py +2 -2
  10. ccxt/async_support/bingx.py +40 -4
  11. ccxt/async_support/bitfinex2.py +20 -3
  12. ccxt/async_support/bitget.py +8 -3
  13. ccxt/async_support/bitmart.py +40 -23
  14. ccxt/async_support/bitmex.py +1 -1
  15. ccxt/async_support/blofin.py +53 -3
  16. ccxt/async_support/coinbase.py +21 -12
  17. ccxt/async_support/hitbtc.py +1 -1
  18. ccxt/async_support/htx.py +3 -1
  19. ccxt/async_support/kraken.py +42 -39
  20. ccxt/async_support/kucoinfutures.py +1 -0
  21. ccxt/async_support/lbank.py +1 -1
  22. ccxt/async_support/mexc.py +1 -1
  23. ccxt/async_support/okx.py +1 -1
  24. ccxt/async_support/phemex.py +1 -1
  25. ccxt/async_support/wazirx.py +6 -1
  26. ccxt/async_support/woo.py +148 -76
  27. ccxt/base/exchange.py +3 -1
  28. ccxt/binance.py +2 -2
  29. ccxt/bingx.py +40 -4
  30. ccxt/bitfinex2.py +20 -3
  31. ccxt/bitget.py +8 -3
  32. ccxt/bitmart.py +40 -23
  33. ccxt/bitmex.py +1 -1
  34. ccxt/blofin.py +53 -3
  35. ccxt/coinbase.py +21 -12
  36. ccxt/hitbtc.py +1 -1
  37. ccxt/htx.py +3 -1
  38. ccxt/kraken.py +42 -39
  39. ccxt/kucoinfutures.py +1 -0
  40. ccxt/lbank.py +1 -1
  41. ccxt/mexc.py +1 -1
  42. ccxt/okx.py +1 -1
  43. ccxt/phemex.py +1 -1
  44. ccxt/pro/__init__.py +1 -1
  45. ccxt/pro/binance.py +12 -3
  46. ccxt/pro/bitfinex2.py +1 -1
  47. ccxt/pro/bitget.py +1 -1
  48. ccxt/pro/bitmart.py +44 -78
  49. ccxt/pro/bitvavo.py +1 -1
  50. ccxt/pro/bybit.py +1 -1
  51. ccxt/pro/coinex.py +1 -1
  52. ccxt/pro/cryptocom.py +1 -1
  53. ccxt/pro/deribit.py +188 -84
  54. ccxt/pro/gate.py +1 -1
  55. ccxt/pro/independentreserve.py +1 -1
  56. ccxt/pro/kraken.py +1 -1
  57. ccxt/pro/kucoinfutures.py +1 -1
  58. ccxt/pro/mexc.py +5 -4
  59. ccxt/pro/okx.py +1 -1
  60. ccxt/pro/woo.py +1 -1
  61. ccxt/test/test_async.py +4 -4
  62. ccxt/test/test_sync.py +4 -4
  63. ccxt/wazirx.py +6 -1
  64. ccxt/woo.py +148 -76
  65. {ccxt-4.2.58.dist-info → ccxt-4.2.60.dist-info}/METADATA +4 -4
  66. {ccxt-4.2.58.dist-info → ccxt-4.2.60.dist-info}/RECORD +68 -68
  67. {ccxt-4.2.58.dist-info → ccxt-4.2.60.dist-info}/WHEEL +0 -0
  68. {ccxt-4.2.58.dist-info → ccxt-4.2.60.dist-info}/top_level.txt +0 -0
ccxt/bitget.py CHANGED
@@ -2846,8 +2846,13 @@ class bitget(Exchange, ImplicitAPI):
2846
2846
  currencyCode = self.safe_currency_code(self.safe_string(feeStructure, 'feeCoin'))
2847
2847
  fee = {
2848
2848
  'currency': currencyCode,
2849
- 'cost': Precise.string_abs(self.safe_string(feeStructure, 'totalFee')),
2850
2849
  }
2850
+ feeCostString = self.safe_string(feeStructure, 'totalFee')
2851
+ deduction = self.safe_string(feeStructure, 'deduction') is True if 'yes' else False
2852
+ if deduction:
2853
+ fee['cost'] = feeCostString
2854
+ else:
2855
+ fee['cost'] = Precise.string_neg(feeCostString)
2851
2856
  return self.safe_trade({
2852
2857
  'info': trade,
2853
2858
  'id': self.safe_string(trade, 'tradeId'),
@@ -3865,7 +3870,7 @@ class bitget(Exchange, ImplicitAPI):
3865
3870
  :see: https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Place-Order
3866
3871
  :param str symbol: unified symbol of the market to create an order in
3867
3872
  :param str type: 'market' or 'limit'
3868
- :param str side: 'buy' or 'sell' or 'open_long' or 'open_short' or 'close_long' or 'close_short'
3873
+ :param str side: 'buy' or 'sell'
3869
3874
  :param float amount: how much you want to trade in units of the base currency
3870
3875
  :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
3871
3876
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -4268,7 +4273,7 @@ class bitget(Exchange, ImplicitAPI):
4268
4273
  params = self.omit(params, ['stopPrice', 'triggerType', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit', 'clientOrderId', 'trailingTriggerPrice', 'trailingPercent'])
4269
4274
  response = None
4270
4275
  if market['spot']:
4271
- editMarketBuyOrderRequiresPrice = self.safe_value(self.options, 'editMarketBuyOrderRequiresPrice', True)
4276
+ editMarketBuyOrderRequiresPrice = self.safe_bool(self.options, 'editMarketBuyOrderRequiresPrice', True)
4272
4277
  if editMarketBuyOrderRequiresPrice and isMarketOrder and (side == 'buy'):
4273
4278
  if price is None:
4274
4279
  raise InvalidOrder(self.id + ' editOrder() requires price argument for market buy orders on spot markets to calculate the total amount to spend(amount * price), alternatively set the editMarketBuyOrderRequiresPrice option to False and pass in the cost to spend into the amount parameter')
ccxt/bitmart.py CHANGED
@@ -530,6 +530,7 @@ class bitmart(Exchange, ImplicitAPI):
530
530
  },
531
531
  'networks': {
532
532
  'ERC20': 'ERC20',
533
+ 'SOL': 'SOL',
533
534
  'BTC': 'BTC',
534
535
  'TRC20': 'TRC20',
535
536
  # todo: should be TRX after unification
@@ -552,7 +553,6 @@ class bitmart(Exchange, ImplicitAPI):
552
553
  'FIO': 'FIO',
553
554
  'SCRT': 'SCRT',
554
555
  'IOTX': 'IOTX',
555
- 'SOL': 'SOL',
556
556
  'ALGO': 'ALGO',
557
557
  'ATOM': 'ATOM',
558
558
  'DOT': 'DOT',
@@ -2886,6 +2886,7 @@ class bitmart(Exchange, ImplicitAPI):
2886
2886
  def fetch_deposit_address(self, code: str, params={}):
2887
2887
  """
2888
2888
  fetch the deposit address for a currency associated with self account
2889
+ :see: https://developer-pro.bitmart.com/en/spot/#deposit-address-keyed
2889
2890
  :param str code: unified currency code
2890
2891
  :param dict [params]: extra parameters specific to the exchange API endpoint
2891
2892
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
@@ -2906,39 +2907,55 @@ class bitmart(Exchange, ImplicitAPI):
2906
2907
  params = self.omit(params, 'network')
2907
2908
  response = self.privateGetAccountV1DepositAddress(self.extend(request, params))
2908
2909
  #
2909
- # {
2910
- # "message":"OK",
2911
- # "code":1000,
2912
- # "trace":"0e6edd79-f77f-4251-abe5-83ba75d06c1a",
2913
- # "data":{
2914
- # "currency":"USDT-TRC20",
2915
- # "chain":"USDT-TRC20",
2916
- # "address":"TGR3ghy2b5VLbyAYrmiE15jasR6aPHTvC5",
2917
- # "address_memo":""
2918
- # }
2919
- # }
2910
+ # {
2911
+ # "message": "OK",
2912
+ # "code": 1000,
2913
+ # "trace": "0e6edd79-f77f-4251-abe5-83ba75d06c1a",
2914
+ # "data": {
2915
+ # currency: 'ETH',
2916
+ # chain: 'Ethereum',
2917
+ # address: '0x99B5EEc2C520f86F0F62F05820d28D05D36EccCf',
2918
+ # address_memo: ''
2919
+ # }
2920
+ # }
2920
2921
  #
2921
2922
  data = self.safe_value(response, 'data', {})
2922
- address = self.safe_string(data, 'address')
2923
- tag = self.safe_string(data, 'address_memo')
2924
- chain = self.safe_string(data, 'chain')
2923
+ return self.parse_deposit_address(data, currency)
2924
+
2925
+ def parse_deposit_address(self, depositAddress, currency=None):
2926
+ #
2927
+ # {
2928
+ # currency: 'ETH',
2929
+ # chain: 'Ethereum',
2930
+ # address: '0x99B5EEc2C520f86F0F62F05820d28D05D36EccCf',
2931
+ # address_memo: ''
2932
+ # }
2933
+ #
2934
+ currencyId = self.safe_string(depositAddress, 'currency')
2935
+ address = self.safe_string(depositAddress, 'address')
2936
+ chain = self.safe_string(depositAddress, 'chain')
2925
2937
  network = None
2938
+ currency = self.safe_currency(currencyId, currency)
2926
2939
  if chain is not None:
2927
2940
  parts = chain.split('-')
2928
- networkId = self.safe_string(parts, 1)
2929
- network = self.safe_network(networkId)
2941
+ partsLength = len(parts)
2942
+ networkId = self.safe_string(parts, partsLength - 1)
2943
+ network = self.safe_network_code(networkId, currency)
2930
2944
  self.check_address(address)
2931
2945
  return {
2932
- 'currency': code,
2946
+ 'info': depositAddress,
2947
+ 'currency': self.safe_string(currency, 'code'),
2933
2948
  'address': address,
2934
- 'tag': tag,
2949
+ 'tag': self.safe_string(depositAddress, 'address_memo'),
2935
2950
  'network': network,
2936
- 'info': response,
2937
2951
  }
2938
2952
 
2939
- def safe_network(self, networkId):
2940
- # TODO: parse
2941
- return networkId
2953
+ def safe_network_code(self, networkId, currency=None):
2954
+ name = self.safe_string(currency, 'name')
2955
+ if networkId == name:
2956
+ code = self.safe_string(currency, 'code')
2957
+ return code
2958
+ return self.network_id_to_code(networkId)
2942
2959
 
2943
2960
  def withdraw(self, code: str, amount: float, address, tag=None, params={}):
2944
2961
  """
ccxt/bitmex.py CHANGED
@@ -1436,7 +1436,7 @@ class bitmex(Exchange, ImplicitAPI):
1436
1436
  params = self.omit(params, ['until'])
1437
1437
  request['endTime'] = self.iso8601(until)
1438
1438
  duration = self.parse_timeframe(timeframe) * 1000
1439
- fetchOHLCVOpenTimestamp = self.safe_value(self.options, 'fetchOHLCVOpenTimestamp', True)
1439
+ fetchOHLCVOpenTimestamp = self.safe_bool(self.options, 'fetchOHLCVOpenTimestamp', True)
1440
1440
  # if since is not set, they will return candles starting from 2017-01-01
1441
1441
  if since is not None:
1442
1442
  timestamp = since
ccxt/blofin.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.blofin import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Leverage, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Balances, Currency, Int, Leverage, Leverages, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
@@ -89,6 +89,7 @@ class blofin(Exchange, ImplicitAPI):
89
89
  'fetchLedger': True,
90
90
  'fetchLedgerEntry': None,
91
91
  'fetchLeverage': True,
92
+ 'fetchLeverages': True,
92
93
  'fetchLeverageTiers': False,
93
94
  'fetchMarketLeverageTiers': False,
94
95
  'fetchMarkets': True,
@@ -193,6 +194,7 @@ class blofin(Exchange, ImplicitAPI):
193
194
  'account/balance': 1,
194
195
  'account/positions': 1,
195
196
  'account/leverage-info': 1,
197
+ 'account/batch-leverage-info': 1,
196
198
  'trade/orders-tpsl-pending': 1,
197
199
  'trade/orders-history': 1,
198
200
  'trade/orders-tpsl-history': 1,
@@ -491,7 +493,7 @@ class blofin(Exchange, ImplicitAPI):
491
493
  symbol = market['symbol']
492
494
  last = self.safe_string(ticker, 'last')
493
495
  open = self.safe_string(ticker, 'open24h')
494
- spot = self.safe_value(market, 'spot', False)
496
+ spot = self.safe_bool(market, 'spot', False)
495
497
  quoteVolume = self.safe_string(ticker, 'volCurrency24h') if spot else None
496
498
  baseVolume = self.safe_string(ticker, 'vol24h')
497
499
  high = self.safe_string(ticker, 'high24h')
@@ -1757,10 +1759,58 @@ class blofin(Exchange, ImplicitAPI):
1757
1759
  'takeProfitPrice': None,
1758
1760
  })
1759
1761
 
1762
+ def fetch_leverages(self, symbols: List[str] = None, params={}) -> Leverages:
1763
+ """
1764
+ fetch the set leverage for all contract markets
1765
+ :see: https://docs.blofin.com/index.html#get-multiple-leverage
1766
+ :param str[] symbols: a list of unified market symbols, required on blofin
1767
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1768
+ :param str [params.marginMode]: 'cross' or 'isolated'
1769
+ :returns dict: a list of `leverage structures <https://docs.ccxt.com/#/?id=leverage-structure>`
1770
+ """
1771
+ self.load_markets()
1772
+ if symbols is None:
1773
+ raise ArgumentsRequired(self.id + ' fetchLeverages() requires a symbols argument')
1774
+ marginMode = None
1775
+ marginMode, params = self.handle_margin_mode_and_params('fetchLeverages', params)
1776
+ if marginMode is None:
1777
+ marginMode = self.safe_string(params, 'marginMode', 'cross') # cross marginMode
1778
+ if (marginMode != 'cross') and (marginMode != 'isolated'):
1779
+ raise BadRequest(self.id + ' fetchLeverages() requires a marginMode parameter that must be either cross or isolated')
1780
+ symbols = self.market_symbols(symbols)
1781
+ instIds = ''
1782
+ for i in range(0, len(symbols)):
1783
+ entry = symbols[i]
1784
+ entryMarket = self.market(entry)
1785
+ if i > 0:
1786
+ instIds = instIds + ',' + entryMarket['id']
1787
+ else:
1788
+ instIds = instIds + entryMarket['id']
1789
+ request = {
1790
+ 'instId': instIds,
1791
+ 'marginMode': marginMode,
1792
+ }
1793
+ response = self.privateGetAccountBatchLeverageInfo(self.extend(request, params))
1794
+ #
1795
+ # {
1796
+ # "code": "0",
1797
+ # "msg": "success",
1798
+ # "data": [
1799
+ # {
1800
+ # "leverage": "3",
1801
+ # "marginMode": "cross",
1802
+ # "instId": "BTC-USDT"
1803
+ # },
1804
+ # ]
1805
+ # }
1806
+ #
1807
+ leverages = self.safe_list(response, 'data', [])
1808
+ return self.parse_leverages(leverages, symbols, 'instId')
1809
+
1760
1810
  def fetch_leverage(self, symbol: str, params={}) -> Leverage:
1761
1811
  """
1762
1812
  fetch the set leverage for a market
1763
- :see: https://blofin.com/docs#set-leverage
1813
+ :see: https://docs.blofin.com/index.html#get-leverage
1764
1814
  :param str symbol: unified market symbol
1765
1815
  :param dict [params]: extra parameters specific to the exchange API endpoint
1766
1816
  :param str [params.marginMode]: 'cross' or 'isolated'
ccxt/coinbase.py CHANGED
@@ -2908,10 +2908,12 @@ class coinbase(Exchange, ImplicitAPI):
2908
2908
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
2909
2909
  """
2910
2910
  self.load_markets()
2911
+ maxLimit = 300
2912
+ limit = maxLimit if (limit is None) else min(limit, maxLimit)
2911
2913
  paginate = False
2912
2914
  paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate', False)
2913
2915
  if paginate:
2914
- return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 299)
2916
+ return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimit - 1)
2915
2917
  market = self.market(symbol)
2916
2918
  request = {
2917
2919
  'product_id': market['id'],
@@ -2920,18 +2922,18 @@ class coinbase(Exchange, ImplicitAPI):
2920
2922
  until = self.safe_value_n(params, ['until', 'till', 'end'])
2921
2923
  params = self.omit(params, ['until', 'till'])
2922
2924
  duration = self.parse_timeframe(timeframe)
2923
- candles300 = 300 * duration
2925
+ requestedDuration = limit * duration
2924
2926
  sinceString = None
2925
2927
  if since is not None:
2926
2928
  sinceString = self.number_to_string(self.parse_to_int(since / 1000))
2927
2929
  else:
2928
2930
  now = str(self.seconds())
2929
- sinceString = Precise.string_sub(now, str(candles300))
2931
+ sinceString = Precise.string_sub(now, str(requestedDuration))
2930
2932
  request['start'] = sinceString
2931
2933
  endString = self.number_to_string(until)
2932
2934
  if until is None:
2933
2935
  # 300 candles max
2934
- endString = Precise.string_add(sinceString, str(candles300))
2936
+ endString = Precise.string_add(sinceString, str(requestedDuration))
2935
2937
  request['end'] = endString
2936
2938
  response = self.v3PrivateGetBrokerageProductsProductIdCandles(self.extend(request, params))
2937
2939
  #
@@ -2988,8 +2990,16 @@ class coinbase(Exchange, ImplicitAPI):
2988
2990
  request = {
2989
2991
  'product_id': market['id'],
2990
2992
  }
2993
+ if since is not None:
2994
+ request['start'] = self.number_to_string(self.parse_to_int(since / 1000))
2991
2995
  if limit is not None:
2992
- request['limit'] = limit
2996
+ request['limit'] = min(limit, 1000)
2997
+ until = None
2998
+ until, params = self.handle_option_and_params(params, 'fetchTrades', 'until')
2999
+ if until is not None:
3000
+ request['end'] = self.number_to_string(self.parse_to_int(until / 1000))
3001
+ elif since is not None:
3002
+ raise ArgumentsRequired(self.id + ' fetchTrades() requires a `until` parameter when you use `since` argument')
2993
3003
  response = self.v3PrivateGetBrokerageProductsProductIdTicker(self.extend(request, params))
2994
3004
  #
2995
3005
  # {
@@ -3110,7 +3120,7 @@ class coinbase(Exchange, ImplicitAPI):
3110
3120
  # }
3111
3121
  # }
3112
3122
  #
3113
- data = self.safe_value(response, 'pricebook', {})
3123
+ data = self.safe_dict(response, 'pricebook', {})
3114
3124
  time = self.safe_string(data, 'time')
3115
3125
  timestamp = self.parse8601(time)
3116
3126
  return self.parse_order_book(data, symbol, timestamp, 'bids', 'asks', 'price', 'size')
@@ -3534,21 +3544,20 @@ class coinbase(Exchange, ImplicitAPI):
3534
3544
  body = self.json(query)
3535
3545
  else:
3536
3546
  self.check_required_credentials()
3537
- nonce = str(self.nonce())
3547
+ timestampString = str(self.seconds())
3538
3548
  payload = ''
3539
3549
  if method != 'GET':
3540
3550
  if query:
3541
3551
  body = self.json(query)
3542
3552
  payload = body
3543
- else:
3544
- if query:
3545
- payload += '?' + self.urlencode(query)
3546
- auth = nonce + method + savedPath + payload
3553
+ # 'GET' doesn't need payload in the signature. inside url is enough
3554
+ # https://docs.cloud.coinbase.com/advanced-trade-api/docs/auth#example-request
3555
+ auth = timestampString + method + savedPath + payload
3547
3556
  signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
3548
3557
  headers = {
3549
3558
  'CB-ACCESS-KEY': self.apiKey,
3550
3559
  'CB-ACCESS-SIGN': signature,
3551
- 'CB-ACCESS-TIMESTAMP': nonce,
3560
+ 'CB-ACCESS-TIMESTAMP': timestampString,
3552
3561
  'Content-Type': 'application/json',
3553
3562
  }
3554
3563
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
ccxt/hitbtc.py CHANGED
@@ -2508,7 +2508,7 @@ class hitbtc(Exchange, ImplicitAPI):
2508
2508
  if (network is not None) and (code == 'USDT'):
2509
2509
  parsedNetwork = self.safe_string(networks, network)
2510
2510
  if parsedNetwork is not None:
2511
- request['currency'] = parsedNetwork
2511
+ request['network_code'] = parsedNetwork
2512
2512
  params = self.omit(params, 'network')
2513
2513
  withdrawOptions = self.safe_value(self.options, 'withdraw', {})
2514
2514
  includeFee = self.safe_bool(withdrawOptions, 'includeFee', False)
ccxt/htx.py CHANGED
@@ -2506,7 +2506,9 @@ class htx(Exchange, ImplicitAPI):
2506
2506
  amountString = self.safe_string(trade, 'trade_volume', amountString)
2507
2507
  costString = self.safe_string(trade, 'trade_turnover')
2508
2508
  fee = None
2509
- feeCost = self.safe_string_2(trade, 'filled-fees', 'trade_fee')
2509
+ feeCost = self.safe_string(trade, 'filled-fees')
2510
+ if feeCost is None:
2511
+ feeCost = Precise.string_neg(self.safe_string(trade, 'trade_fee'))
2510
2512
  feeCurrencyId = self.safe_string_2(trade, 'fee-currency', 'fee_asset')
2511
2513
  feeCurrency = self.safe_currency_code(feeCurrencyId)
2512
2514
  filledPoints = self.safe_string(trade, 'filled-points')
ccxt/kraken.py CHANGED
@@ -39,7 +39,10 @@ class kraken(Exchange, ImplicitAPI):
39
39
  'name': 'Kraken',
40
40
  'countries': ['US'],
41
41
  'version': '0',
42
- 'rateLimit': 3000, # bucket fills max 15, but drains 1 every 3s
42
+ # rate-limits: https://support.kraken.com/hc/en-us/articles/206548367-What-are-the-API-rate-limits-#1
43
+ # for public: 1 req/s
44
+ # for private: every second 0.33 weight added to your allowed capacity(some private endpoints need 1 weight, some need 2)
45
+ 'rateLimit': 1000,
43
46
  'certified': False,
44
47
  'pro': True,
45
48
  'has': {
@@ -169,7 +172,7 @@ class kraken(Exchange, ImplicitAPI):
169
172
  },
170
173
  'public': {
171
174
  'get': {
172
- # public endpoint rate-limits are described in article: https://support.kraken.com/hc/en-us/articles/206548367-What-are-the-API-rate-limits-#1
175
+ # rate-limits explained in comment in the top of self file
173
176
  'Assets': 1,
174
177
  'AssetPairs': 1,
175
178
  'Depth': 1,
@@ -185,48 +188,48 @@ class kraken(Exchange, ImplicitAPI):
185
188
  'post': {
186
189
  'AddOrder': 0,
187
190
  'AddOrderBatch': 0,
188
- 'AddExport': 1,
189
- 'Balance': 1,
190
- 'CancelAll': 1,
191
- 'CancelAllOrdersAfter': 1,
191
+ 'AddExport': 3,
192
+ 'Balance': 3,
193
+ 'CancelAll': 3,
194
+ 'CancelAllOrdersAfter': 3,
192
195
  'CancelOrder': 0,
193
196
  'CancelOrderBatch': 0,
194
- 'ClosedOrders': 1,
195
- 'DepositAddresses': 1,
196
- 'DepositMethods': 1,
197
- 'DepositStatus': 1,
197
+ 'ClosedOrders': 3,
198
+ 'DepositAddresses': 3,
199
+ 'DepositMethods': 3,
200
+ 'DepositStatus': 3,
198
201
  'EditOrder': 0,
199
- 'ExportStatus': 1,
200
- 'GetWebSocketsToken': 1,
201
- 'Ledgers': 2,
202
- 'OpenOrders': 1,
203
- 'OpenPositions': 1,
204
- 'QueryLedgers': 1,
205
- 'QueryOrders': 1,
206
- 'QueryTrades': 1,
207
- 'RetrieveExport': 1,
208
- 'RemoveExport': 1,
209
- 'BalanceEx': 1,
210
- 'TradeBalance': 1,
211
- 'TradesHistory': 2,
212
- 'TradeVolume': 1,
213
- 'Withdraw': 1,
214
- 'WithdrawCancel': 1,
215
- 'WithdrawInfo': 1,
216
- 'WithdrawMethods': 1,
217
- 'WithdrawAddresses': 1,
218
- 'WithdrawStatus': 1,
219
- 'WalletTransfer': 1,
202
+ 'ExportStatus': 3,
203
+ 'GetWebSocketsToken': 3,
204
+ 'Ledgers': 6,
205
+ 'OpenOrders': 3,
206
+ 'OpenPositions': 3,
207
+ 'QueryLedgers': 3,
208
+ 'QueryOrders': 3,
209
+ 'QueryTrades': 3,
210
+ 'RetrieveExport': 3,
211
+ 'RemoveExport': 3,
212
+ 'BalanceEx': 3,
213
+ 'TradeBalance': 3,
214
+ 'TradesHistory': 6,
215
+ 'TradeVolume': 3,
216
+ 'Withdraw': 3,
217
+ 'WithdrawCancel': 3,
218
+ 'WithdrawInfo': 3,
219
+ 'WithdrawMethods': 3,
220
+ 'WithdrawAddresses': 3,
221
+ 'WithdrawStatus': 3,
222
+ 'WalletTransfer': 3,
220
223
  # sub accounts
221
- 'CreateSubaccount': 1,
222
- 'AccountTransfer': 1,
224
+ 'CreateSubaccount': 3,
225
+ 'AccountTransfer': 3,
223
226
  # earn
224
- 'Earn/Allocate': 1,
225
- 'Earn/Deallocate': 1,
226
- 'Earn/AllocateStatus': 1,
227
- 'Earn/DeallocateStatus': 1,
228
- 'Earn/Strategies': 1,
229
- 'Earn/Allocations': 1,
227
+ 'Earn/Allocate': 3,
228
+ 'Earn/Deallocate': 3,
229
+ 'Earn/AllocateStatus': 3,
230
+ 'Earn/DeallocateStatus': 3,
231
+ 'Earn/Strategies': 3,
232
+ 'Earn/Allocations': 3,
230
233
  },
231
234
  },
232
235
  },
ccxt/kucoinfutures.py CHANGED
@@ -46,6 +46,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
46
46
  'addMargin': True,
47
47
  'cancelAllOrders': True,
48
48
  'cancelOrder': True,
49
+ 'closeAllPositions': False,
49
50
  'closePosition': True,
50
51
  'closePositions': False,
51
52
  'createDepositAddress': True,
ccxt/lbank.py CHANGED
@@ -2529,7 +2529,7 @@ class lbank(Exchange, ImplicitAPI):
2529
2529
  uppercaseHash = hash.upper()
2530
2530
  sign = None
2531
2531
  if signatureMethod == 'RSA':
2532
- cacheSecretAsPem = self.safe_value(self.options, 'cacheSecretAsPem', True)
2532
+ cacheSecretAsPem = self.safe_bool(self.options, 'cacheSecretAsPem', True)
2533
2533
  pem = None
2534
2534
  if cacheSecretAsPem:
2535
2535
  pem = self.safe_value(self.options, 'pem')
ccxt/mexc.py CHANGED
@@ -5148,7 +5148,7 @@ class mexc(Exchange, ImplicitAPI):
5148
5148
  'X-MEXC-APIKEY': self.apiKey,
5149
5149
  'source': self.safe_string(self.options, 'broker', 'CCXT'),
5150
5150
  }
5151
- if (method == 'POST') or (method == 'PUT'):
5151
+ if (method == 'POST') or (method == 'PUT') or (method == 'DELETE'):
5152
5152
  headers['Content-Type'] = 'application/json'
5153
5153
  elif section == 'contract' or section == 'spot2':
5154
5154
  url = self.urls['api'][section][access] + '/' + self.implode_params(path, params)
ccxt/okx.py CHANGED
@@ -1549,7 +1549,7 @@ class okx(Exchange, ImplicitAPI):
1549
1549
  # while fetchCurrencies is a public API method by design
1550
1550
  # therefore we check the keys here
1551
1551
  # and fallback to generating the currencies from the markets
1552
- isSandboxMode = self.safe_value(self.options, 'sandboxMode', False)
1552
+ isSandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1553
1553
  if not self.check_required_credentials(False) or isSandboxMode:
1554
1554
  return None
1555
1555
  #
ccxt/phemex.py CHANGED
@@ -2337,7 +2337,7 @@ class phemex(Exchange, ImplicitAPI):
2337
2337
 
2338
2338
  def parse_order(self, order, market: Market = None) -> Order:
2339
2339
  isSwap = self.safe_bool(market, 'swap', False)
2340
- hasPnl = ('closedPnl' in order)
2340
+ hasPnl = ('closedPnl' in order) or ('closedPnlRv' in order) or ('totalPnlRv' in order)
2341
2341
  if isSwap or hasPnl:
2342
2342
  return self.parse_swap_order(order, market)
2343
2343
  return self.parse_spot_order(order, market)
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.58'
7
+ __version__ = '4.2.60'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -2264,7 +2264,7 @@ class binance(ccxt.async_support.binance):
2264
2264
  self.set_balance_cache(client, type, isPortfolioMargin)
2265
2265
  self.set_positions_cache(client, type, symbols, isPortfolioMargin)
2266
2266
  fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', True)
2267
- awaitPositionsSnapshot = self.safe_value('watchPositions', 'awaitPositionsSnapshot', True)
2267
+ awaitPositionsSnapshot = self.safe_bool('watchPositions', 'awaitPositionsSnapshot', True)
2268
2268
  cache = self.safe_value(self.positions, type)
2269
2269
  if fetchPositionsSnapshot and awaitPositionsSnapshot and cache is None:
2270
2270
  snapshot = await client.future(type + ':fetchPositionsSnapshot')
@@ -2382,8 +2382,17 @@ class binance(ccxt.async_support.binance):
2382
2382
  # }
2383
2383
  #
2384
2384
  marketId = self.safe_string(position, 's')
2385
+ contracts = self.safe_string(position, 'pa')
2386
+ contractsAbs = Precise.string_abs(self.safe_string(position, 'pa'))
2385
2387
  positionSide = self.safe_string_lower(position, 'ps')
2386
- hedged = positionSide != 'both'
2388
+ hedged = True
2389
+ if positionSide == 'both':
2390
+ hedged = False
2391
+ if not Precise.string_eq(contracts, '0'):
2392
+ if Precise.string_lt(contracts, '0'):
2393
+ positionSide = 'short'
2394
+ else:
2395
+ positionSide = 'long'
2387
2396
  return self.safe_position({
2388
2397
  'info': position,
2389
2398
  'id': None,
@@ -2394,7 +2403,7 @@ class binance(ccxt.async_support.binance):
2394
2403
  'entryPrice': self.safe_number(position, 'ep'),
2395
2404
  'unrealizedPnl': self.safe_number(position, 'up'),
2396
2405
  'percentage': None,
2397
- 'contracts': self.safe_number(position, 'pa'),
2406
+ 'contracts': self.parse_number(contractsAbs),
2398
2407
  'contractSize': None,
2399
2408
  'markPrice': None,
2400
2409
  'side': positionSide,
ccxt/pro/bitfinex2.py CHANGED
@@ -61,7 +61,7 @@ class bitfinex2(ccxt.async_support.bitfinex2):
61
61
  'symbol': marketId,
62
62
  }
63
63
  result = await self.watch(url, messageHash, self.deep_extend(request, params), messageHash, {'checksum': False})
64
- checksum = self.safe_value(self.options, 'checksum', True)
64
+ checksum = self.safe_bool(self.options, 'checksum', True)
65
65
  if checksum and not client.subscriptions[messageHash]['checksum'] and (channel == 'book'):
66
66
  client.subscriptions[messageHash]['checksum'] = True
67
67
  await client.send({
ccxt/pro/bitget.py CHANGED
@@ -520,7 +520,7 @@ class bitget(ccxt.async_support.bitget):
520
520
  self.handle_deltas(storedOrderBook['bids'], bids)
521
521
  storedOrderBook['timestamp'] = timestamp
522
522
  storedOrderBook['datetime'] = self.iso8601(timestamp)
523
- checksum = self.safe_value(self.options, 'checksum', True)
523
+ checksum = self.safe_bool(self.options, 'checksum', True)
524
524
  isSnapshot = self.safe_string(message, 'action') == 'snapshot' # snapshot does not have a checksum
525
525
  if not isSnapshot and checksum:
526
526
  storedAsks = storedOrderBook['asks']