ccxt 4.4.80__py2.py3-none-any.whl → 4.4.85__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 (104) hide show
  1. ccxt/__init__.py +1 -5
  2. ccxt/abstract/blofin.py +8 -0
  3. ccxt/abstract/btcbox.py +1 -0
  4. ccxt/apex.py +21 -30
  5. ccxt/ascendex.py +1 -1
  6. ccxt/async_support/__init__.py +1 -5
  7. ccxt/async_support/apex.py +21 -30
  8. ccxt/async_support/ascendex.py +1 -1
  9. ccxt/async_support/base/exchange.py +26 -3
  10. ccxt/async_support/base/ws/cache.py +6 -1
  11. ccxt/async_support/bigone.py +17 -14
  12. ccxt/async_support/bingx.py +13 -32
  13. ccxt/async_support/bitfinex.py +61 -48
  14. ccxt/async_support/bitget.py +7 -4
  15. ccxt/async_support/bitrue.py +14 -32
  16. ccxt/async_support/bitso.py +33 -0
  17. ccxt/async_support/bitstamp.py +33 -0
  18. ccxt/async_support/blofin.py +145 -14
  19. ccxt/async_support/btcbox.py +25 -5
  20. ccxt/async_support/bybit.py +20 -39
  21. ccxt/async_support/cex.py +2 -4
  22. ccxt/async_support/coinbase.py +56 -42
  23. ccxt/async_support/coinbaseexchange.py +141 -32
  24. ccxt/async_support/coincatch.py +14 -67
  25. ccxt/async_support/coinex.py +28 -29
  26. ccxt/async_support/coinlist.py +17 -16
  27. ccxt/async_support/coinmetro.py +20 -11
  28. ccxt/async_support/coinone.py +8 -10
  29. ccxt/async_support/coinsph.py +124 -2
  30. ccxt/async_support/cryptocom.py +109 -2
  31. ccxt/async_support/cryptomus.py +42 -80
  32. ccxt/async_support/delta.py +75 -36
  33. ccxt/async_support/derive.py +46 -10
  34. ccxt/async_support/ellipx.py +175 -77
  35. ccxt/async_support/gate.py +1 -1
  36. ccxt/async_support/gemini.py +3 -4
  37. ccxt/async_support/hitbtc.py +56 -65
  38. ccxt/async_support/htx.py +2 -2
  39. ccxt/async_support/hyperliquid.py +15 -2
  40. ccxt/async_support/kraken.py +27 -23
  41. ccxt/async_support/kucoinfutures.py +5 -0
  42. ccxt/async_support/lbank.py +1 -1
  43. ccxt/async_support/okx.py +1 -2
  44. ccxt/async_support/oxfun.py +21 -1
  45. ccxt/async_support/paradex.py +120 -4
  46. ccxt/base/errors.py +6 -0
  47. ccxt/base/exchange.py +40 -3
  48. ccxt/base/types.py +3 -0
  49. ccxt/bigone.py +17 -14
  50. ccxt/bingx.py +13 -32
  51. ccxt/bitfinex.py +61 -48
  52. ccxt/bitget.py +7 -4
  53. ccxt/bitrue.py +14 -32
  54. ccxt/bitso.py +33 -0
  55. ccxt/bitstamp.py +33 -0
  56. ccxt/blofin.py +145 -14
  57. ccxt/btcbox.py +24 -5
  58. ccxt/bybit.py +20 -39
  59. ccxt/cex.py +2 -4
  60. ccxt/coinbase.py +56 -42
  61. ccxt/coinbaseexchange.py +141 -32
  62. ccxt/coincatch.py +14 -67
  63. ccxt/coinex.py +28 -29
  64. ccxt/coinlist.py +17 -16
  65. ccxt/coinmetro.py +20 -11
  66. ccxt/coinone.py +8 -10
  67. ccxt/coinsph.py +124 -2
  68. ccxt/cryptocom.py +109 -2
  69. ccxt/cryptomus.py +42 -80
  70. ccxt/delta.py +75 -36
  71. ccxt/derive.py +46 -10
  72. ccxt/ellipx.py +175 -77
  73. ccxt/gate.py +1 -1
  74. ccxt/gemini.py +3 -4
  75. ccxt/hitbtc.py +56 -65
  76. ccxt/htx.py +2 -2
  77. ccxt/hyperliquid.py +15 -2
  78. ccxt/kraken.py +27 -23
  79. ccxt/kucoinfutures.py +5 -0
  80. ccxt/lbank.py +1 -1
  81. ccxt/okx.py +1 -2
  82. ccxt/oxfun.py +21 -1
  83. ccxt/paradex.py +120 -4
  84. ccxt/pro/__init__.py +69 -3
  85. ccxt/pro/binance.py +31 -33
  86. ccxt/pro/bithumb.py +5 -3
  87. ccxt/pro/coinbase.py +1 -1
  88. ccxt/pro/hyperliquid.py +10 -2
  89. ccxt/pro/kraken.py +249 -79
  90. ccxt/pro/mexc.py +252 -7
  91. ccxt/pro/poloniex.py +6 -2
  92. {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/METADATA +7 -11
  93. {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/RECORD +96 -104
  94. ccxt/abstract/bl3p.py +0 -19
  95. ccxt/abstract/idex.py +0 -26
  96. ccxt/async_support/base/ws/fast_client.py +0 -97
  97. ccxt/async_support/bl3p.py +0 -543
  98. ccxt/async_support/idex.py +0 -1889
  99. ccxt/bl3p.py +0 -543
  100. ccxt/idex.py +0 -1889
  101. ccxt/pro/idex.py +0 -687
  102. {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/LICENSE.txt +0 -0
  103. {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/WHEEL +0 -0
  104. {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/top_level.txt +0 -0
@@ -1616,6 +1616,8 @@ class kraken(Exchange, ImplicitAPI):
1616
1616
  'volume': self.amount_to_precision(symbol, amount),
1617
1617
  }
1618
1618
  orderRequest = self.order_request('createOrder', symbol, type, request, amount, price, params)
1619
+ flags = self.safe_string(orderRequest[0], 'oflags', '')
1620
+ isUsingCost = flags.find('viqc') > -1
1619
1621
  response = await self.privatePostAddOrder(self.extend(orderRequest[0], orderRequest[1]))
1620
1622
  #
1621
1623
  # {
@@ -1627,6 +1629,10 @@ class kraken(Exchange, ImplicitAPI):
1627
1629
  # }
1628
1630
  #
1629
1631
  result = self.safe_dict(response, 'result')
1632
+ result['usingCost'] = isUsingCost
1633
+ # it's impossible to know if the order was created using cost or base currency
1634
+ # becuase kraken only returns something like self: {order: 'buy 10.00000000 LTCUSD @ market'}
1635
+ # self usingCost flag is used to help the parsing but omited from the order
1630
1636
  return self.parse_order(result)
1631
1637
 
1632
1638
  def find_market_by_altname_or_id(self, id):
@@ -1713,22 +1719,15 @@ class kraken(Exchange, ImplicitAPI):
1713
1719
  # }
1714
1720
  #
1715
1721
  # ws - createOrder
1716
- # {
1717
- # "descr": 'sell 0.00010000 XBTUSDT @ market',
1718
- # "event": 'addOrderStatus',
1719
- # "reqid": 1,
1720
- # "status": 'ok',
1721
- # "txid": 'OAVXZH-XIE54-JCYYDG'
1722
- # }
1722
+ # {
1723
+ # "order_id": "OXM2QD-EALR2-YBAVEU"
1724
+ # }
1725
+ #
1723
1726
  # ws - editOrder
1724
- # {
1725
- # "descr": "order edited price = 9000.00000000",
1726
- # "event": "editOrderStatus",
1727
- # "originaltxid": "O65KZW-J4AW3-VFS74A",
1728
- # "reqid": 3,
1729
- # "status": "ok",
1730
- # "txid": "OTI672-HJFAO-XOIPPK"
1731
- # }
1727
+ # {
1728
+ # "amend_id": "TJSMEH-AA67V-YUSQ6O",
1729
+ # "order_id": "OXM2QD-EALR2-YBAVEU"
1730
+ # }
1732
1731
  #
1733
1732
  # {
1734
1733
  # "error": [],
@@ -1796,6 +1795,8 @@ class kraken(Exchange, ImplicitAPI):
1796
1795
  # "oflags": "fciq"
1797
1796
  # }
1798
1797
  #
1798
+ isUsingCost = self.safe_bool(order, 'usingCost', False)
1799
+ order = self.omit(order, 'usingCost')
1799
1800
  description = self.safe_dict(order, 'descr', {})
1800
1801
  orderDescriptionObj = self.safe_dict(order, 'descr') # can be null
1801
1802
  orderDescription = None
@@ -1808,11 +1809,15 @@ class kraken(Exchange, ImplicitAPI):
1808
1809
  marketId = None
1809
1810
  price = None
1810
1811
  amount = None
1812
+ cost = None
1811
1813
  triggerPrice = None
1812
1814
  if orderDescription is not None:
1813
1815
  parts = orderDescription.split(' ')
1814
1816
  side = self.safe_string(parts, 0)
1815
- amount = self.safe_string(parts, 1)
1817
+ if not isUsingCost:
1818
+ amount = self.safe_string(parts, 1)
1819
+ else:
1820
+ cost = self.safe_string(parts, 1)
1816
1821
  marketId = self.safe_string(parts, 2)
1817
1822
  part4 = self.safe_string(parts, 4)
1818
1823
  part5 = self.safe_string(parts, 5)
@@ -1842,13 +1847,12 @@ class kraken(Exchange, ImplicitAPI):
1842
1847
  # kraken truncates the cost in the api response so we will ignore it and calculate it from average & filled
1843
1848
  # cost = self.safe_string(order, 'cost')
1844
1849
  price = self.safe_string(description, 'price', price)
1845
- # when type = trailling stop returns price = '+50.0000%'
1846
- if (price is not None) and price.endswith('%'):
1850
+ # when type = trailing stop returns price = '+50.0000%'
1851
+ if (price is not None) and (price.endswith('%') or Precise.string_equals(price, '0.00000') or Precise.string_equals(price, '0')):
1847
1852
  price = None # self is not the price we want
1848
- if (price is None) or Precise.string_equals(price, '0'):
1853
+ if price is None:
1849
1854
  price = self.safe_string(description, 'price2')
1850
- if (price is None) or Precise.string_equals(price, '0'):
1851
- price = self.safe_string(order, 'price', price)
1855
+ price = self.safe_string_2(order, 'limitprice', 'price', price)
1852
1856
  flags = self.safe_string(order, 'oflags', '')
1853
1857
  isPostOnly = flags.find('post') > -1
1854
1858
  average = self.safe_number(order, 'price')
@@ -1865,7 +1869,7 @@ class kraken(Exchange, ImplicitAPI):
1865
1869
  elif flags.find('fcib') >= 0:
1866
1870
  fee['currency'] = market['base']
1867
1871
  status = self.parse_order_status(self.safe_string(order, 'status'))
1868
- id = self.safe_string_n(order, ['id', 'txid', 'amend_id'])
1872
+ id = self.safe_string_n(order, ['id', 'txid', 'order_id', 'amend_id'])
1869
1873
  if (id is None) or (id.startswith('[')):
1870
1874
  txid = self.safe_list(order, 'txid')
1871
1875
  id = self.safe_string(txid, 0)
@@ -1922,7 +1926,7 @@ class kraken(Exchange, ImplicitAPI):
1922
1926
  'triggerPrice': triggerPrice,
1923
1927
  'takeProfitPrice': takeProfitPrice,
1924
1928
  'stopLossPrice': stopLossPrice,
1925
- 'cost': None,
1929
+ 'cost': cost,
1926
1930
  'amount': amount,
1927
1931
  'filled': filled,
1928
1932
  'average': average,
@@ -1510,6 +1510,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
1510
1510
  :param str [params.timeInForce]: GTC, GTT, IOC, or FOK, default is GTC, limit orders only
1511
1511
  :param str [params.postOnly]: Post only flag, invalid when timeInForce is IOC or FOK
1512
1512
  :param float [params.cost]: the cost of the order in units of USDT
1513
+ :param str [params.marginMode]: 'cross' or 'isolated', default is 'isolated'
1513
1514
  ----------------- Exchange Specific Parameters -----------------
1514
1515
  :param float [params.leverage]: Leverage size of the order(mandatory param in request, default is 1)
1515
1516
  :param str [params.clientOid]: client order id, defaults to uuid if not passed
@@ -1607,6 +1608,10 @@ class kucoinfutures(kucoin, ImplicitAPI):
1607
1608
  'type': type, # limit or market
1608
1609
  'leverage': 1,
1609
1610
  }
1611
+ marginModeUpper = self.safe_string_upper(params, 'marginMode')
1612
+ if marginModeUpper is not None:
1613
+ params = self.omit(params, 'marginMode')
1614
+ request['marginMode'] = marginModeUpper
1610
1615
  cost = self.safe_string(params, 'cost')
1611
1616
  params = self.omit(params, 'cost')
1612
1617
  if cost is not None:
@@ -876,7 +876,7 @@ class lbank(Exchange, ImplicitAPI):
876
876
  timestamp = self.milliseconds()
877
877
  if market['swap']:
878
878
  return self.parse_order_book(orderbook, market['symbol'], timestamp, 'bids', 'asks', 'price', 'volume')
879
- return self.parse_order_book(orderbook, market['symbol'], timestamp)
879
+ return self.parse_order_book(orderbook, market['symbol'], timestamp, 'bids', 'asks', 1, 0)
880
880
 
881
881
  def parse_trade(self, trade: dict, market: Market = None) -> Trade:
882
882
  #
ccxt/async_support/okx.py CHANGED
@@ -1648,7 +1648,6 @@ class okx(Exchange, ImplicitAPI):
1648
1648
  ymd = self.yymmdd(expiry)
1649
1649
  symbol = symbol + '-' + ymd + '-' + strikePrice + '-' + optionType
1650
1650
  optionType = 'put' if (optionType == 'P') else 'call'
1651
- tickSize = self.safe_string(market, 'tickSz')
1652
1651
  fees = self.safe_dict_2(self.fees, type, 'trading', {})
1653
1652
  maxLeverage = self.safe_string(market, 'lever', '1')
1654
1653
  maxLeverage = Precise.string_max(maxLeverage, '1')
@@ -1680,7 +1679,7 @@ class okx(Exchange, ImplicitAPI):
1680
1679
  'created': self.safe_integer(market, 'listTime'),
1681
1680
  'precision': {
1682
1681
  'amount': self.safe_number(market, 'lotSz'),
1683
- 'price': self.parse_number(tickSize),
1682
+ 'price': self.safe_number(market, 'tickSz'),
1684
1683
  },
1685
1684
  'limits': {
1686
1685
  'leverage': {
@@ -84,7 +84,7 @@ class oxfun(Exchange, ImplicitAPI):
84
84
  'fetchDepositWithdrawFee': False,
85
85
  'fetchDepositWithdrawFees': False,
86
86
  'fetchFundingHistory': True,
87
- 'fetchFundingRate': 'emulated',
87
+ 'fetchFundingRate': True,
88
88
  'fetchFundingRateHistory': True,
89
89
  'fetchFundingRates': True,
90
90
  'fetchIndexOHLCV': False,
@@ -1104,6 +1104,26 @@ class oxfun(Exchange, ImplicitAPI):
1104
1104
  data = self.safe_list(response, 'data', [])
1105
1105
  return self.parse_funding_rates(data, symbols)
1106
1106
 
1107
+ async def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
1108
+ """
1109
+ fetch the current funding rates for a symbol
1110
+
1111
+ https://docs.ox.fun/?json#get-v3-funding-estimates
1112
+
1113
+ :param str symbol: unified market symbols
1114
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1115
+ :returns Order[]: an array of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-structure>`
1116
+ """
1117
+ await self.load_markets()
1118
+ request: dict = {
1119
+ 'marketCode': self.market_id(symbol),
1120
+ }
1121
+ response = await self.publicGetV3FundingEstimates(self.extend(request, params))
1122
+ #
1123
+ data = self.safe_list(response, 'data', [])
1124
+ first = self.safe_dict(data, 0, {})
1125
+ return self.parse_funding_rate(first, self.market(symbol))
1126
+
1107
1127
  def parse_funding_rate(self, fundingRate, market: Market = None) -> FundingRate:
1108
1128
  #
1109
1129
  # {
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.paradex import ImplicitAPI
8
- from ccxt.base.types import Any, Balances, Currency, Int, Leverage, MarginMode, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction
8
+ from ccxt.base.types import Any, Balances, Currency, Greeks, Int, Leverage, MarginMode, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import AuthenticationError
@@ -75,6 +75,7 @@ class paradex(Exchange, ImplicitAPI):
75
75
  'fetchFundingRate': False,
76
76
  'fetchFundingRateHistory': False,
77
77
  'fetchFundingRates': False,
78
+ 'fetchGreeks': True,
78
79
  'fetchIndexOHLCV': False,
79
80
  'fetchIsolatedBorrowRate': False,
80
81
  'fetchIsolatedBorrowRates': False,
@@ -558,13 +559,14 @@ class paradex(Exchange, ImplicitAPI):
558
559
  expiry = self.safe_integer(market, 'expiry_at')
559
560
  optionType = self.safe_string(market, 'option_type')
560
561
  strikePrice = self.safe_string(market, 'strike_price')
562
+ takerFee = self.parse_number('0.0003')
563
+ makerFee = self.parse_number('-0.00005')
561
564
  if isOption:
562
565
  optionTypeSuffix = 'C' if (optionType == 'CALL') else 'P'
563
566
  symbol = symbol + '-' + strikePrice + '-' + optionTypeSuffix
567
+ makerFee = self.parse_number('0.0003')
564
568
  else:
565
569
  expiry = None
566
- takerFee = self.parse_number('0.0003')
567
- makerFee = self.parse_number('-0.00005')
568
570
  return self.safe_market_structure({
569
571
  'id': marketId,
570
572
  'symbol': symbol,
@@ -1262,7 +1264,7 @@ class paradex(Exchange, ImplicitAPI):
1262
1264
  'status': self.parse_order_status(status),
1263
1265
  'symbol': symbol,
1264
1266
  'type': self.parse_order_type(orderType),
1265
- 'timeInForce': self.parse_time_in_force(self.safe_string(order, 'instrunction')),
1267
+ 'timeInForce': self.parse_time_in_force(self.safe_string(order, 'instruction')),
1266
1268
  'postOnly': None,
1267
1269
  'reduceOnly': reduceOnly,
1268
1270
  'side': side,
@@ -2284,6 +2286,120 @@ class paradex(Exchange, ImplicitAPI):
2284
2286
  }
2285
2287
  return await self.privatePostAccountMarginMarket(self.extend(request, params))
2286
2288
 
2289
+ async def fetch_greeks(self, symbol: str, params={}) -> Greeks:
2290
+ """
2291
+ fetches an option contracts greeks, financial metrics used to measure the factors that affect the price of an options contract
2292
+
2293
+ https://docs.api.testnet.paradex.trade/#list-available-markets-summary
2294
+
2295
+ :param str symbol: unified symbol of the market to fetch greeks for
2296
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2297
+ :returns dict: a `greeks structure <https://docs.ccxt.com/#/?id=greeks-structure>`
2298
+ """
2299
+ await self.load_markets()
2300
+ market = self.market(symbol)
2301
+ request: dict = {
2302
+ 'market': market['id'],
2303
+ }
2304
+ response = await self.publicGetMarketsSummary(self.extend(request, params))
2305
+ #
2306
+ # {
2307
+ # "results": [
2308
+ # {
2309
+ # "symbol": "BTC-USD-114000-P",
2310
+ # "mark_price": "10835.66892602",
2311
+ # "mark_iv": "0.71781855",
2312
+ # "delta": "-0.98726024",
2313
+ # "greeks": {
2314
+ # "delta": "-0.9872602390817709",
2315
+ # "gamma": "0.000004560958862297231",
2316
+ # "vega": "227.11344863639806",
2317
+ # "rho": "-302.0617972461581",
2318
+ # "vanna": "0.06609830491614832",
2319
+ # "volga": "925.9501532805552"
2320
+ # },
2321
+ # "last_traded_price": "10551.5",
2322
+ # "bid": "10794.9",
2323
+ # "bid_iv": "0.05",
2324
+ # "ask": "10887.3",
2325
+ # "ask_iv": "0.8783283",
2326
+ # "last_iv": "0.05",
2327
+ # "volume_24h": "0",
2328
+ # "total_volume": "195240.72672261014",
2329
+ # "created_at": 1747644009995,
2330
+ # "underlying_price": "103164.79162649",
2331
+ # "open_interest": "0",
2332
+ # "funding_rate": "0.000004464241170536191",
2333
+ # "price_change_rate_24h": "0.074915",
2334
+ # "future_funding_rate": "0.0001"
2335
+ # }
2336
+ # ]
2337
+ # }
2338
+ #
2339
+ data = self.safe_list(response, 'results', [])
2340
+ greeks = self.safe_dict(data, 0, {})
2341
+ return self.parse_greeks(greeks, market)
2342
+
2343
+ def parse_greeks(self, greeks: dict, market: Market = None) -> Greeks:
2344
+ #
2345
+ # {
2346
+ # "symbol": "BTC-USD-114000-P",
2347
+ # "mark_price": "10835.66892602",
2348
+ # "mark_iv": "0.71781855",
2349
+ # "delta": "-0.98726024",
2350
+ # "greeks": {
2351
+ # "delta": "-0.9872602390817709",
2352
+ # "gamma": "0.000004560958862297231",
2353
+ # "vega": "227.11344863639806",
2354
+ # "rho": "-302.0617972461581",
2355
+ # "vanna": "0.06609830491614832",
2356
+ # "volga": "925.9501532805552"
2357
+ # },
2358
+ # "last_traded_price": "10551.5",
2359
+ # "bid": "10794.9",
2360
+ # "bid_iv": "0.05",
2361
+ # "ask": "10887.3",
2362
+ # "ask_iv": "0.8783283",
2363
+ # "last_iv": "0.05",
2364
+ # "volume_24h": "0",
2365
+ # "total_volume": "195240.72672261014",
2366
+ # "created_at": 1747644009995,
2367
+ # "underlying_price": "103164.79162649",
2368
+ # "open_interest": "0",
2369
+ # "funding_rate": "0.000004464241170536191",
2370
+ # "price_change_rate_24h": "0.074915",
2371
+ # "future_funding_rate": "0.0001"
2372
+ # }
2373
+ #
2374
+ marketId = self.safe_string(greeks, 'symbol')
2375
+ market = self.safe_market(marketId, market, None, 'option')
2376
+ symbol = market['symbol']
2377
+ timestamp = self.safe_integer(greeks, 'created_at')
2378
+ greeksData = self.safe_dict(greeks, 'greeks', {})
2379
+ return {
2380
+ 'symbol': symbol,
2381
+ 'timestamp': timestamp,
2382
+ 'datetime': self.iso8601(timestamp),
2383
+ 'delta': self.safe_number(greeksData, 'delta'),
2384
+ 'gamma': self.safe_number(greeksData, 'gamma'),
2385
+ 'theta': None,
2386
+ 'vega': self.safe_number(greeksData, 'vega'),
2387
+ 'rho': self.safe_number(greeksData, 'rho'),
2388
+ 'vanna': self.safe_number(greeksData, 'vanna'),
2389
+ 'volga': self.safe_number(greeksData, 'volga'),
2390
+ 'bidSize': None,
2391
+ 'askSize': None,
2392
+ 'bidImpliedVolatility': self.safe_number(greeks, 'bid_iv'),
2393
+ 'askImpliedVolatility': self.safe_number(greeks, 'ask_iv'),
2394
+ 'markImpliedVolatility': self.safe_number(greeks, 'mark_iv'),
2395
+ 'bidPrice': self.safe_number(greeks, 'bid'),
2396
+ 'askPrice': self.safe_number(greeks, 'ask'),
2397
+ 'markPrice': self.safe_number(greeks, 'mark_price'),
2398
+ 'lastPrice': self.safe_number(greeks, 'last_traded_price'),
2399
+ 'underlyingPrice': self.safe_number(greeks, 'underlying_price'),
2400
+ 'info': greeks,
2401
+ }
2402
+
2287
2403
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2288
2404
  url = self.implode_hostname(self.urls['api'][self.version]) + '/' + self.implode_params(path, params)
2289
2405
  query = self.omit(params, self.extract_params(path))
ccxt/base/errors.py CHANGED
@@ -1,3 +1,9 @@
1
+ # ----------------------------------------------------------------------------
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+ # EDIT THE CORRESPONDENT .ts FILE INSTEAD
6
+
1
7
  error_hierarchy = {
2
8
  'BaseError': {
3
9
  'ExchangeError': {
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.80'
7
+ __version__ = '4.4.85'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -1000,7 +1000,7 @@ class Exchange(object):
1000
1000
  return string
1001
1001
 
1002
1002
  @staticmethod
1003
- def urlencode(params={}, doseq=False):
1003
+ def urlencode(params={}, doseq=False, sort=False):
1004
1004
  newParams = params.copy()
1005
1005
  for key, value in params.items():
1006
1006
  if isinstance(value, bool):
@@ -1506,6 +1506,25 @@ class Exchange(object):
1506
1506
  return len(parts[1]) if len(parts) > 1 else 0
1507
1507
 
1508
1508
  def load_markets(self, reload=False, params={}):
1509
+ """
1510
+ Loads and prepares the markets for trading.
1511
+
1512
+ Args:
1513
+ reload (bool): If True, the markets will be reloaded from the exchange.
1514
+ params (dict): Additional exchange-specific parameters for the request.
1515
+
1516
+ Returns:
1517
+ dict: A dictionary of markets.
1518
+
1519
+ Raises:
1520
+ Exception: If the markets cannot be loaded or prepared.
1521
+
1522
+ Notes:
1523
+ It ensures that the markets are only loaded once, even if called multiple times.
1524
+ If the markets are already loaded and `reload` is False or not provided, it returns the existing markets.
1525
+ If a reload is in progress, it waits for completion before returning.
1526
+ If an error occurs during loading or preparation, an exception is raised.
1527
+ """
1509
1528
  if not reload:
1510
1529
  if self.markets:
1511
1530
  if not self.markets_by_id:
@@ -3008,7 +3027,7 @@ class Exchange(object):
3008
3027
  currency['networks'][key]['active'] = True
3009
3028
  elif deposit is not None and withdraw is not None:
3010
3029
  currency['networks'][key]['active'] = False
3011
- active = self.safe_bool(network, 'active')
3030
+ active = self.safe_bool(currency['networks'][key], 'active') # dict might have been updated on above lines, so access directly instead of `network` variable
3012
3031
  currencyActive = self.safe_bool(currency, 'active')
3013
3032
  if currencyActive is None or active:
3014
3033
  currency['active'] = active
@@ -5522,6 +5541,24 @@ class Exchange(object):
5522
5541
  def create_expired_option_market(self, symbol: str):
5523
5542
  raise NotSupported(self.id + ' createExpiredOptionMarket() is not supported yet')
5524
5543
 
5544
+ def is_leveraged_currency(self, currencyCode, checkBaseCoin: Bool = False, existingCurrencies: dict = None):
5545
+ leverageSuffixes = [
5546
+ '2L', '2S', '3L', '3S', '4L', '4S', '5L', '5S', # Leveraged Tokens(LT)
5547
+ 'UP', 'DOWN', # exchange-specific(e.g. BLVT)
5548
+ 'BULL', 'BEAR', # similar
5549
+ ]
5550
+ for i in range(0, len(leverageSuffixes)):
5551
+ leverageSuffix = leverageSuffixes[i]
5552
+ if currencyCode.endswith(leverageSuffix):
5553
+ if not checkBaseCoin:
5554
+ return True
5555
+ else:
5556
+ # check if base currency is inside dict
5557
+ baseCurrencyCode = currencyCode.replace(leverageSuffix, '')
5558
+ if baseCurrencyCode in existingCurrencies:
5559
+ return True
5560
+ return False
5561
+
5525
5562
  def handle_withdraw_tag_and_params(self, tag, params):
5526
5563
  if (tag is not None) and (isinstance(tag, dict)):
5527
5564
  params = self.extend(tag, params)
ccxt/base/types.py CHANGED
@@ -308,6 +308,9 @@ class Greeks(TypedDict):
308
308
  theta: Num
309
309
  vega: Num
310
310
  rho: Num
311
+ vanna: Num
312
+ volga: Num
313
+ charm: Num
311
314
  bidSize: Num
312
315
  askSize: Num
313
316
  bidImpliedVolatility: Num
ccxt/bigone.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bigone import ImplicitAPI
8
- from ccxt.base.types import Any, Balances, Bool, Currencies, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
8
+ from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import AuthenticationError
@@ -509,19 +509,15 @@ class bigone(Exchange, ImplicitAPI):
509
509
  id = self.safe_string(currency, 'symbol')
510
510
  code = self.safe_currency_code(id)
511
511
  name = self.safe_string(currency, 'name')
512
- type = 'fiat' if self.safe_bool(currency, 'is_fiat') else 'crypto'
513
512
  networks: dict = {}
514
513
  chains = self.safe_list(currency, 'binding_gateways', [])
515
514
  currencyMaxPrecision = self.parse_precision(self.safe_string_2(currency, 'withdrawal_scale', 'scale'))
516
- currencyDepositEnabled: Bool = None
517
- currencyWithdrawEnabled: Bool = None
518
515
  for j in range(0, len(chains)):
519
516
  chain = chains[j]
520
517
  networkId = self.safe_string(chain, 'gateway_name')
521
518
  networkCode = self.network_id_to_code(networkId)
522
519
  deposit = self.safe_bool(chain, 'is_deposit_enabled')
523
520
  withdraw = self.safe_bool(chain, 'is_withdrawal_enabled')
524
- isActive = (deposit and withdraw)
525
521
  minDepositAmount = self.safe_string(chain, 'min_deposit_amount')
526
522
  minWithdrawalAmount = self.safe_string(chain, 'min_withdrawal_amount')
527
523
  withdrawalFee = self.safe_string(chain, 'withdrawal_fee')
@@ -532,7 +528,7 @@ class bigone(Exchange, ImplicitAPI):
532
528
  'margin': None,
533
529
  'deposit': deposit,
534
530
  'withdraw': withdraw,
535
- 'active': isActive,
531
+ 'active': None,
536
532
  'fee': self.parse_number(withdrawalFee),
537
533
  'precision': self.parse_number(precision),
538
534
  'limits': {
@@ -547,19 +543,26 @@ class bigone(Exchange, ImplicitAPI):
547
543
  },
548
544
  'info': chain,
549
545
  }
550
- # fill global values
551
- currencyDepositEnabled = (currencyDepositEnabled is None) or deposit if deposit else currencyDepositEnabled
552
- currencyWithdrawEnabled = (currencyWithdrawEnabled is None) or withdraw if withdraw else currencyWithdrawEnabled
553
- currencyMaxPrecision = (currencyMaxPrecision is None) or precision if Precise.string_gt(currencyMaxPrecision, precision) else currencyMaxPrecision
554
- result[code] = {
546
+ chainLength = len(chains)
547
+ type: Str = None
548
+ if self.safe_bool(currency, 'is_fiat'):
549
+ type = 'fiat'
550
+ elif chainLength == 0:
551
+ if self.is_leveraged_currency(id):
552
+ type = 'leveraged'
553
+ else:
554
+ type = 'other'
555
+ else:
556
+ type = 'crypto'
557
+ result[code] = self.safe_currency_structure({
555
558
  'id': id,
556
559
  'code': code,
557
560
  'info': currency,
558
561
  'name': name,
559
562
  'type': type,
560
563
  'active': None,
561
- 'deposit': currencyDepositEnabled,
562
- 'withdraw': currencyWithdrawEnabled,
564
+ 'deposit': None,
565
+ 'withdraw': None,
563
566
  'fee': None,
564
567
  'precision': self.parse_number(currencyMaxPrecision),
565
568
  'limits': {
@@ -573,7 +576,7 @@ class bigone(Exchange, ImplicitAPI):
573
576
  },
574
577
  },
575
578
  'networks': networks,
576
- }
579
+ })
577
580
  return result
578
581
 
579
582
  def fetch_markets(self, params={}) -> List[Market]:
ccxt/bingx.py CHANGED
@@ -766,56 +766,41 @@ class bingx(Exchange, ImplicitAPI):
766
766
  name = self.safe_string(entry, 'name')
767
767
  networkList = self.safe_list(entry, 'networkList')
768
768
  networks: dict = {}
769
- fee = None
770
- depositEnabled = False
771
- withdrawEnabled = False
772
- defaultLimits: dict = {}
773
769
  for j in range(0, len(networkList)):
774
770
  rawNetwork = networkList[j]
775
771
  network = self.safe_string(rawNetwork, 'network')
776
772
  networkCode = self.network_id_to_code(network)
777
- isDefault = self.safe_bool(rawNetwork, 'isDefault')
778
- networkDepositEnabled = self.safe_bool(rawNetwork, 'depositEnable')
779
- if networkDepositEnabled:
780
- depositEnabled = True
781
- networkWithdrawEnabled = self.safe_bool(rawNetwork, 'withdrawEnable')
782
- if networkWithdrawEnabled:
783
- withdrawEnabled = True
784
773
  limits: dict = {
785
774
  'withdraw': {
786
775
  'min': self.safe_number(rawNetwork, 'withdrawMin'),
787
776
  'max': self.safe_number(rawNetwork, 'withdrawMax'),
788
777
  },
789
778
  }
790
- fee = self.safe_number(rawNetwork, 'withdrawFee')
791
- if isDefault:
792
- defaultLimits = limits
793
- precision = self.safe_number(rawNetwork, 'withdrawPrecision')
794
- networkActive = networkDepositEnabled or networkWithdrawEnabled
779
+ precision = self.parse_number(self.parse_precision(self.safe_string(rawNetwork, 'withdrawPrecision')))
795
780
  networks[networkCode] = {
796
781
  'info': rawNetwork,
797
782
  'id': network,
798
783
  'network': networkCode,
799
- 'fee': fee,
800
- 'active': networkActive,
801
- 'deposit': networkDepositEnabled,
802
- 'withdraw': networkWithdrawEnabled,
784
+ 'fee': self.safe_number(rawNetwork, 'withdrawFee'),
785
+ 'active': None,
786
+ 'deposit': self.safe_bool(rawNetwork, 'depositEnable'),
787
+ 'withdraw': self.safe_bool(rawNetwork, 'withdrawEnable'),
803
788
  'precision': precision,
804
789
  'limits': limits,
805
790
  }
806
- active = depositEnabled or withdrawEnabled
807
791
  result[code] = self.safe_currency_structure({
808
792
  'info': entry,
809
793
  'code': code,
810
794
  'id': currencyId,
811
795
  'precision': None,
812
796
  'name': name,
813
- 'active': active,
814
- 'deposit': depositEnabled,
815
- 'withdraw': withdrawEnabled,
797
+ 'active': None,
798
+ 'deposit': None,
799
+ 'withdraw': None,
816
800
  'networks': networks,
817
- 'fee': fee,
818
- 'limits': defaultLimits,
801
+ 'fee': None,
802
+ 'limits': None,
803
+ 'type': 'crypto', # only cryptos now
819
804
  })
820
805
  return result
821
806
 
@@ -5535,18 +5520,14 @@ class bingx(Exchange, ImplicitAPI):
5535
5520
  :param str address: the address to withdraw to
5536
5521
  :param str [tag]:
5537
5522
  :param dict [params]: extra parameters specific to the exchange API endpoint
5538
- :param int [params.walletType]: 1 fund account, 2 standard account, 3 perpetual account
5523
+ :param int [params.walletType]: 1 fund account, 2 standard account, 3 perpetual account, 15 spot account
5539
5524
  :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
5540
5525
  """
5541
5526
  tag, params = self.handle_withdraw_tag_and_params(tag, params)
5542
5527
  self.check_address(address)
5543
5528
  self.load_markets()
5544
5529
  currency = self.currency(code)
5545
- walletType = self.safe_integer(params, 'walletType')
5546
- if walletType is None:
5547
- walletType = 1
5548
- if not self.in_array(walletType, [1, 2, 3]):
5549
- raise BadRequest(self.id + ' withdraw() requires either 1 fund account, 2 standard futures account, 3 perpetual account for walletType')
5530
+ walletType = self.safe_integer(params, 'walletType', 1)
5550
5531
  request: dict = {
5551
5532
  'coin': currency['id'],
5552
5533
  'address': address,