ccxt 4.4.21__py2.py3-none-any.whl → 4.4.23__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.
Files changed (76) hide show
  1. ccxt/__init__.py +3 -1
  2. ccxt/abstract/binance.py +64 -43
  3. ccxt/abstract/binancecoinm.py +64 -43
  4. ccxt/abstract/binanceus.py +64 -43
  5. ccxt/abstract/binanceusdm.py +64 -43
  6. ccxt/abstract/bitflyer.py +1 -0
  7. ccxt/abstract/bitget.py +3 -0
  8. ccxt/abstract/cex.py +28 -29
  9. ccxt/abstract/coincatch.py +94 -0
  10. ccxt/abstract/gate.py +5 -0
  11. ccxt/abstract/gateio.py +5 -0
  12. ccxt/abstract/kucoin.py +1 -0
  13. ccxt/abstract/kucoinfutures.py +1 -0
  14. ccxt/abstract/okx.py +1 -0
  15. ccxt/alpaca.py +1 -0
  16. ccxt/async_support/__init__.py +3 -1
  17. ccxt/async_support/alpaca.py +1 -0
  18. ccxt/async_support/base/exchange.py +7 -1
  19. ccxt/async_support/bigone.py +3 -0
  20. ccxt/async_support/binance.py +183 -63
  21. ccxt/async_support/bitfinex.py +4 -0
  22. ccxt/async_support/bitflyer.py +57 -1
  23. ccxt/async_support/bitget.py +73 -1
  24. ccxt/async_support/bitrue.py +3 -0
  25. ccxt/async_support/bybit.py +76 -3
  26. ccxt/async_support/cex.py +1247 -1322
  27. ccxt/async_support/coinbase.py +1 -1
  28. ccxt/async_support/coinbaseexchange.py +3 -0
  29. ccxt/async_support/coincatch.py +4955 -0
  30. ccxt/async_support/coinex.py +60 -1
  31. ccxt/async_support/cryptocom.py +1 -1
  32. ccxt/async_support/gate.py +97 -2
  33. ccxt/async_support/htx.py +1 -5
  34. ccxt/async_support/hyperliquid.py +10 -8
  35. ccxt/async_support/kucoin.py +27 -57
  36. ccxt/async_support/latoken.py +6 -0
  37. ccxt/async_support/mexc.py +1 -1
  38. ccxt/async_support/oceanex.py +2 -0
  39. ccxt/async_support/okcoin.py +1 -0
  40. ccxt/async_support/okx.py +67 -1
  41. ccxt/async_support/poloniex.py +5 -0
  42. ccxt/base/exchange.py +21 -1
  43. ccxt/base/types.py +9 -0
  44. ccxt/bigone.py +3 -0
  45. ccxt/binance.py +183 -63
  46. ccxt/bitfinex.py +4 -0
  47. ccxt/bitflyer.py +57 -1
  48. ccxt/bitget.py +73 -1
  49. ccxt/bitrue.py +3 -0
  50. ccxt/bybit.py +76 -3
  51. ccxt/cex.py +1246 -1322
  52. ccxt/coinbase.py +1 -1
  53. ccxt/coinbaseexchange.py +3 -0
  54. ccxt/coincatch.py +4955 -0
  55. ccxt/coinex.py +60 -1
  56. ccxt/cryptocom.py +1 -1
  57. ccxt/gate.py +97 -2
  58. ccxt/htx.py +1 -5
  59. ccxt/hyperliquid.py +10 -8
  60. ccxt/kucoin.py +27 -57
  61. ccxt/latoken.py +6 -0
  62. ccxt/mexc.py +1 -1
  63. ccxt/oceanex.py +2 -0
  64. ccxt/okcoin.py +1 -0
  65. ccxt/okx.py +67 -1
  66. ccxt/poloniex.py +5 -0
  67. ccxt/pro/__init__.py +3 -1
  68. ccxt/pro/coincatch.py +1429 -0
  69. ccxt/test/tests_async.py +19 -5
  70. ccxt/test/tests_sync.py +19 -5
  71. ccxt-4.4.23.dist-info/METADATA +636 -0
  72. {ccxt-4.4.21.dist-info → ccxt-4.4.23.dist-info}/RECORD +75 -71
  73. ccxt-4.4.21.dist-info/METADATA +0 -635
  74. {ccxt-4.4.21.dist-info → ccxt-4.4.23.dist-info}/LICENSE.txt +0 -0
  75. {ccxt-4.4.21.dist-info → ccxt-4.4.23.dist-info}/WHEEL +0 -0
  76. {ccxt-4.4.21.dist-info → ccxt-4.4.23.dist-info}/top_level.txt +0 -0
ccxt/coinex.py CHANGED
@@ -58,6 +58,8 @@ class coinex(Exchange, ImplicitAPI):
58
58
  'cancelAllOrders': True,
59
59
  'cancelOrder': True,
60
60
  'cancelOrders': True,
61
+ 'closeAllPositions': False,
62
+ 'closePosition': True,
61
63
  'createDepositAddress': True,
62
64
  'createMarketBuyOrderWithCost': True,
63
65
  'createMarketOrderWithCost': False,
@@ -1729,7 +1731,7 @@ class coinex(Exchange, ImplicitAPI):
1729
1731
  # "stop_id": 117180138153
1730
1732
  # }
1731
1733
  #
1732
- # Swap createOrder, createOrders, editOrder, cancelOrders, cancelOrder, fetchOpenOrders, fetchClosedOrders
1734
+ # Swap createOrder, createOrders, editOrder, cancelOrders, cancelOrder, fetchOpenOrders, fetchClosedOrders, closePosition
1733
1735
  #
1734
1736
  # {
1735
1737
  # "amount": "0.0001",
@@ -5363,6 +5365,63 @@ class coinex(Exchange, ImplicitAPI):
5363
5365
  positions = self.parse_positions(records)
5364
5366
  return self.filter_by_symbol_since_limit(positions, symbol, since, limit)
5365
5367
 
5368
+ def close_position(self, symbol: str, side: OrderSide = None, params={}) -> Order:
5369
+ """
5370
+ closes an open position for a market
5371
+ :see: https://docs.coinex.com/api/v2/futures/position/http/close-position
5372
+ :param str symbol: unified CCXT market symbol
5373
+ :param str [side]: buy or sell, not used by coinex
5374
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5375
+ :param str params['type']: required by coinex, one of: limit, market, maker_only, ioc or fok, default is *market*
5376
+ :param str [params.price]: the price to fulfill the order, ignored in market orders
5377
+ :param str [params.amount]: the amount to trade in units of the base currency
5378
+ :param str [params.clientOrderId]: the client id of the order
5379
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
5380
+ """
5381
+ self.load_markets()
5382
+ market = self.market(symbol)
5383
+ type = self.safe_string(params, 'type', 'market')
5384
+ request: dict = {
5385
+ 'market': market['id'],
5386
+ 'market_type': 'FUTURES',
5387
+ 'type': type,
5388
+ }
5389
+ clientOrderId = self.safe_string_2(params, 'client_id', 'clientOrderId')
5390
+ if clientOrderId is not None:
5391
+ request['client_id'] = clientOrderId
5392
+ params = self.omit(params, 'clientOrderId')
5393
+ response = self.v2PrivatePostFuturesClosePosition(self.extend(request, params))
5394
+ #
5395
+ # {
5396
+ # "code": 0,
5397
+ # "data": {
5398
+ # "amount": "0.0001",
5399
+ # "client_id": "",
5400
+ # "created_at": 1729666043969,
5401
+ # "fee": "0.00335858",
5402
+ # "fee_ccy": "USDT",
5403
+ # "filled_amount": "0.0001",
5404
+ # "filled_value": "6.717179",
5405
+ # "last_filled_amount": "0.0001",
5406
+ # "last_filled_price": "67171.79",
5407
+ # "maker_fee_rate": "0",
5408
+ # "market": "BTCUSDT",
5409
+ # "market_type": "FUTURES",
5410
+ # "order_id": 155477479761,
5411
+ # "price": "0",
5412
+ # "realized_pnl": "-0.001823",
5413
+ # "side": "sell",
5414
+ # "taker_fee_rate": "0.0005",
5415
+ # "type": "market",
5416
+ # "unfilled_amount": "0",
5417
+ # "updated_at": 1729666043969
5418
+ # },
5419
+ # "message": "OK"
5420
+ # }
5421
+ #
5422
+ data = self.safe_dict(response, 'data', {})
5423
+ return self.parse_order(data, market)
5424
+
5366
5425
  def handle_margin_mode_and_params(self, methodName, params={}, defaultValue=None):
5367
5426
  """
5368
5427
  * @ignore
ccxt/cryptocom.py CHANGED
@@ -1496,7 +1496,7 @@ class cryptocom(Exchange, ImplicitAPI):
1496
1496
  paginate = False
1497
1497
  paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
1498
1498
  if paginate:
1499
- return self.fetch_paginated_call_dynamic('fetchMyTrades', symbol, since, limit, params)
1499
+ return self.fetch_paginated_call_dynamic('fetchMyTrades', symbol, since, limit, params, 100)
1500
1500
  request: dict = {}
1501
1501
  market = None
1502
1502
  if symbol is not None:
ccxt/gate.py CHANGED
@@ -339,10 +339,17 @@ class gate(Exchange, ImplicitAPI):
339
339
  'interest_records': 20 / 15,
340
340
  'estimate_rate': 20 / 15,
341
341
  'currency_discount_tiers': 20 / 15,
342
+ 'risk_units': 20 / 15,
343
+ 'unified_mode': 20 / 15,
344
+ 'loan_margin_tiers': 20 / 15,
342
345
  },
343
346
  'post': {
344
347
  'account_mode': 20 / 15,
345
348
  'loans': 200 / 15, # 15r/10s cost = 20 / 1.5 = 13.33
349
+ 'portfolio_calculator': 20 / 15,
350
+ },
351
+ 'put': {
352
+ 'unified_mode': 20 / 15,
346
353
  },
347
354
  },
348
355
  'spot': {
@@ -644,6 +651,7 @@ class gate(Exchange, ImplicitAPI):
644
651
  },
645
652
  'options': {
646
653
  'sandboxMode': False,
654
+ 'unifiedAccount': None,
647
655
  'createOrder': {
648
656
  'expiration': 86400, # for conditional orders
649
657
  },
@@ -905,6 +913,34 @@ class gate(Exchange, ImplicitAPI):
905
913
  super(gate, self).set_sandbox_mode(enable)
906
914
  self.options['sandboxMode'] = enable
907
915
 
916
+ def load_unified_status(self, params={}):
917
+ """
918
+ returns unifiedAccount so the user can check if the unified account is enabled
919
+ :see: https://www.gate.io/docs/developers/apiv4/#get-account-detail
920
+ :returns boolean: True or False if the enabled unified account is enabled or not and sets the unifiedAccount option if it is None
921
+ """
922
+ unifiedAccount = self.safe_bool(self.options, 'unifiedAccount')
923
+ if unifiedAccount is None:
924
+ response = self.privateAccountGetDetail(params)
925
+ #
926
+ # {
927
+ # "user_id": 10406147,
928
+ # "ip_whitelist": [],
929
+ # "currency_pairs": [],
930
+ # "key": {
931
+ # "mode": 1
932
+ # },
933
+ # "tier": 0,
934
+ # "tier_expire_time": "0001-01-01T00:00:00Z",
935
+ # "copy_trading_role": 0
936
+ # }
937
+ #
938
+ result = self.safe_dict(response, 'key', {})
939
+ self.options['unifiedAccount'] = self.safe_integer(result, 'mode') == 2
940
+
941
+ def upgrade_unified_trade_account(self, params={}):
942
+ return self.privateUnifiedPutUnifiedMode(params)
943
+
908
944
  def create_expired_option_market(self, symbol: str):
909
945
  # support expired option contracts
910
946
  quote = 'USDT'
@@ -1549,6 +1585,8 @@ class gate(Exchange, ImplicitAPI):
1549
1585
  apiBackup = self.safe_value(self.urls, 'apiBackup')
1550
1586
  if apiBackup is not None:
1551
1587
  return None
1588
+ if self.check_required_credentials(False):
1589
+ self.load_unified_status()
1552
1590
  response = self.publicSpotGetCurrencies(params)
1553
1591
  #
1554
1592
  # {
@@ -2573,10 +2611,14 @@ class gate(Exchange, ImplicitAPI):
2573
2611
  :param str [params.settle]: 'btc' or 'usdt' - settle currency for perpetual swap and future - default="usdt" for swap and "btc" for future
2574
2612
  :param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
2575
2613
  :param str [params.symbol]: margin only - unified ccxt symbol
2614
+ :param boolean [params.unifiedAccount]: default False, set to True for fetching the unified account balance
2576
2615
  """
2577
2616
  self.load_markets()
2617
+ self.load_unified_status()
2578
2618
  symbol = self.safe_string(params, 'symbol')
2579
2619
  params = self.omit(params, 'symbol')
2620
+ isUnifiedAccount = False
2621
+ isUnifiedAccount, params = self.handle_option_and_params(params, 'fetchBalance', 'unifiedAccount')
2580
2622
  type, query = self.handle_market_type_and_params('fetchBalance', None, params)
2581
2623
  request, requestParams = self.prepare_request(None, type, query)
2582
2624
  marginMode, requestQuery = self.get_margin_mode(False, requestParams)
@@ -2584,7 +2626,9 @@ class gate(Exchange, ImplicitAPI):
2584
2626
  market = self.market(symbol)
2585
2627
  request['currency_pair'] = market['id']
2586
2628
  response = None
2587
- if type == 'spot':
2629
+ if isUnifiedAccount:
2630
+ response = self.privateUnifiedGetAccounts(self.extend(request, params))
2631
+ elif type == 'spot':
2588
2632
  if marginMode == 'spot':
2589
2633
  response = self.privateSpotGetAccounts(self.extend(request, requestQuery))
2590
2634
  elif marginMode == 'margin':
@@ -2747,12 +2791,63 @@ class gate(Exchange, ImplicitAPI):
2747
2791
  # "orders_limit": 10
2748
2792
  # }
2749
2793
  #
2794
+ # unified
2795
+ #
2796
+ # {
2797
+ # "user_id": 10001,
2798
+ # "locked": False,
2799
+ # "balances": {
2800
+ # "ETH": {
2801
+ # "available": "0",
2802
+ # "freeze": "0",
2803
+ # "borrowed": "0.075393666654",
2804
+ # "negative_liab": "0",
2805
+ # "futures_pos_liab": "0",
2806
+ # "equity": "1016.1",
2807
+ # "total_freeze": "0",
2808
+ # "total_liab": "0"
2809
+ # },
2810
+ # "POINT": {
2811
+ # "available": "9999999999.017023138734",
2812
+ # "freeze": "0",
2813
+ # "borrowed": "0",
2814
+ # "negative_liab": "0",
2815
+ # "futures_pos_liab": "0",
2816
+ # "equity": "12016.1",
2817
+ # "total_freeze": "0",
2818
+ # "total_liab": "0"
2819
+ # },
2820
+ # "USDT": {
2821
+ # "available": "0.00000062023",
2822
+ # "freeze": "0",
2823
+ # "borrowed": "0",
2824
+ # "negative_liab": "0",
2825
+ # "futures_pos_liab": "0",
2826
+ # "equity": "16.1",
2827
+ # "total_freeze": "0",
2828
+ # "total_liab": "0"
2829
+ # }
2830
+ # },
2831
+ # "total": "230.94621713",
2832
+ # "borrowed": "161.66395521",
2833
+ # "total_initial_margin": "1025.0524665088",
2834
+ # "total_margin_balance": "3382495.944473949183",
2835
+ # "total_maintenance_margin": "205.01049330176",
2836
+ # "total_initial_margin_rate": "3299.827135672679",
2837
+ # "total_maintenance_margin_rate": "16499.135678363399",
2838
+ # "total_available_margin": "3381470.892007440383",
2839
+ # "unified_account_total": "3381470.892007440383",
2840
+ # "unified_account_total_liab": "0",
2841
+ # "unified_account_total_equity": "100016.1",
2842
+ # "leverage": "2"
2843
+ # }
2844
+ #
2750
2845
  result: dict = {
2751
2846
  'info': response,
2752
2847
  }
2753
2848
  isolated = marginMode == 'margin'
2754
2849
  data = response
2755
- if 'balances' in data: # True for cross_margin
2850
+ if 'balances' in data: # True for cross_margin and unified
2756
2851
  flatBalances = []
2757
2852
  balances = self.safe_value(data, 'balances', [])
2758
2853
  # inject currency and create an artificial balance object
ccxt/htx.py CHANGED
@@ -4779,11 +4779,7 @@ class htx(Exchange, ImplicitAPI):
4779
4779
  cost = None
4780
4780
  amount = None
4781
4781
  if (type is not None) and (type.find('market') >= 0):
4782
- # for market orders amount is in quote currency, meaning it is the cost
4783
- if side == 'sell':
4784
- cost = self.safe_string(order, 'field-cash-amount')
4785
- else:
4786
- cost = self.safe_string(order, 'amount')
4782
+ cost = self.safe_string(order, 'field-cash-amount')
4787
4783
  else:
4788
4784
  amount = self.safe_string_2(order, 'volume', 'amount')
4789
4785
  cost = self.safe_string_n(order, ['filled-cash-amount', 'field-cash-amount', 'trade_turnover']) # same typo here
ccxt/hyperliquid.py CHANGED
@@ -2112,14 +2112,16 @@ class hyperliquid(Exchange, ImplicitAPI):
2112
2112
  leverage = self.safe_dict(entry, 'leverage', {})
2113
2113
  marginMode = self.safe_string(leverage, 'type')
2114
2114
  isIsolated = (marginMode == 'isolated')
2115
- size = self.safe_string(entry, 'szi')
2115
+ rawSize = self.safe_string(entry, 'szi')
2116
+ size = rawSize
2116
2117
  side = None
2117
2118
  if size is not None:
2118
- side = 'long' if Precise.string_gt(size, '0') else 'short'
2119
+ side = 'long' if Precise.string_gt(rawSize, '0') else 'short'
2119
2120
  size = Precise.string_abs(size)
2120
- unrealizedPnl = self.safe_number(entry, 'unrealizedPnl')
2121
- initialMargin = self.safe_number(entry, 'marginUsed')
2122
- percentage = unrealizedPnl / initialMargin * 100
2121
+ rawUnrealizedPnl = self.safe_string(entry, 'unrealizedPnl')
2122
+ absRawUnrealizedPnl = Precise.string_abs(rawUnrealizedPnl)
2123
+ initialMargin = self.safe_string(entry, 'marginUsed')
2124
+ percentage = Precise.string_mul(Precise.string_div(absRawUnrealizedPnl, initialMargin), '100')
2123
2125
  return self.safe_position({
2124
2126
  'info': position,
2125
2127
  'id': None,
@@ -2129,7 +2131,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2129
2131
  'isolated': isIsolated,
2130
2132
  'hedged': None,
2131
2133
  'side': side,
2132
- 'contracts': size,
2134
+ 'contracts': self.parse_number(size),
2133
2135
  'contractSize': None,
2134
2136
  'entryPrice': self.safe_number(entry, 'entryPx'),
2135
2137
  'markPrice': None,
@@ -2140,10 +2142,10 @@ class hyperliquid(Exchange, ImplicitAPI):
2140
2142
  'maintenanceMargin': None,
2141
2143
  'initialMarginPercentage': None,
2142
2144
  'maintenanceMarginPercentage': None,
2143
- 'unrealizedPnl': unrealizedPnl,
2145
+ 'unrealizedPnl': self.parse_number(rawUnrealizedPnl),
2144
2146
  'liquidationPrice': self.safe_number(entry, 'liquidationPx'),
2145
2147
  'marginMode': marginMode,
2146
- 'percentage': percentage,
2148
+ 'percentage': self.parse_number(percentage),
2147
2149
  })
2148
2150
 
2149
2151
  def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
ccxt/kucoin.py CHANGED
@@ -307,6 +307,7 @@ class kucoin(Exchange, ImplicitAPI):
307
307
  # ws
308
308
  'bullet-private': 10, # 10SW
309
309
  'position/update-user-leverage': 5,
310
+ 'deposit-address/create': 20,
310
311
  },
311
312
  'delete': {
312
313
  # account
@@ -726,6 +727,7 @@ class kucoin(Exchange, ImplicitAPI):
726
727
  'accounts/sub-transfer': 'v2',
727
728
  'accounts/inner-transfer': 'v2',
728
729
  'transfer-out': 'v3',
730
+ 'deposit-address/create': 'v3',
729
731
  # spot trading
730
732
  'oco/order': 'v3',
731
733
  # margin trading
@@ -737,6 +739,7 @@ class kucoin(Exchange, ImplicitAPI):
737
739
  'redeem': 'v3',
738
740
  'lend/purchase/update': 'v3',
739
741
  'position/update-user-leverage': 'v3',
742
+ 'withdrawals': 'v3',
740
743
  },
741
744
  'DELETE': {
742
745
  # account
@@ -802,7 +805,7 @@ class kucoin(Exchange, ImplicitAPI):
802
805
  'TLOS': 'tlos', # tlosevm is different
803
806
  'CFX': 'cfx',
804
807
  'ACA': 'aca',
805
- 'OPTIMISM': 'optimism',
808
+ 'OP': 'optimism',
806
809
  'ONT': 'ont',
807
810
  'GLMR': 'glmr',
808
811
  'CSPR': 'cspr',
@@ -1862,7 +1865,7 @@ class kucoin(Exchange, ImplicitAPI):
1862
1865
 
1863
1866
  def create_deposit_address(self, code: str, params={}):
1864
1867
  """
1865
- :see: https://docs.kucoin.com/#create-deposit-address
1868
+ :see: https://www.kucoin.com/docs/rest/funding/deposit/create-deposit-address-v3-
1866
1869
  create a currency deposit address
1867
1870
  :param str code: unified currency code of the currency for the deposit address
1868
1871
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1877,11 +1880,23 @@ class kucoin(Exchange, ImplicitAPI):
1877
1880
  networkCode = None
1878
1881
  networkCode, params = self.handle_network_code_and_params(params)
1879
1882
  if networkCode is not None:
1880
- request['chain'] = self.network_code_to_id(networkCode).lower()
1881
- response = self.privatePostDepositAddresses(self.extend(request, params))
1883
+ request['chain'] = self.network_code_to_id(networkCode) # docs mention "chain-name", but seems "chain-id" is used, like in "fetchDepositAddress"
1884
+ response = self.privatePostDepositAddressCreate(self.extend(request, params))
1882
1885
  # {"code":"260000","msg":"Deposit address already exists."}
1883
- # BCH {"code":"200000","data":{"address":"bitcoincash:qza3m4nj9rx7l9r0cdadfqxts6f92shvhvr5ls4q7z","memo":""}}
1884
- # BTC {"code":"200000","data":{"address":"36SjucKqQpQSvsak9A7h6qzFjrVXpRNZhE","memo":""}}
1886
+ #
1887
+ # {
1888
+ # "code": "200000",
1889
+ # "data": {
1890
+ # "address": "0x2336d1834faab10b2dac44e468f2627138417431",
1891
+ # "memo": null,
1892
+ # "chainId": "bsc",
1893
+ # "to": "MAIN",
1894
+ # "expirationDate": 0,
1895
+ # "currency": "BNB",
1896
+ # "chainName": "BEP20"
1897
+ # }
1898
+ # }
1899
+ #
1885
1900
  data = self.safe_dict(response, 'data', {})
1886
1901
  return self.parse_deposit_address(data, currency)
1887
1902
 
@@ -1931,7 +1946,7 @@ class kucoin(Exchange, ImplicitAPI):
1931
1946
  return {
1932
1947
  'info': depositAddress,
1933
1948
  'currency': code,
1934
- 'network': self.network_id_to_code(self.safe_string(depositAddress, 'chain')),
1949
+ 'network': self.network_id_to_code(self.safe_string(depositAddress, 'chainId')),
1935
1950
  'address': address,
1936
1951
  'tag': self.safe_string(depositAddress, 'memo'),
1937
1952
  }
@@ -3238,7 +3253,7 @@ class kucoin(Exchange, ImplicitAPI):
3238
3253
  def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
3239
3254
  """
3240
3255
  make a withdrawal
3241
- :see: https://www.kucoin.com/docs/rest/funding/withdrawals/apply-withdraw
3256
+ :see: https://www.kucoin.com/docs/rest/funding/withdrawals/apply-withdraw-v3-
3242
3257
  :param str code: unified currency code
3243
3258
  :param float amount: the amount to withdraw
3244
3259
  :param str address: the address to withdraw to
@@ -3252,7 +3267,8 @@ class kucoin(Exchange, ImplicitAPI):
3252
3267
  currency = self.currency(code)
3253
3268
  request: dict = {
3254
3269
  'currency': currency['id'],
3255
- 'address': address,
3270
+ 'toAddress': address,
3271
+ 'withdrawType': 'ADDRESS',
3256
3272
  # 'memo': tag,
3257
3273
  # 'isInner': False, # internal transfer or external withdrawal
3258
3274
  # 'remark': 'optional',
@@ -3264,15 +3280,14 @@ class kucoin(Exchange, ImplicitAPI):
3264
3280
  networkCode, params = self.handle_network_code_and_params(params)
3265
3281
  if networkCode is not None:
3266
3282
  request['chain'] = self.network_code_to_id(networkCode).lower()
3267
- self.load_currency_precision(currency, networkCode)
3268
- request['amount'] = self.currency_to_precision(code, amount, networkCode)
3283
+ request['amount'] = float(self.currency_to_precision(code, amount, networkCode))
3269
3284
  includeFee = None
3270
3285
  includeFee, params = self.handle_option_and_params(params, 'withdraw', 'includeFee', False)
3271
3286
  if includeFee:
3272
3287
  request['feeDeductType'] = 'INTERNAL'
3273
3288
  response = self.privatePostWithdrawals(self.extend(request, params))
3274
3289
  #
3275
- # https://github.com/ccxt/ccxt/issues/5558
3290
+ # the id is inside "data"
3276
3291
  #
3277
3292
  # {
3278
3293
  # "code": 200000,
@@ -3284,51 +3299,6 @@ class kucoin(Exchange, ImplicitAPI):
3284
3299
  data = self.safe_dict(response, 'data', {})
3285
3300
  return self.parse_transaction(data, currency)
3286
3301
 
3287
- def load_currency_precision(self, currency, networkCode: Str = None):
3288
- # might not have network specific precisions defined in fetchCurrencies(because of webapi failure)
3289
- # we should check and refetch precision once-per-instance for that specific currency & network
3290
- # so avoids thorwing exceptions and burden to users
3291
- # Note: self needs to be executed only if networkCode was provided
3292
- if networkCode is not None:
3293
- networks = currency['networks']
3294
- network = self.safe_dict(networks, networkCode)
3295
- if self.safe_number(network, 'precision') is not None:
3296
- # if precision exists, no need to refetch
3297
- return
3298
- # otherwise try to fetch and store in instance
3299
- request: dict = {
3300
- 'currency': currency['id'],
3301
- 'chain': self.network_code_to_id(networkCode).lower(),
3302
- }
3303
- response = self.privateGetWithdrawalsQuotas(request)
3304
- #
3305
- # {
3306
- # "code": "200000",
3307
- # "data": {
3308
- # "currency": "USDT",
3309
- # "limitBTCAmount": "14.24094850",
3310
- # "usedBTCAmount": "0.00000000",
3311
- # "quotaCurrency": "USDT",
3312
- # "limitQuotaCurrencyAmount": "999999.00000000",
3313
- # "usedQuotaCurrencyAmount": "0",
3314
- # "remainAmount": "999999.0000",
3315
- # "availableAmount": "10.77545071",
3316
- # "withdrawMinFee": "1",
3317
- # "innerWithdrawMinFee": "0",
3318
- # "withdrawMinSize": "10",
3319
- # "isWithdrawEnabled": True,
3320
- # "precision": 4,
3321
- # "chain": "EOS",
3322
- # "reason": null,
3323
- # "lockedAmount": "0"
3324
- # }
3325
- # }
3326
- #
3327
- data = self.safe_dict(response, 'data', {})
3328
- precision = self.parse_number(self.parse_precision(self.safe_string(data, 'precision')))
3329
- code = currency['code']
3330
- self.currencies[code]['networks'][networkCode]['precision'] = precision
3331
-
3332
3302
  def parse_transaction_status(self, status: Str):
3333
3303
  statuses: dict = {
3334
3304
  'SUCCESS': 'ok',
ccxt/latoken.py CHANGED
@@ -60,6 +60,12 @@ class latoken(Exchange, ImplicitAPI):
60
60
  'fetchDepositAddressesByNetwork': False,
61
61
  'fetchDepositsWithdrawals': True,
62
62
  'fetchDepositWithdrawFees': False,
63
+ 'fetchFundingHistory': False,
64
+ 'fetchFundingInterval': False,
65
+ 'fetchFundingIntervals': False,
66
+ 'fetchFundingRate': False,
67
+ 'fetchFundingRateHistory': False,
68
+ 'fetchFundingRates': False,
63
69
  'fetchIsolatedBorrowRate': False,
64
70
  'fetchIsolatedBorrowRates': False,
65
71
  'fetchMarginMode': False,
ccxt/mexc.py CHANGED
@@ -93,7 +93,7 @@ class mexc(Exchange, ImplicitAPI):
93
93
  'fetchFundingIntervals': False,
94
94
  'fetchFundingRate': True,
95
95
  'fetchFundingRateHistory': True,
96
- 'fetchFundingRates': None,
96
+ 'fetchFundingRates': False,
97
97
  'fetchIndexOHLCV': True,
98
98
  'fetchIsolatedBorrowRate': False,
99
99
  'fetchIsolatedBorrowRates': False,
ccxt/oceanex.py CHANGED
@@ -57,6 +57,8 @@ class oceanex(Exchange, ImplicitAPI):
57
57
  'fetchDepositAddress': 'emulated',
58
58
  'fetchDepositAddresses': None,
59
59
  'fetchDepositAddressesByNetwork': True,
60
+ 'fetchFundingRateHistory': False,
61
+ 'fetchFundingRates': False,
60
62
  'fetchIsolatedBorrowRate': False,
61
63
  'fetchIsolatedBorrowRates': False,
62
64
  'fetchMarkets': True,
ccxt/okcoin.py CHANGED
@@ -72,6 +72,7 @@ class okcoin(Exchange, ImplicitAPI):
72
72
  'fetchFundingHistory': False,
73
73
  'fetchFundingRate': False,
74
74
  'fetchFundingRateHistory': False,
75
+ 'fetchFundingRates': False,
75
76
  'fetchLedger': True,
76
77
  'fetchMarkets': True,
77
78
  'fetchMyTrades': True,
ccxt/okx.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.okx import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Balances, Conversion, CrossBorrowRate, CrossBorrowRates, Currencies, Currency, DepositAddress, Greeks, Int, LedgerEntry, Leverage, LeverageTier, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
9
+ from ccxt.base.types import Account, LongShortRatio, Balances, Conversion, CrossBorrowRate, CrossBorrowRates, Currencies, Currency, DepositAddress, Greeks, Int, LedgerEntry, Leverage, LeverageTier, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from typing import Any
12
12
  from ccxt.base.errors import ExchangeError
@@ -119,6 +119,8 @@ class okx(Exchange, ImplicitAPI):
119
119
  'fetchLedgerEntry': None,
120
120
  'fetchLeverage': True,
121
121
  'fetchLeverageTiers': False,
122
+ 'fetchLongShortRatio': False,
123
+ 'fetchLongShortRatioHistory': True,
122
124
  'fetchMarginAdjustmentHistory': True,
123
125
  'fetchMarketLeverageTiers': True,
124
126
  'fetchMarkets': True,
@@ -261,6 +263,7 @@ class okx(Exchange, ImplicitAPI):
261
263
  'rubik/stat/margin/loan-ratio': 4,
262
264
  # long/short
263
265
  'rubik/stat/contracts/long-short-account-ratio': 4,
266
+ 'rubik/stat/contracts/long-short-account-ratio-contract': 4,
264
267
  'rubik/stat/contracts/open-interest-volume': 4,
265
268
  'rubik/stat/option/open-interest-volume': 4,
266
269
  # put/call
@@ -7929,3 +7932,66 @@ class okx(Exchange, ImplicitAPI):
7929
7932
  data = self.safe_list(response, 'data')
7930
7933
  positions = self.parse_positions(data, symbols, params)
7931
7934
  return self.filter_by_since_limit(positions, since, limit)
7935
+
7936
+ def fetch_long_short_ratio_history(self, symbol: Str = None, timeframe: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LongShortRatio]:
7937
+ """
7938
+ fetches the long short ratio history for a unified market symbol
7939
+ :see: https://www.okx.com/docs-v5/en/#trading-statistics-rest-api-get-contract-long-short-ratio
7940
+ :param str symbol: unified symbol of the market to fetch the long short ratio for
7941
+ :param str [timeframe]: the period for the ratio
7942
+ :param int [since]: the earliest time in ms to fetch ratios for
7943
+ :param int [limit]: the maximum number of long short ratio structures to retrieve
7944
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7945
+ :param int [params.until]: timestamp in ms of the latest ratio to fetch
7946
+ :returns dict[]: an array of `long short ratio structures <https://docs.ccxt.com/#/?id=long-short-ratio-structure>`
7947
+ """
7948
+ self.load_markets()
7949
+ market = self.market(symbol)
7950
+ request: dict = {
7951
+ 'instId': market['id'],
7952
+ }
7953
+ until = self.safe_string_2(params, 'until', 'end')
7954
+ params = self.omit(params, 'until')
7955
+ if until is not None:
7956
+ request['end'] = until
7957
+ if timeframe is not None:
7958
+ request['period'] = timeframe
7959
+ if since is not None:
7960
+ request['begin'] = since
7961
+ if limit is not None:
7962
+ request['limit'] = limit
7963
+ response = self.publicGetRubikStatContractsLongShortAccountRatioContract(self.extend(request, params))
7964
+ #
7965
+ # {
7966
+ # "code": "0",
7967
+ # "data": [
7968
+ # ["1729323600000", "0.9398602814619824"],
7969
+ # ["1729323300000", "0.9398602814619824"],
7970
+ # ["1729323000000", "0.9398602814619824"],
7971
+ # ],
7972
+ # "msg": ""
7973
+ # }
7974
+ #
7975
+ data = self.safe_list(response, 'data', [])
7976
+ result = []
7977
+ for i in range(0, len(data)):
7978
+ entry = data[i]
7979
+ result.append({
7980
+ 'timestamp': self.safe_string(entry, 0),
7981
+ 'longShortRatio': self.safe_string(entry, 1),
7982
+ })
7983
+ return self.parse_long_short_ratio_history(result, market)
7984
+
7985
+ def parse_long_short_ratio(self, info: dict, market: Market = None) -> LongShortRatio:
7986
+ timestamp = self.safe_integer(info, 'timestamp')
7987
+ symbol = None
7988
+ if market is not None:
7989
+ symbol = market['symbol']
7990
+ return {
7991
+ 'info': info,
7992
+ 'symbol': symbol,
7993
+ 'timestamp': timestamp,
7994
+ 'datetime': self.iso8601(timestamp),
7995
+ 'timeframe': None,
7996
+ 'longShortRatio': self.safe_number(info, 'longShortRatio'),
7997
+ }
ccxt/poloniex.py CHANGED
@@ -62,7 +62,12 @@ class poloniex(Exchange, ImplicitAPI):
62
62
  'fetchDepositsWithdrawals': True,
63
63
  'fetchDepositWithdrawFee': 'emulated',
64
64
  'fetchDepositWithdrawFees': True,
65
+ 'fetchFundingHistory': False,
66
+ 'fetchFundingInterval': False,
67
+ 'fetchFundingIntervals': False,
65
68
  'fetchFundingRate': False,
69
+ 'fetchFundingRateHistory': False,
70
+ 'fetchFundingRates': False,
66
71
  'fetchMarginMode': False,
67
72
  'fetchMarkets': True,
68
73
  'fetchMyTrades': True,
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.21'
7
+ __version__ = '4.4.23'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
@@ -40,6 +40,7 @@ from ccxt.pro.coinbase import coinbase # noqa
40
40
  from ccxt.pro.coinbaseadvanced import coinbaseadvanced # noqa: F401
41
41
  from ccxt.pro.coinbaseexchange import coinbaseexchange # noqa: F401
42
42
  from ccxt.pro.coinbaseinternational import coinbaseinternational # noqa: F401
43
+ from ccxt.pro.coincatch import coincatch # noqa: F401
43
44
  from ccxt.pro.coincheck import coincheck # noqa: F401
44
45
  from ccxt.pro.coinex import coinex # noqa: F401
45
46
  from ccxt.pro.coinone import coinone # noqa: F401
@@ -114,6 +115,7 @@ exchanges = [
114
115
  'coinbaseadvanced',
115
116
  'coinbaseexchange',
116
117
  'coinbaseinternational',
118
+ 'coincatch',
117
119
  'coincheck',
118
120
  'coinex',
119
121
  'coinone',