ccxt 4.2.86__py2.py3-none-any.whl → 4.2.88__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 (82) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/ascendex.py +16 -6
  3. ccxt/async_support/__init__.py +1 -1
  4. ccxt/async_support/ascendex.py +16 -6
  5. ccxt/async_support/base/exchange.py +1 -1
  6. ccxt/async_support/binance.py +28 -11
  7. ccxt/async_support/bingx.py +39 -3
  8. ccxt/async_support/bitfinex.py +2 -0
  9. ccxt/async_support/bitfinex2.py +18 -4
  10. ccxt/async_support/bitflyer.py +18 -0
  11. ccxt/async_support/bitget.py +37 -22
  12. ccxt/async_support/bitopro.py +2 -0
  13. ccxt/async_support/bitrue.py +16 -8
  14. ccxt/async_support/bitvavo.py +2 -0
  15. ccxt/async_support/btcmarkets.py +1 -1
  16. ccxt/async_support/btcturk.py +2 -1
  17. ccxt/async_support/coinex.py +182 -58
  18. ccxt/async_support/cryptocom.py +1 -1
  19. ccxt/async_support/currencycom.py +1 -1
  20. ccxt/async_support/delta.py +8 -6
  21. ccxt/async_support/digifinex.py +9 -7
  22. ccxt/async_support/exmo.py +15 -15
  23. ccxt/async_support/gate.py +23 -20
  24. ccxt/async_support/hitbtc.py +31 -7
  25. ccxt/async_support/htx.py +2 -2
  26. ccxt/async_support/huobijp.py +1 -1
  27. ccxt/async_support/hyperliquid.py +242 -16
  28. ccxt/async_support/idex.py +1 -1
  29. ccxt/async_support/krakenfutures.py +4 -5
  30. ccxt/async_support/kucoin.py +7 -4
  31. ccxt/async_support/kucoinfutures.py +2 -2
  32. ccxt/async_support/lbank.py +2 -0
  33. ccxt/async_support/mexc.py +4 -4
  34. ccxt/async_support/oceanex.py +1 -1
  35. ccxt/async_support/okx.py +29 -15
  36. ccxt/async_support/phemex.py +6 -4
  37. ccxt/async_support/wazirx.py +1 -1
  38. ccxt/async_support/zonda.py +2 -0
  39. ccxt/base/exchange.py +22 -3
  40. ccxt/base/types.py +12 -0
  41. ccxt/binance.py +28 -11
  42. ccxt/bingx.py +39 -3
  43. ccxt/bitfinex.py +2 -0
  44. ccxt/bitfinex2.py +18 -4
  45. ccxt/bitflyer.py +18 -0
  46. ccxt/bitget.py +37 -22
  47. ccxt/bitopro.py +2 -0
  48. ccxt/bitrue.py +16 -8
  49. ccxt/bitvavo.py +2 -0
  50. ccxt/btcmarkets.py +1 -1
  51. ccxt/btcturk.py +2 -1
  52. ccxt/coinex.py +182 -58
  53. ccxt/cryptocom.py +1 -1
  54. ccxt/currencycom.py +1 -1
  55. ccxt/delta.py +8 -6
  56. ccxt/digifinex.py +9 -7
  57. ccxt/exmo.py +15 -15
  58. ccxt/gate.py +23 -20
  59. ccxt/hitbtc.py +31 -7
  60. ccxt/htx.py +2 -2
  61. ccxt/huobijp.py +1 -1
  62. ccxt/hyperliquid.py +241 -16
  63. ccxt/idex.py +1 -1
  64. ccxt/krakenfutures.py +4 -5
  65. ccxt/kucoin.py +7 -4
  66. ccxt/kucoinfutures.py +2 -2
  67. ccxt/lbank.py +2 -0
  68. ccxt/mexc.py +4 -4
  69. ccxt/oceanex.py +1 -1
  70. ccxt/okx.py +29 -15
  71. ccxt/phemex.py +6 -4
  72. ccxt/pro/__init__.py +1 -1
  73. ccxt/pro/kucoin.py +10 -6
  74. ccxt/test/base/test_last_price.py +0 -1
  75. ccxt/test/base/test_shared_methods.py +1 -2
  76. ccxt/test/base/test_status.py +1 -1
  77. ccxt/wazirx.py +1 -1
  78. ccxt/zonda.py +2 -0
  79. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/METADATA +5 -6
  80. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/RECORD +82 -82
  81. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/WHEEL +0 -0
  82. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/top_level.txt +0 -0
@@ -463,7 +463,7 @@ class idex(Exchange, ImplicitAPI):
463
463
  if since is not None:
464
464
  request['start'] = since
465
465
  if limit is not None:
466
- request['limit'] = limit
466
+ request['limit'] = min(limit, 1000)
467
467
  response = await self.publicGetCandles(self.extend(request, params))
468
468
  if isinstance(response, list):
469
469
  # [
@@ -363,7 +363,8 @@ class krakenfutures(Exchange, ImplicitAPI):
363
363
  # swap == perpetual
364
364
  settle = None
365
365
  settleId = None
366
- amountPrecision = self.parse_number(self.parse_precision(self.safe_string(market, 'contractValueTradePrecision', '0')))
366
+ cvtp = self.safe_string(market, 'contractValueTradePrecision')
367
+ amountPrecision = self.parse_number(self.integer_precision_to_amount(cvtp))
367
368
  pricePrecision = self.safe_number(market, 'tickSize')
368
369
  contract = (swap or future or index)
369
370
  swapOrFutures = (swap or future)
@@ -635,14 +636,12 @@ class krakenfutures(Exchange, ImplicitAPI):
635
636
  request['from'] = self.parse_to_int(since / 1000)
636
637
  if limit is None:
637
638
  limit = 5000
638
- elif limit > 5000:
639
- raise BadRequest(self.id + ' fetchOHLCV() limit cannot exceed 5000')
639
+ limit = min(limit, 5000)
640
640
  toTimestamp = self.sum(request['from'], limit * duration - 1)
641
641
  currentTimestamp = self.seconds()
642
642
  request['to'] = min(toTimestamp, currentTimestamp)
643
643
  elif limit is not None:
644
- if limit > 5000:
645
- raise BadRequest(self.id + ' fetchOHLCV() limit cannot exceed 5000')
644
+ limit = min(limit, 5000)
646
645
  duration = self.parse_timeframe(timeframe)
647
646
  request['to'] = self.seconds()
648
647
  request['from'] = self.parse_to_int(request['to'] - (duration * limit))
@@ -3326,9 +3326,9 @@ class kucoin(Exchange, ImplicitAPI):
3326
3326
  async def fetch_balance(self, params={}) -> Balances:
3327
3327
  """
3328
3328
  query for balance and get the amount of funds available for trading or funds locked in orders
3329
- :see: https://docs.kucoin.com/#list-accounts
3330
3329
  :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-list-spot-margin-trade_hf
3331
- :see: https://docs.kucoin.com/#query-isolated-margin-account-info
3330
+ :see: https://www.kucoin.com/docs/rest/funding/funding-overview/get-account-detail-margin
3331
+ :see: https://www.kucoin.com/docs/rest/funding/funding-overview/get-account-detail-isolated-margin
3332
3332
  :param dict [params]: extra parameters specific to the exchange API endpoint
3333
3333
  :param dict [params.marginMode]: 'cross' or 'isolated', margin type for fetching margin balance
3334
3334
  :param dict [params.type]: extra parameters specific to the exchange API endpoint
@@ -3353,7 +3353,7 @@ class kucoin(Exchange, ImplicitAPI):
3353
3353
  response = None
3354
3354
  request = {}
3355
3355
  isolated = (marginMode == 'isolated') or (type == 'isolated')
3356
- cross = (marginMode == 'cross') or (type == 'cross')
3356
+ cross = (marginMode == 'cross') or (type == 'margin')
3357
3357
  if isolated:
3358
3358
  if currency is not None:
3359
3359
  request['balanceCurrency'] = currency['id']
@@ -3418,13 +3418,14 @@ class kucoin(Exchange, ImplicitAPI):
3418
3418
  # }
3419
3419
  # }
3420
3420
  #
3421
- data = self.safe_list(response, 'data', [])
3421
+ data = None
3422
3422
  result = {
3423
3423
  'info': response,
3424
3424
  'timestamp': None,
3425
3425
  'datetime': None,
3426
3426
  }
3427
3427
  if isolated:
3428
+ data = self.safe_dict(response, 'data', {})
3428
3429
  assets = self.safe_value(data, 'assets', data)
3429
3430
  for i in range(0, len(assets)):
3430
3431
  entry = assets[i]
@@ -3439,6 +3440,7 @@ class kucoin(Exchange, ImplicitAPI):
3439
3440
  subResult[quoteCode] = self.parse_balance_helper(quote)
3440
3441
  result[symbol] = self.safe_balance(subResult)
3441
3442
  elif cross:
3443
+ data = self.safe_dict(response, 'data', {})
3442
3444
  accounts = self.safe_list(data, 'accounts', [])
3443
3445
  for i in range(0, len(accounts)):
3444
3446
  balance = accounts[i]
@@ -3446,6 +3448,7 @@ class kucoin(Exchange, ImplicitAPI):
3446
3448
  codeInner = self.safe_currency_code(currencyId)
3447
3449
  result[codeInner] = self.parse_balance_helper(balance)
3448
3450
  else:
3451
+ data = self.safe_list(response, 'data', [])
3449
3452
  for i in range(0, len(data)):
3450
3453
  balance = data[i]
3451
3454
  balanceType = self.safe_string(balance, 'type')
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.kucoin import kucoin
7
7
  from ccxt.abstract.kucoinfutures import ImplicitAPI
8
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
8
+ from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
9
  from typing import List
10
10
  from ccxt.base.errors import PermissionDenied
11
11
  from ccxt.base.errors import AccountSuspended
@@ -1424,7 +1424,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
1424
1424
  #
1425
1425
  return self.safe_value(response, 'data')
1426
1426
 
1427
- async def add_margin(self, symbol: str, amount, params={}):
1427
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
1428
1428
  """
1429
1429
  add margin
1430
1430
  :see: https://www.kucoin.com/docs/rest/futures-trading/positions/add-margin-manually
@@ -970,6 +970,8 @@ class lbank(Exchange, ImplicitAPI):
970
970
  market = self.market(symbol)
971
971
  if limit is None:
972
972
  limit = 100
973
+ else:
974
+ limit = min(limit, 2000)
973
975
  if since is None:
974
976
  duration = self.parse_timeframe(timeframe)
975
977
  since = self.milliseconds() - duration * 1000 * limit
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.mexc import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Balances, Currency, IndexType, Int, Leverage, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Account, Balances, Currency, IndexType, Int, Leverage, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -3778,7 +3778,7 @@ class mexc(Exchange, ImplicitAPI):
3778
3778
  # }
3779
3779
  return response
3780
3780
 
3781
- async def reduce_margin(self, symbol: str, amount, params={}):
3781
+ async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
3782
3782
  """
3783
3783
  remove margin from a position
3784
3784
  :param str symbol: unified market symbol
@@ -3788,7 +3788,7 @@ class mexc(Exchange, ImplicitAPI):
3788
3788
  """
3789
3789
  return await self.modify_margin_helper(symbol, amount, 'SUB', params)
3790
3790
 
3791
- async def add_margin(self, symbol: str, amount, params={}):
3791
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
3792
3792
  """
3793
3793
  add margin
3794
3794
  :param str symbol: unified market symbol
@@ -4228,7 +4228,7 @@ class mexc(Exchange, ImplicitAPI):
4228
4228
  key = self.safe_string(keys, 0)
4229
4229
  result = self.safe_dict(addressStructures, key)
4230
4230
  if result is None:
4231
- raise InvalidAddress(self.id + ' fetchDepositAddress() cannot find a deposit address for ' + code + ', and network' + network + 'consider creating one using the MEXC platform')
4231
+ raise InvalidAddress(self.id + ' fetchDepositAddress() cannot find a deposit address for ' + code + ', and network' + network + 'consider creating one using .createDepositAddress() method or in MEXC website')
4232
4232
  return result
4233
4233
 
4234
4234
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
@@ -750,7 +750,7 @@ class oceanex(Exchange, ImplicitAPI):
750
750
  if since is not None:
751
751
  request['timestamp'] = since
752
752
  if limit is not None:
753
- request['limit'] = limit
753
+ request['limit'] = min(limit, 10000)
754
754
  response = await self.publicPostK(self.extend(request, params))
755
755
  ohlcvs = self.safe_list(response, 'data', [])
756
756
  return self.parse_ohlcvs(ohlcvs, market, timeframe, since, limit)
ccxt/async_support/okx.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.okx import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Account, Balances, Currency, Greeks, Int, Leverage, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Account, Balances, Currency, Greeks, Int, Leverage, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -6007,7 +6007,7 @@ class okx(Exchange, ImplicitAPI):
6007
6007
  data = self.safe_value(response, 'data')
6008
6008
  return self.parse_borrow_rate_history(data, code, since, limit)
6009
6009
 
6010
- async def modify_margin_helper(self, symbol: str, amount, type, params={}):
6010
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
6011
6011
  await self.load_markets()
6012
6012
  market = self.market(symbol)
6013
6013
  posSide = self.safe_string(params, 'posSide', 'net')
@@ -6033,29 +6033,43 @@ class okx(Exchange, ImplicitAPI):
6033
6033
  # "msg": ""
6034
6034
  # }
6035
6035
  #
6036
- return self.parse_margin_modification(response, market)
6036
+ data = self.safe_list(response, 'data', [])
6037
+ errorCode = self.safe_string(response, 'code')
6038
+ item = self.safe_dict(data, 0, {})
6039
+ return self.extend(self.parse_margin_modification(item, market), {
6040
+ 'status': 'ok' if (errorCode == '0') else 'failed',
6041
+ })
6037
6042
 
6038
- def parse_margin_modification(self, data, market: Market = None):
6039
- innerData = self.safe_value(data, 'data', [])
6040
- entry = self.safe_value(innerData, 0, {})
6041
- errorCode = self.safe_string(data, 'code')
6042
- status = 'ok' if (errorCode == '0') else 'failed'
6043
- amountRaw = self.safe_number(entry, 'amt')
6044
- typeRaw = self.safe_string(entry, 'type')
6043
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
6044
+ #
6045
+ # addMargin/reduceMargin
6046
+ #
6047
+ # {
6048
+ # "amt": "0.01",
6049
+ # "instId": "ETH-USD-SWAP",
6050
+ # "posSide": "net",
6051
+ # "type": "reduce"
6052
+ # }
6053
+ #
6054
+ amountRaw = self.safe_number(data, 'amt')
6055
+ typeRaw = self.safe_string(data, 'type')
6045
6056
  type = 'reduce' if (typeRaw == 'reduce') else 'add'
6046
- marketId = self.safe_string(entry, 'instId')
6057
+ marketId = self.safe_string(data, 'instId')
6047
6058
  responseMarket = self.safe_market(marketId, market)
6048
6059
  code = responseMarket['base'] if responseMarket['inverse'] else responseMarket['quote']
6049
6060
  return {
6050
6061
  'info': data,
6062
+ 'symbol': responseMarket['symbol'],
6051
6063
  'type': type,
6052
6064
  'amount': amountRaw,
6065
+ 'total': None,
6053
6066
  'code': code,
6054
- 'symbol': responseMarket['symbol'],
6055
- 'status': status,
6067
+ 'status': None,
6068
+ 'timestamp': None,
6069
+ 'datetime': None,
6056
6070
  }
6057
6071
 
6058
- async def reduce_margin(self, symbol: str, amount, params={}):
6072
+ async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
6059
6073
  """
6060
6074
  remove margin from a position
6061
6075
  :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-increase-decrease-margin
@@ -6066,7 +6080,7 @@ class okx(Exchange, ImplicitAPI):
6066
6080
  """
6067
6081
  return await self.modify_margin_helper(symbol, amount, 'reduce', params)
6068
6082
 
6069
- async def add_margin(self, symbol: str, amount, params={}):
6083
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
6070
6084
  """
6071
6085
  add margin
6072
6086
  :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-increase-decrease-margin
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.phemex import ImplicitAPI
8
8
  import hashlib
9
9
  import numbers
10
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -3744,7 +3744,7 @@ class phemex(Exchange, ImplicitAPI):
3744
3744
  'previousFundingDatetime': None,
3745
3745
  }
3746
3746
 
3747
- async def set_margin(self, symbol: str, amount: float, params={}):
3747
+ async def set_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3748
3748
  """
3749
3749
  Either adds or reduces margin in an isolated position in order to set the margin to a specific value
3750
3750
  :see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#assign-position-balance-in-isolated-marign-mode
@@ -3777,7 +3777,7 @@ class phemex(Exchange, ImplicitAPI):
3777
3777
  }
3778
3778
  return self.safe_string(statuses, status, status)
3779
3779
 
3780
- def parse_margin_modification(self, data, market: Market = None):
3780
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
3781
3781
  #
3782
3782
  # {
3783
3783
  # "code": 0,
@@ -3790,12 +3790,14 @@ class phemex(Exchange, ImplicitAPI):
3790
3790
  codeCurrency = 'base' if inverse else 'quote'
3791
3791
  return {
3792
3792
  'info': data,
3793
+ 'symbol': self.safe_symbol(None, market),
3793
3794
  'type': 'set',
3794
3795
  'amount': None,
3795
3796
  'total': None,
3796
3797
  'code': market[codeCurrency],
3797
- 'symbol': self.safe_symbol(None, market),
3798
3798
  'status': self.parse_margin_status(self.safe_string(data, 'code')),
3799
+ 'timestamp': None,
3800
+ 'datetime': None,
3799
3801
  }
3800
3802
 
3801
3803
  async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
@@ -324,7 +324,7 @@ class wazirx(Exchange, ImplicitAPI):
324
324
  'interval': self.safe_string(self.timeframes, timeframe, timeframe),
325
325
  }
326
326
  if limit is not None:
327
- request['limit'] = limit
327
+ request['limit'] = min(limit, 2000)
328
328
  until = self.safe_integer(params, 'until')
329
329
  params = self.omit(params, ['until'])
330
330
  if since is not None:
@@ -1181,6 +1181,8 @@ class zonda(Exchange, ImplicitAPI):
1181
1181
  }
1182
1182
  if limit is None:
1183
1183
  limit = 100
1184
+ else:
1185
+ limit = min(limit, 11000) # supports up to 11k candles diapason
1184
1186
  duration = self.parse_timeframe(timeframe)
1185
1187
  timerange = limit * duration * 1000
1186
1188
  if since is None:
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.86'
7
+ __version__ = '4.2.88'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -4525,6 +4525,25 @@ class Exchange(object):
4525
4525
  parsedPrecision = parsedPrecision + '0'
4526
4526
  return parsedPrecision + '1'
4527
4527
 
4528
+ def integer_precision_to_amount(self, precision: Str):
4529
+ """
4530
+ * @ignore
4531
+ handles positive & negative numbers too. parsePrecision() does not handle negative numbers, but self method handles
4532
+ :param str precision: The number of digits to the right of the decimal
4533
+ :returns str: a string number equal to 1e-precision
4534
+ """
4535
+ if precision is None:
4536
+ return None
4537
+ if Precise.string_ge(precision, '0'):
4538
+ return self.parse_precision(precision)
4539
+ else:
4540
+ positivePrecisionString = Precise.string_abs(precision)
4541
+ positivePrecision = int(positivePrecisionString)
4542
+ parsedPrecision = '1'
4543
+ for i in range(0, positivePrecision - 1):
4544
+ parsedPrecision = parsedPrecision + '0'
4545
+ return parsedPrecision + '0'
4546
+
4528
4547
  def load_time_difference(self, params={}):
4529
4548
  serverTime = self.fetch_time(params)
4530
4549
  after = self.milliseconds()
@@ -4935,8 +4954,8 @@ class Exchange(object):
4935
4954
  entry = responseKeys[i]
4936
4955
  dictionary = entry if isArray else response[entry]
4937
4956
  currencyId = self.safe_string(dictionary, currencyIdKey) if isArray else entry
4938
- currency = self.safe_value(self.currencies_by_id, currencyId)
4939
- code = self.safe_string(currency, 'code', currencyId)
4957
+ currency = self.safe_currency(currencyId)
4958
+ code = self.safe_string(currency, 'code')
4940
4959
  if (codes is None) or (self.in_array(code, codes)):
4941
4960
  depositWithdrawFees[code] = self.parseDepositWithdrawFee(dictionary, currency)
4942
4961
  return depositWithdrawFees
ccxt/base/types.py CHANGED
@@ -324,6 +324,7 @@ class Option(TypedDict):
324
324
 
325
325
  OptionChain = Dict[str, Option]
326
326
 
327
+
327
328
  class MarketInterface(TypedDict):
328
329
  info: Dict[str, Any]
329
330
  id: Str
@@ -375,6 +376,17 @@ class LastPrice(TypedDict):
375
376
  info: Dict[str, Any]
376
377
 
377
378
 
379
+ class MarginModification(TypedDict):
380
+ info: Dict[str, any]
381
+ symbol: str
382
+ type: Optional[Literal['add', 'reduce', 'set']]
383
+ amount: Optional[float]
384
+ code: Str
385
+ status: Str
386
+ timestamp: Int
387
+ datetime: Str
388
+
389
+
378
390
  LastPrices = Dict[Str, LastPrice]
379
391
 
380
392
  Market = Optional[MarketInterface]
ccxt/binance.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.binance import ImplicitAPI
8
8
  import hashlib
9
9
  import json
10
- from ccxt.base.types import Balances, Currency, Greeks, Int, Leverage, Leverages, MarginMode, MarginModes, Market, MarketInterface, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Currency, Greeks, Int, Leverage, Leverages, MarginMode, MarginModes, MarginModification, Market, MarketInterface, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -1882,7 +1882,7 @@ class binance(Exchange, ImplicitAPI):
1882
1882
  '-4140': BadRequest, # Invalid symbol status for opening position
1883
1883
  '-4141': OperationRejected, # Symbol is closed
1884
1884
  '-4144': BadSymbol, # Invalid pair
1885
- '-4164': OperationRejected, # Leverage reduction is not supported in Isolated Margin Mode with open positions
1885
+ '-4164': InvalidOrder, # {"code":-4164,"msg":"Order's notional must be no smaller than 20(unless you choose reduce only)."}
1886
1886
  '-4165': BadRequest, # Invalid time interval
1887
1887
  '-4167': BadRequest, # Unable to adjust to Multi-Assets mode with symbols of USDⓈ-M Futures under isolated-margin mode.
1888
1888
  '-4168': BadRequest, # Unable to adjust to isolated-margin mode under the Multi-Assets mode.
@@ -8499,7 +8499,7 @@ class binance(Exchange, ImplicitAPI):
8499
8499
  'previousFundingDatetime': None,
8500
8500
  }
8501
8501
 
8502
- def parse_account_positions(self, account):
8502
+ def parse_account_positions(self, account, filterClosed=False):
8503
8503
  positions = self.safe_list(account, 'positions')
8504
8504
  assets = self.safe_list(account, 'assets', [])
8505
8505
  balances = {}
@@ -8521,7 +8521,8 @@ class binance(Exchange, ImplicitAPI):
8521
8521
  code = market['quote'] if market['linear'] else market['base']
8522
8522
  maintenanceMargin = self.safe_string(position, 'maintMargin')
8523
8523
  # check for maintenance margin so empty positions are not returned
8524
- if (maintenanceMargin != '0') and (maintenanceMargin != '0.00000000'):
8524
+ isPositionOpen = (maintenanceMargin != '0') and (maintenanceMargin != '0.00000000')
8525
+ if not filterClosed or isPositionOpen:
8525
8526
  # sometimes not all the codes are correctly returned...
8526
8527
  if code in balances:
8527
8528
  parsed = self.parse_account_position(self.extend(position, {
@@ -9287,10 +9288,11 @@ class binance(Exchange, ImplicitAPI):
9287
9288
  :see: https://binance-docs.github.io/apidocs/delivery/en/#account-information-user_data
9288
9289
  :see: https://binance-docs.github.io/apidocs/pm/en/#get-um-account-detail-user_data
9289
9290
  :see: https://binance-docs.github.io/apidocs/pm/en/#get-cm-account-detail-user_data
9290
- :param str[]|None symbols: list of unified market symbols
9291
+ :param str[] [symbols]: list of unified market symbols
9291
9292
  :param dict [params]: extra parameters specific to the exchange API endpoint
9292
9293
  :param boolean [params.portfolioMargin]: set to True if you would like to fetch positions in a portfolio margin account
9293
9294
  :param str [params.subType]: "linear" or "inverse"
9295
+ :param boolean [params.filterClosed]: set to True if you would like to filter out closed positions, default is False
9294
9296
  :returns dict: data on account positions
9295
9297
  """
9296
9298
  if symbols is not None:
@@ -9318,7 +9320,9 @@ class binance(Exchange, ImplicitAPI):
9318
9320
  response = self.dapiPrivateGetAccount(params)
9319
9321
  else:
9320
9322
  raise NotSupported(self.id + ' fetchPositions() supports linear and inverse contracts only')
9321
- result = self.parse_account_positions(response)
9323
+ filterClosed = None
9324
+ filterClosed, params = self.handle_option_and_params(params, 'fetchAccountPositions', 'filterClosed', False)
9325
+ result = self.parse_account_positions(response, filterClosed)
9322
9326
  symbols = self.market_symbols(symbols)
9323
9327
  return self.filter_by_array_positions(result, 'symbol', symbols, False)
9324
9328
 
@@ -10286,7 +10290,7 @@ class binance(Exchange, ImplicitAPI):
10286
10290
  raise NotSupported(self.id + ' add / reduce margin only supported with type future or delivery')
10287
10291
  self.load_markets()
10288
10292
  market = self.market(symbol)
10289
- amount = self.cost_to_precision(symbol, amount)
10293
+ amount = self.amount_to_precision(symbol, amount)
10290
10294
  request = {
10291
10295
  'type': addOrReduce,
10292
10296
  'symbol': market['id'],
@@ -10312,7 +10316,17 @@ class binance(Exchange, ImplicitAPI):
10312
10316
  'code': code,
10313
10317
  })
10314
10318
 
10315
- def parse_margin_modification(self, data, market: Market = None):
10319
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
10320
+ #
10321
+ # add/reduce margin
10322
+ #
10323
+ # {
10324
+ # "code": 200,
10325
+ # "msg": "Successfully modify position margin.",
10326
+ # "amount": 0.001,
10327
+ # "type": 1
10328
+ # }
10329
+ #
10316
10330
  rawType = self.safe_integer(data, 'type')
10317
10331
  resultType = 'add' if (rawType == 1) else 'reduce'
10318
10332
  resultAmount = self.safe_number(data, 'amount')
@@ -10320,14 +10334,17 @@ class binance(Exchange, ImplicitAPI):
10320
10334
  status = 'ok' if (errorCode == '200') else 'failed'
10321
10335
  return {
10322
10336
  'info': data,
10337
+ 'symbol': market['symbol'],
10323
10338
  'type': resultType,
10324
10339
  'amount': resultAmount,
10340
+ 'total': None,
10325
10341
  'code': None,
10326
- 'symbol': market['symbol'],
10327
10342
  'status': status,
10343
+ 'timestamp': None,
10344
+ 'datetime': None,
10328
10345
  }
10329
10346
 
10330
- def reduce_margin(self, symbol: str, amount, params={}):
10347
+ def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
10331
10348
  """
10332
10349
  :see: https://binance-docs.github.io/apidocs/delivery/en/#modify-isolated-position-margin-trade
10333
10350
  :see: https://binance-docs.github.io/apidocs/futures/en/#modify-isolated-position-margin-trade
@@ -10339,7 +10356,7 @@ class binance(Exchange, ImplicitAPI):
10339
10356
  """
10340
10357
  return self.modify_margin_helper(symbol, amount, 2, params)
10341
10358
 
10342
- def add_margin(self, symbol: str, amount, params={}):
10359
+ def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
10343
10360
  """
10344
10361
  :see: https://binance-docs.github.io/apidocs/delivery/en/#modify-isolated-position-margin-trade
10345
10362
  :see: https://binance-docs.github.io/apidocs/futures/en/#modify-isolated-position-margin-trade
ccxt/bingx.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bingx import ImplicitAPI
8
8
  import hashlib
9
9
  import numbers
10
- from ccxt.base.types import Balances, Currency, Int, Leverage, MarginMode, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Currency, Int, Leverage, MarginMode, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -43,6 +43,7 @@ class bingx(Exchange, ImplicitAPI):
43
43
  'swap': True,
44
44
  'future': False,
45
45
  'option': False,
46
+ 'addMargin': True,
46
47
  'cancelAllOrders': True,
47
48
  'cancelOrder': True,
48
49
  'cancelOrders': True,
@@ -89,6 +90,7 @@ class bingx(Exchange, ImplicitAPI):
89
90
  'fetchTrades': True,
90
91
  'fetchTransfers': True,
91
92
  'fetchWithdrawals': True,
93
+ 'reduceMargin': True,
92
94
  'setLeverage': True,
93
95
  'setMargin': True,
94
96
  'setMarginMode': True,
@@ -3246,7 +3248,19 @@ class bingx(Exchange, ImplicitAPI):
3246
3248
  }
3247
3249
  return self.swapV2PrivatePostTradeMarginType(self.extend(request, params))
3248
3250
 
3249
- def set_margin(self, symbol: str, amount: float, params={}):
3251
+ def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3252
+ request = {
3253
+ 'type': 1,
3254
+ }
3255
+ return self.set_margin(symbol, amount, self.extend(request, params))
3256
+
3257
+ def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3258
+ request = {
3259
+ 'type': 2,
3260
+ }
3261
+ return self.set_margin(symbol, amount, self.extend(request, params))
3262
+
3263
+ def set_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3250
3264
  """
3251
3265
  Either adds or reduces margin in an isolated position in order to set the margin to a specific value
3252
3266
  :see: https://bingx-api.github.io/docs/#/swapV2/trade-api.html#Adjust%20isolated%20margin
@@ -3276,7 +3290,29 @@ class bingx(Exchange, ImplicitAPI):
3276
3290
  # "type": 1
3277
3291
  # }
3278
3292
  #
3279
- return response
3293
+ return self.parse_margin_modification(response, market)
3294
+
3295
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
3296
+ #
3297
+ # {
3298
+ # "code": 0,
3299
+ # "msg": "",
3300
+ # "amount": 1,
3301
+ # "type": 1
3302
+ # }
3303
+ #
3304
+ type = self.safe_string(data, 'type')
3305
+ return {
3306
+ 'info': data,
3307
+ 'symbol': self.safe_string(market, 'symbol'),
3308
+ 'type': 'add' if (type == '1') else 'reduce',
3309
+ 'amount': self.safe_number(data, 'amount'),
3310
+ 'total': self.safe_number(data, 'margin'),
3311
+ 'code': self.safe_string(market, 'settle'),
3312
+ 'status': None,
3313
+ 'timestamp': None,
3314
+ 'datetime': None,
3315
+ }
3280
3316
 
3281
3317
  def fetch_leverage(self, symbol: str, params={}) -> Leverage:
3282
3318
  """
ccxt/bitfinex.py CHANGED
@@ -1259,6 +1259,8 @@ class bitfinex(Exchange, ImplicitAPI):
1259
1259
  self.load_markets()
1260
1260
  if limit is None:
1261
1261
  limit = 100
1262
+ else:
1263
+ limit = min(limit, 10000)
1262
1264
  market = self.market(symbol)
1263
1265
  v2id = 't' + market['id']
1264
1266
  request = {
ccxt/bitfinex2.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bitfinex2 import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -1343,6 +1343,8 @@ class bitfinex2(Exchange, ImplicitAPI):
1343
1343
  market = self.market(symbol)
1344
1344
  if limit is None:
1345
1345
  limit = 10000
1346
+ else:
1347
+ limit = min(limit, 10000)
1346
1348
  request = {
1347
1349
  'symbol': market['id'],
1348
1350
  'timeframe': self.safe_string(self.timeframes, timeframe, timeframe),
@@ -3279,7 +3281,7 @@ class bitfinex2(Exchange, ImplicitAPI):
3279
3281
  'datetime': self.iso8601(timestamp),
3280
3282
  })
3281
3283
 
3282
- def set_margin(self, symbol: str, amount: float, params={}):
3284
+ def set_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
3283
3285
  """
3284
3286
  either adds or reduces margin in a swap position in order to set the margin to a specific value
3285
3287
  :see: https://docs.bitfinex.com/reference/rest-auth-deriv-pos-collateral-set
@@ -3307,16 +3309,28 @@ class bitfinex2(Exchange, ImplicitAPI):
3307
3309
  data = self.safe_value(response, 0)
3308
3310
  return self.parse_margin_modification(data, market)
3309
3311
 
3310
- def parse_margin_modification(self, data, market=None):
3312
+ def parse_margin_modification(self, data, market=None) -> MarginModification:
3313
+ #
3314
+ # setMargin
3315
+ #
3316
+ # [
3317
+ # [
3318
+ # 1
3319
+ # ]
3320
+ # ]
3321
+ #
3311
3322
  marginStatusRaw = data[0]
3312
3323
  marginStatus = 'ok' if (marginStatusRaw == 1) else 'failed'
3313
3324
  return {
3314
3325
  'info': data,
3326
+ 'symbol': market['symbol'],
3315
3327
  'type': None,
3316
3328
  'amount': None,
3329
+ 'total': None,
3317
3330
  'code': None,
3318
- 'symbol': market['symbol'],
3319
3331
  'status': marginStatus,
3332
+ 'timestamp': None,
3333
+ 'datetime': None,
3320
3334
  }
3321
3335
 
3322
3336
  def fetch_order(self, id: str, symbol: Str = None, params={}):