ccxt 4.4.96__py2.py3-none-any.whl → 4.4.98__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 (67) hide show
  1. ccxt/__init__.py +2 -1
  2. ccxt/abstract/binance.py +3 -0
  3. ccxt/abstract/binancecoinm.py +3 -0
  4. ccxt/abstract/binanceus.py +3 -0
  5. ccxt/abstract/binanceusdm.py +3 -0
  6. ccxt/abstract/phemex.py +1 -0
  7. ccxt/async_support/__init__.py +2 -1
  8. ccxt/async_support/base/exchange.py +6 -3
  9. ccxt/async_support/binance.py +90 -34
  10. ccxt/async_support/binancecoinm.py +5 -1
  11. ccxt/async_support/binanceus.py +3 -1
  12. ccxt/async_support/binanceusdm.py +3 -1
  13. ccxt/async_support/bingx.py +1 -1
  14. ccxt/async_support/bitget.py +14 -2
  15. ccxt/async_support/coinmetro.py +2 -3
  16. ccxt/async_support/cryptocom.py +77 -2
  17. ccxt/async_support/exmo.py +1 -1
  18. ccxt/async_support/foxbit.py +1 -1
  19. ccxt/async_support/gate.py +1 -2
  20. ccxt/async_support/hashkey.py +39 -0
  21. ccxt/async_support/hyperliquid.py +40 -25
  22. ccxt/async_support/independentreserve.py +35 -0
  23. ccxt/async_support/indodax.py +34 -0
  24. ccxt/async_support/kucoin.py +2 -1
  25. ccxt/async_support/latoken.py +42 -0
  26. ccxt/async_support/luno.py +36 -0
  27. ccxt/async_support/mercado.py +34 -0
  28. ccxt/async_support/mexc.py +3 -19
  29. ccxt/async_support/ndax.py +8 -0
  30. ccxt/async_support/okx.py +2 -0
  31. ccxt/async_support/phemex.py +36 -31
  32. ccxt/base/decimal_to_precision.py +14 -10
  33. ccxt/base/errors.py +6 -0
  34. ccxt/base/exchange.py +55 -15
  35. ccxt/binance.py +90 -34
  36. ccxt/binancecoinm.py +5 -1
  37. ccxt/binanceus.py +3 -1
  38. ccxt/binanceusdm.py +3 -1
  39. ccxt/bingx.py +1 -1
  40. ccxt/bitget.py +14 -2
  41. ccxt/coinmetro.py +2 -3
  42. ccxt/cryptocom.py +77 -2
  43. ccxt/exmo.py +1 -1
  44. ccxt/foxbit.py +1 -1
  45. ccxt/gate.py +1 -2
  46. ccxt/hashkey.py +39 -0
  47. ccxt/hyperliquid.py +40 -25
  48. ccxt/independentreserve.py +35 -0
  49. ccxt/indodax.py +34 -0
  50. ccxt/kucoin.py +2 -1
  51. ccxt/latoken.py +42 -0
  52. ccxt/luno.py +36 -0
  53. ccxt/mercado.py +34 -0
  54. ccxt/mexc.py +3 -19
  55. ccxt/ndax.py +8 -0
  56. ccxt/okx.py +2 -0
  57. ccxt/phemex.py +36 -31
  58. ccxt/pro/__init__.py +2 -1
  59. ccxt/pro/binancecoinm.py +3 -1
  60. ccxt/pro/binanceus.py +3 -1
  61. ccxt/pro/binanceusdm.py +3 -1
  62. ccxt/pro/bybit.py +33 -1
  63. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/METADATA +16 -16
  64. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/RECORD +67 -67
  65. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/LICENSE.txt +0 -0
  66. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/WHEEL +0 -0
  67. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/top_level.txt +0 -0
ccxt/__init__.py CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  # ----------------------------------------------------------------------------
24
24
 
25
- __version__ = '4.4.96'
25
+ __version__ = '4.4.98'
26
26
 
27
27
  # ----------------------------------------------------------------------------
28
28
 
@@ -55,6 +55,7 @@ from ccxt.base.errors import NoChange # noqa: F4
55
55
  from ccxt.base.errors import MarginModeAlreadySet # noqa: F401
56
56
  from ccxt.base.errors import MarketClosed # noqa: F401
57
57
  from ccxt.base.errors import ManualInteractionNeeded # noqa: F401
58
+ from ccxt.base.errors import RestrictedLocation # noqa: F401
58
59
  from ccxt.base.errors import InsufficientFunds # noqa: F401
59
60
  from ccxt.base.errors import InvalidAddress # noqa: F401
60
61
  from ccxt.base.errors import AddressPending # noqa: F401
ccxt/abstract/binance.py CHANGED
@@ -222,6 +222,7 @@ class ImplicitAPI:
222
222
  sapi_get_portfolio_balance = sapiGetPortfolioBalance = Entry('portfolio/balance', 'sapi', 'GET', {'cost': 2})
223
223
  sapi_get_portfolio_negative_balance_exchange_record = sapiGetPortfolioNegativeBalanceExchangeRecord = Entry('portfolio/negative-balance-exchange-record', 'sapi', 'GET', {'cost': 2})
224
224
  sapi_get_portfolio_pmloan_history = sapiGetPortfolioPmloanHistory = Entry('portfolio/pmloan-history', 'sapi', 'GET', {'cost': 5})
225
+ sapi_get_portfolio_earn_asset_balance = sapiGetPortfolioEarnAssetBalance = Entry('portfolio/earn-asset-balance', 'sapi', 'GET', {'cost': 150})
225
226
  sapi_get_staking_productlist = sapiGetStakingProductList = Entry('staking/productList', 'sapi', 'GET', {'cost': 0.1})
226
227
  sapi_get_staking_position = sapiGetStakingPosition = Entry('staking/position', 'sapi', 'GET', {'cost': 0.1})
227
228
  sapi_get_staking_stakingrecord = sapiGetStakingStakingRecord = Entry('staking/stakingRecord', 'sapi', 'GET', {'cost': 0.1})
@@ -364,6 +365,7 @@ class ImplicitAPI:
364
365
  sapi_post_portfolio_repay_futures_negative_balance = sapiPostPortfolioRepayFuturesNegativeBalance = Entry('portfolio/repay-futures-negative-balance', 'sapi', 'POST', {'cost': 150})
365
366
  sapi_post_portfolio_mint = sapiPostPortfolioMint = Entry('portfolio/mint', 'sapi', 'POST', {'cost': 20})
366
367
  sapi_post_portfolio_redeem = sapiPostPortfolioRedeem = Entry('portfolio/redeem', 'sapi', 'POST', {'cost': 20})
368
+ sapi_post_portfolio_earn_asset_transfer = sapiPostPortfolioEarnAssetTransfer = Entry('portfolio/earn-asset-transfer', 'sapi', 'POST', {'cost': 150})
367
369
  sapi_post_lending_auto_invest_plan_add = sapiPostLendingAutoInvestPlanAdd = Entry('lending/auto-invest/plan/add', 'sapi', 'POST', {'cost': 0.1})
368
370
  sapi_post_lending_auto_invest_plan_edit = sapiPostLendingAutoInvestPlanEdit = Entry('lending/auto-invest/plan/edit', 'sapi', 'POST', {'cost': 0.1})
369
371
  sapi_post_lending_auto_invest_plan_edit_status = sapiPostLendingAutoInvestPlanEditStatus = Entry('lending/auto-invest/plan/edit-status', 'sapi', 'POST', {'cost': 0.1})
@@ -502,6 +504,7 @@ class ImplicitAPI:
502
504
  fapipublic_get_apitradingstatus = fapiPublicGetApiTradingStatus = Entry('apiTradingStatus', 'fapiPublic', 'GET', {'cost': 1, 'noSymbol': 10})
503
505
  fapipublic_get_lvtklines = fapiPublicGetLvtKlines = Entry('lvtKlines', 'fapiPublic', 'GET', {'cost': 1})
504
506
  fapipublic_get_convert_exchangeinfo = fapiPublicGetConvertExchangeInfo = Entry('convert/exchangeInfo', 'fapiPublic', 'GET', {'cost': 4})
507
+ fapipublic_get_insurancebalance = fapiPublicGetInsuranceBalance = Entry('insuranceBalance', 'fapiPublic', 'GET', {'cost': 1})
505
508
  fapidata_get_delivery_price = fapiDataGetDeliveryPrice = Entry('delivery-price', 'fapiData', 'GET', {'cost': 1})
506
509
  fapidata_get_openinteresthist = fapiDataGetOpenInterestHist = Entry('openInterestHist', 'fapiData', 'GET', {'cost': 1})
507
510
  fapidata_get_toplongshortaccountratio = fapiDataGetTopLongShortAccountRatio = Entry('topLongShortAccountRatio', 'fapiData', 'GET', {'cost': 1})
@@ -222,6 +222,7 @@ class ImplicitAPI:
222
222
  sapi_get_portfolio_balance = sapiGetPortfolioBalance = Entry('portfolio/balance', 'sapi', 'GET', {'cost': 2})
223
223
  sapi_get_portfolio_negative_balance_exchange_record = sapiGetPortfolioNegativeBalanceExchangeRecord = Entry('portfolio/negative-balance-exchange-record', 'sapi', 'GET', {'cost': 2})
224
224
  sapi_get_portfolio_pmloan_history = sapiGetPortfolioPmloanHistory = Entry('portfolio/pmloan-history', 'sapi', 'GET', {'cost': 5})
225
+ sapi_get_portfolio_earn_asset_balance = sapiGetPortfolioEarnAssetBalance = Entry('portfolio/earn-asset-balance', 'sapi', 'GET', {'cost': 150})
225
226
  sapi_get_staking_productlist = sapiGetStakingProductList = Entry('staking/productList', 'sapi', 'GET', {'cost': 0.1})
226
227
  sapi_get_staking_position = sapiGetStakingPosition = Entry('staking/position', 'sapi', 'GET', {'cost': 0.1})
227
228
  sapi_get_staking_stakingrecord = sapiGetStakingStakingRecord = Entry('staking/stakingRecord', 'sapi', 'GET', {'cost': 0.1})
@@ -364,6 +365,7 @@ class ImplicitAPI:
364
365
  sapi_post_portfolio_repay_futures_negative_balance = sapiPostPortfolioRepayFuturesNegativeBalance = Entry('portfolio/repay-futures-negative-balance', 'sapi', 'POST', {'cost': 150})
365
366
  sapi_post_portfolio_mint = sapiPostPortfolioMint = Entry('portfolio/mint', 'sapi', 'POST', {'cost': 20})
366
367
  sapi_post_portfolio_redeem = sapiPostPortfolioRedeem = Entry('portfolio/redeem', 'sapi', 'POST', {'cost': 20})
368
+ sapi_post_portfolio_earn_asset_transfer = sapiPostPortfolioEarnAssetTransfer = Entry('portfolio/earn-asset-transfer', 'sapi', 'POST', {'cost': 150})
367
369
  sapi_post_lending_auto_invest_plan_add = sapiPostLendingAutoInvestPlanAdd = Entry('lending/auto-invest/plan/add', 'sapi', 'POST', {'cost': 0.1})
368
370
  sapi_post_lending_auto_invest_plan_edit = sapiPostLendingAutoInvestPlanEdit = Entry('lending/auto-invest/plan/edit', 'sapi', 'POST', {'cost': 0.1})
369
371
  sapi_post_lending_auto_invest_plan_edit_status = sapiPostLendingAutoInvestPlanEditStatus = Entry('lending/auto-invest/plan/edit-status', 'sapi', 'POST', {'cost': 0.1})
@@ -502,6 +504,7 @@ class ImplicitAPI:
502
504
  fapipublic_get_apitradingstatus = fapiPublicGetApiTradingStatus = Entry('apiTradingStatus', 'fapiPublic', 'GET', {'cost': 1, 'noSymbol': 10})
503
505
  fapipublic_get_lvtklines = fapiPublicGetLvtKlines = Entry('lvtKlines', 'fapiPublic', 'GET', {'cost': 1})
504
506
  fapipublic_get_convert_exchangeinfo = fapiPublicGetConvertExchangeInfo = Entry('convert/exchangeInfo', 'fapiPublic', 'GET', {'cost': 4})
507
+ fapipublic_get_insurancebalance = fapiPublicGetInsuranceBalance = Entry('insuranceBalance', 'fapiPublic', 'GET', {'cost': 1})
505
508
  fapidata_get_delivery_price = fapiDataGetDeliveryPrice = Entry('delivery-price', 'fapiData', 'GET', {'cost': 1})
506
509
  fapidata_get_openinteresthist = fapiDataGetOpenInterestHist = Entry('openInterestHist', 'fapiData', 'GET', {'cost': 1})
507
510
  fapidata_get_toplongshortaccountratio = fapiDataGetTopLongShortAccountRatio = Entry('topLongShortAccountRatio', 'fapiData', 'GET', {'cost': 1})
@@ -222,6 +222,7 @@ class ImplicitAPI:
222
222
  sapi_get_portfolio_balance = sapiGetPortfolioBalance = Entry('portfolio/balance', 'sapi', 'GET', {'cost': 2})
223
223
  sapi_get_portfolio_negative_balance_exchange_record = sapiGetPortfolioNegativeBalanceExchangeRecord = Entry('portfolio/negative-balance-exchange-record', 'sapi', 'GET', {'cost': 2})
224
224
  sapi_get_portfolio_pmloan_history = sapiGetPortfolioPmloanHistory = Entry('portfolio/pmloan-history', 'sapi', 'GET', {'cost': 5})
225
+ sapi_get_portfolio_earn_asset_balance = sapiGetPortfolioEarnAssetBalance = Entry('portfolio/earn-asset-balance', 'sapi', 'GET', {'cost': 150})
225
226
  sapi_get_staking_productlist = sapiGetStakingProductList = Entry('staking/productList', 'sapi', 'GET', {'cost': 0.1})
226
227
  sapi_get_staking_position = sapiGetStakingPosition = Entry('staking/position', 'sapi', 'GET', {'cost': 0.1})
227
228
  sapi_get_staking_stakingrecord = sapiGetStakingStakingRecord = Entry('staking/stakingRecord', 'sapi', 'GET', {'cost': 0.1})
@@ -395,6 +396,7 @@ class ImplicitAPI:
395
396
  sapi_post_portfolio_repay_futures_negative_balance = sapiPostPortfolioRepayFuturesNegativeBalance = Entry('portfolio/repay-futures-negative-balance', 'sapi', 'POST', {'cost': 150})
396
397
  sapi_post_portfolio_mint = sapiPostPortfolioMint = Entry('portfolio/mint', 'sapi', 'POST', {'cost': 20})
397
398
  sapi_post_portfolio_redeem = sapiPostPortfolioRedeem = Entry('portfolio/redeem', 'sapi', 'POST', {'cost': 20})
399
+ sapi_post_portfolio_earn_asset_transfer = sapiPostPortfolioEarnAssetTransfer = Entry('portfolio/earn-asset-transfer', 'sapi', 'POST', {'cost': 150})
398
400
  sapi_post_lending_auto_invest_plan_add = sapiPostLendingAutoInvestPlanAdd = Entry('lending/auto-invest/plan/add', 'sapi', 'POST', {'cost': 0.1})
399
401
  sapi_post_lending_auto_invest_plan_edit = sapiPostLendingAutoInvestPlanEdit = Entry('lending/auto-invest/plan/edit', 'sapi', 'POST', {'cost': 0.1})
400
402
  sapi_post_lending_auto_invest_plan_edit_status = sapiPostLendingAutoInvestPlanEditStatus = Entry('lending/auto-invest/plan/edit-status', 'sapi', 'POST', {'cost': 0.1})
@@ -554,6 +556,7 @@ class ImplicitAPI:
554
556
  fapipublic_get_apitradingstatus = fapiPublicGetApiTradingStatus = Entry('apiTradingStatus', 'fapiPublic', 'GET', {'cost': 1, 'noSymbol': 10})
555
557
  fapipublic_get_lvtklines = fapiPublicGetLvtKlines = Entry('lvtKlines', 'fapiPublic', 'GET', {'cost': 1})
556
558
  fapipublic_get_convert_exchangeinfo = fapiPublicGetConvertExchangeInfo = Entry('convert/exchangeInfo', 'fapiPublic', 'GET', {'cost': 4})
559
+ fapipublic_get_insurancebalance = fapiPublicGetInsuranceBalance = Entry('insuranceBalance', 'fapiPublic', 'GET', {'cost': 1})
557
560
  fapidata_get_delivery_price = fapiDataGetDeliveryPrice = Entry('delivery-price', 'fapiData', 'GET', {'cost': 1})
558
561
  fapidata_get_openinteresthist = fapiDataGetOpenInterestHist = Entry('openInterestHist', 'fapiData', 'GET', {'cost': 1})
559
562
  fapidata_get_toplongshortaccountratio = fapiDataGetTopLongShortAccountRatio = Entry('topLongShortAccountRatio', 'fapiData', 'GET', {'cost': 1})
@@ -222,6 +222,7 @@ class ImplicitAPI:
222
222
  sapi_get_portfolio_balance = sapiGetPortfolioBalance = Entry('portfolio/balance', 'sapi', 'GET', {'cost': 2})
223
223
  sapi_get_portfolio_negative_balance_exchange_record = sapiGetPortfolioNegativeBalanceExchangeRecord = Entry('portfolio/negative-balance-exchange-record', 'sapi', 'GET', {'cost': 2})
224
224
  sapi_get_portfolio_pmloan_history = sapiGetPortfolioPmloanHistory = Entry('portfolio/pmloan-history', 'sapi', 'GET', {'cost': 5})
225
+ sapi_get_portfolio_earn_asset_balance = sapiGetPortfolioEarnAssetBalance = Entry('portfolio/earn-asset-balance', 'sapi', 'GET', {'cost': 150})
225
226
  sapi_get_staking_productlist = sapiGetStakingProductList = Entry('staking/productList', 'sapi', 'GET', {'cost': 0.1})
226
227
  sapi_get_staking_position = sapiGetStakingPosition = Entry('staking/position', 'sapi', 'GET', {'cost': 0.1})
227
228
  sapi_get_staking_stakingrecord = sapiGetStakingStakingRecord = Entry('staking/stakingRecord', 'sapi', 'GET', {'cost': 0.1})
@@ -364,6 +365,7 @@ class ImplicitAPI:
364
365
  sapi_post_portfolio_repay_futures_negative_balance = sapiPostPortfolioRepayFuturesNegativeBalance = Entry('portfolio/repay-futures-negative-balance', 'sapi', 'POST', {'cost': 150})
365
366
  sapi_post_portfolio_mint = sapiPostPortfolioMint = Entry('portfolio/mint', 'sapi', 'POST', {'cost': 20})
366
367
  sapi_post_portfolio_redeem = sapiPostPortfolioRedeem = Entry('portfolio/redeem', 'sapi', 'POST', {'cost': 20})
368
+ sapi_post_portfolio_earn_asset_transfer = sapiPostPortfolioEarnAssetTransfer = Entry('portfolio/earn-asset-transfer', 'sapi', 'POST', {'cost': 150})
367
369
  sapi_post_lending_auto_invest_plan_add = sapiPostLendingAutoInvestPlanAdd = Entry('lending/auto-invest/plan/add', 'sapi', 'POST', {'cost': 0.1})
368
370
  sapi_post_lending_auto_invest_plan_edit = sapiPostLendingAutoInvestPlanEdit = Entry('lending/auto-invest/plan/edit', 'sapi', 'POST', {'cost': 0.1})
369
371
  sapi_post_lending_auto_invest_plan_edit_status = sapiPostLendingAutoInvestPlanEditStatus = Entry('lending/auto-invest/plan/edit-status', 'sapi', 'POST', {'cost': 0.1})
@@ -502,6 +504,7 @@ class ImplicitAPI:
502
504
  fapipublic_get_apitradingstatus = fapiPublicGetApiTradingStatus = Entry('apiTradingStatus', 'fapiPublic', 'GET', {'cost': 1, 'noSymbol': 10})
503
505
  fapipublic_get_lvtklines = fapiPublicGetLvtKlines = Entry('lvtKlines', 'fapiPublic', 'GET', {'cost': 1})
504
506
  fapipublic_get_convert_exchangeinfo = fapiPublicGetConvertExchangeInfo = Entry('convert/exchangeInfo', 'fapiPublic', 'GET', {'cost': 4})
507
+ fapipublic_get_insurancebalance = fapiPublicGetInsuranceBalance = Entry('insuranceBalance', 'fapiPublic', 'GET', {'cost': 1})
505
508
  fapidata_get_delivery_price = fapiDataGetDeliveryPrice = Entry('delivery-price', 'fapiData', 'GET', {'cost': 1})
506
509
  fapidata_get_openinteresthist = fapiDataGetOpenInterestHist = Entry('openInterestHist', 'fapiData', 'GET', {'cost': 1})
507
510
  fapidata_get_toplongshortaccountratio = fapiDataGetTopLongShortAccountRatio = Entry('topLongShortAccountRatio', 'fapiData', 'GET', {'cost': 1})
ccxt/abstract/phemex.py CHANGED
@@ -102,6 +102,7 @@ class ImplicitAPI:
102
102
  private_put_spot_orders = privatePutSpotOrders = Entry('spot/orders', 'private', 'PUT', {'cost': 1})
103
103
  private_put_orders_replace = privatePutOrdersReplace = Entry('orders/replace', 'private', 'PUT', {'cost': 1})
104
104
  private_put_g_orders_replace = privatePutGOrdersReplace = Entry('g-orders/replace', 'private', 'PUT', {'cost': 1})
105
+ private_put_g_orders_create = privatePutGOrdersCreate = Entry('g-orders/create', 'private', 'PUT', {'cost': 1})
105
106
  private_put_positions_leverage = privatePutPositionsLeverage = Entry('positions/leverage', 'private', 'PUT', {'cost': 5})
106
107
  private_put_g_positions_leverage = privatePutGPositionsLeverage = Entry('g-positions/leverage', 'private', 'PUT', {'cost': 5})
107
108
  private_put_g_positions_switch_pos_mode_sync = privatePutGPositionsSwitchPosModeSync = Entry('g-positions/switch-pos-mode-sync', 'private', 'PUT', {'cost': 5})
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.96'
7
+ __version__ = '4.4.98'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -34,6 +34,7 @@ from ccxt.base.errors import NoChange # noqa: F4
34
34
  from ccxt.base.errors import MarginModeAlreadySet # noqa: F401
35
35
  from ccxt.base.errors import MarketClosed # noqa: F401
36
36
  from ccxt.base.errors import ManualInteractionNeeded # noqa: F401
37
+ from ccxt.base.errors import RestrictedLocation # noqa: F401
37
38
  from ccxt.base.errors import InsufficientFunds # noqa: F401
38
39
  from ccxt.base.errors import InvalidAddress # noqa: F401
39
40
  from ccxt.base.errors import AddressPending # noqa: F401
@@ -2,7 +2,7 @@
2
2
 
3
3
  # -----------------------------------------------------------------------------
4
4
 
5
- __version__ = '4.4.96'
5
+ __version__ = '4.4.98'
6
6
 
7
7
  # -----------------------------------------------------------------------------
8
8
 
@@ -176,7 +176,7 @@ class Exchange(BaseExchange):
176
176
  if (socksProxy not in self.socks_proxy_sessions):
177
177
  # Create our SSL context object with our CA cert file
178
178
  self.open() # ensure `asyncio_loop` is set
179
- proxy_session = self.get_socks_proxy_session(socksProxy)
179
+ proxy_session = self.get_socks_proxy_session(socksProxy)
180
180
  # add aiohttp_proxy for python as exclusion
181
181
  elif self.aiohttp_proxy:
182
182
  final_proxy = self.aiohttp_proxy
@@ -670,6 +670,9 @@ class Exchange(BaseExchange):
670
670
  async def un_watch_order_book_for_symbols(self, symbols: List[str], params={}):
671
671
  raise NotSupported(self.id + ' unWatchOrderBookForSymbols() is not supported yet')
672
672
 
673
+ async def un_watch_positions(self, symbols: Strings = None, params={}):
674
+ raise NotSupported(self.id + ' unWatchPositions() is not supported yet')
675
+
673
676
  async def fetch_deposit_addresses(self, codes: Strings = None, params={}):
674
677
  raise NotSupported(self.id + ' fetchDepositAddresses() is not supported yet')
675
678
 
@@ -1894,7 +1897,7 @@ class Exchange(BaseExchange):
1894
1897
  calls = 0
1895
1898
  result = []
1896
1899
  errors = 0
1897
- until = self.safe_integer_2(params, 'untill', 'till') # do not omit it from params here
1900
+ until = self.safe_integer_n(params, ['until', 'untill', 'till']) # do not omit it from params here
1898
1901
  maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
1899
1902
  if (paginationDirection == 'forward'):
1900
1903
  if since is None:
@@ -506,6 +506,7 @@ class binance(Exchange, ImplicitAPI):
506
506
  'portfolio/balance': 2,
507
507
  'portfolio/negative-balance-exchange-record': 2,
508
508
  'portfolio/pmloan-history': 5,
509
+ 'portfolio/earn-asset-balance': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
509
510
  # staking
510
511
  'staking/productList': 0.1,
511
512
  'staking/position': 0.1,
@@ -664,6 +665,7 @@ class binance(Exchange, ImplicitAPI):
664
665
  'portfolio/repay-futures-negative-balance': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
665
666
  'portfolio/mint': 20,
666
667
  'portfolio/redeem': 20,
668
+ 'portfolio/earn-asset-transfer': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
667
669
  'lending/auto-invest/plan/add': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
668
670
  'lending/auto-invest/plan/edit': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
669
671
  'lending/auto-invest/plan/edit-status': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
@@ -852,6 +854,7 @@ class binance(Exchange, ImplicitAPI):
852
854
  'apiTradingStatus': {'cost': 1, 'noSymbol': 10},
853
855
  'lvtKlines': 1,
854
856
  'convert/exchangeInfo': 4,
857
+ 'insuranceBalance': 1,
855
858
  },
856
859
  },
857
860
  'fapiData': {
@@ -1289,12 +1292,14 @@ class binance(Exchange, ImplicitAPI):
1289
1292
  'options': {
1290
1293
  'sandboxMode': False,
1291
1294
  'fetchMargins': True,
1292
- 'fetchMarkets': [
1293
- 'spot', # allows CORS in browsers
1294
- 'linear', # allows CORS in browsers
1295
- 'inverse', # allows CORS in browsers
1296
- # 'option', # does not allow CORS, enable outside of the browser only
1297
- ],
1295
+ 'fetchMarkets': {
1296
+ 'types': [
1297
+ 'spot', # allows CORS in browsers
1298
+ 'linear', # allows CORS in browsers
1299
+ 'inverse', # allows CORS in browsers
1300
+ # 'option', # does not allow CORS, enable outside of the browser only
1301
+ ],
1302
+ },
1298
1303
  'loadAllOptions': False,
1299
1304
  'fetchCurrencies': True, # self is a private call and it requires API keys
1300
1305
  # 'fetchTradesMethod': 'publicGetAggTrades', # publicGetTrades, publicGetHistoricalTrades, eapiPublicGetTrades
@@ -3022,7 +3027,14 @@ class binance(Exchange, ImplicitAPI):
3022
3027
  :returns dict[]: an array of objects representing market data
3023
3028
  """
3024
3029
  promisesRaw = []
3025
- rawFetchMarkets = self.safe_list(self.options, 'fetchMarkets', ['spot', 'linear', 'inverse'])
3030
+ rawFetchMarkets = None
3031
+ defaultTypes = ['spot', 'linear', 'inverse']
3032
+ fetchMarketsOptions = self.safe_dict(self.options, 'fetchMarkets')
3033
+ if fetchMarketsOptions is not None:
3034
+ rawFetchMarkets = self.safe_list(fetchMarketsOptions, 'types', defaultTypes)
3035
+ else:
3036
+ # for backward-compatibility
3037
+ rawFetchMarkets = self.safe_list(self.options, 'fetchMarkets', defaultTypes)
3026
3038
  # handle loadAllOptions option
3027
3039
  loadAllOptions = self.safe_bool(self.options, 'loadAllOptions', False)
3028
3040
  if loadAllOptions:
@@ -3914,29 +3926,52 @@ class binance(Exchange, ImplicitAPI):
3914
3926
  # "time": 1597370495002
3915
3927
  # }
3916
3928
  #
3917
- # {
3918
- # "symbol": "ETHBTC",
3919
- # "priceChange": "0.00068700",
3920
- # "priceChangePercent": "2.075",
3921
- # "weightedAvgPrice": "0.03342681",
3922
- # "prevClosePrice": "0.03310300",
3923
- # "lastPrice": "0.03378900",
3924
- # "lastQty": "0.07700000",
3925
- # "bidPrice": "0.03378900",
3926
- # "bidQty": "7.16800000",
3927
- # "askPrice": "0.03379000",
3928
- # "askQty": "24.00000000",
3929
- # "openPrice": "0.03310200",
3930
- # "highPrice": "0.03388900",
3931
- # "lowPrice": "0.03306900",
3932
- # "volume": "205478.41000000",
3933
- # "quoteVolume": "6868.48826294",
3934
- # "openTime": 1601469986932,
3935
- # "closeTime": 1601556386932,
3936
- # "firstId": 196098772,
3937
- # "lastId": 196186315,
3938
- # "count": 87544
3939
- # }
3929
+ # spot - ticker
3930
+ #
3931
+ # {
3932
+ # "symbol": "BTCUSDT",
3933
+ # "priceChange": "-188.18000000",
3934
+ # "priceChangePercent": "-0.159",
3935
+ # "weightedAvgPrice": "118356.64734074",
3936
+ # "lastPrice": "118449.03000000",
3937
+ # "prevClosePrice": "118637.22000000", # field absent in rolling ticker
3938
+ # "lastQty": "0.00731000", # field absent in rolling ticker
3939
+ # "bidPrice": "118449.02000000", # field absent in rolling ticker
3940
+ # "bidQty": "7.15931000", # field absent in rolling ticker
3941
+ # "askPrice": "118449.03000000", # field absent in rolling ticker
3942
+ # "askQty": "0.09592000", # field absent in rolling ticker
3943
+ # "openPrice": "118637.21000000",
3944
+ # "highPrice": "119273.36000000",
3945
+ # "lowPrice": "117427.50000000",
3946
+ # "volume": "14741.41491000",
3947
+ # "quoteVolume": "1744744445.80640740",
3948
+ # "openTime": "1753701474013",
3949
+ # "closeTime": "1753787874013",
3950
+ # "firstId": "5116031635",
3951
+ # "lastId": "5117964946",
3952
+ # "count": "1933312"
3953
+ # }
3954
+ #
3955
+ # usdm tickers
3956
+ #
3957
+ # {
3958
+ # "symbol": "SUSDT",
3959
+ # "priceChange": "-0.0229000",
3960
+ # "priceChangePercent": "-6.777",
3961
+ # "weightedAvgPrice": "0.3210035",
3962
+ # "lastPrice": "0.3150000",
3963
+ # "lastQty": "16",
3964
+ # "openPrice": "0.3379000",
3965
+ # "highPrice": "0.3411000",
3966
+ # "lowPrice": "0.3071000",
3967
+ # "volume": "120588225",
3968
+ # "quoteVolume": "38709237.2289000",
3969
+ # "openTime": "1753701720000",
3970
+ # "closeTime": "1753788172414",
3971
+ # "firstId": "72234973",
3972
+ # "lastId": "72423677",
3973
+ # "count": "188700"
3974
+ # }
3940
3975
  #
3941
3976
  # coinm
3942
3977
  #
@@ -4287,16 +4322,37 @@ class binance(Exchange, ImplicitAPI):
4287
4322
  elif self.is_inverse(type, subType):
4288
4323
  response = await self.dapiPublicGetTicker24hr(params)
4289
4324
  elif type == 'spot':
4290
- request: dict = {}
4291
- if symbols is not None:
4292
- request['symbols'] = self.json(self.market_ids(symbols))
4293
- response = await self.publicGetTicker24hr(self.extend(request, params))
4325
+ rolling = self.safe_bool(params, 'rolling', False)
4326
+ params = self.omit(params, 'rolling')
4327
+ if rolling:
4328
+ symbols = self.market_symbols(symbols)
4329
+ request: dict = {
4330
+ 'symbols': self.json(self.market_ids(symbols)),
4331
+ }
4332
+ response = await self.publicGetTicker(self.extend(request, params))
4333
+ # parseTicker is not able to handle marketType for spot-rolling ticker fields, so we need custom parsing
4334
+ return self.parse_tickers_for_rolling(response, symbols)
4335
+ else:
4336
+ request: dict = {}
4337
+ if symbols is not None:
4338
+ request['symbols'] = self.json(self.market_ids(symbols))
4339
+ response = await self.publicGetTicker24hr(self.extend(request, params))
4294
4340
  elif type == 'option':
4295
4341
  response = await self.eapiPublicGetTicker(params)
4296
4342
  else:
4297
4343
  raise NotSupported(self.id + ' fetchTickers() does not support ' + type + ' markets yet')
4298
4344
  return self.parse_tickers(response, symbols)
4299
4345
 
4346
+ def parse_tickers_for_rolling(self, response, symbols):
4347
+ results = []
4348
+ for i in range(0, len(response)):
4349
+ marketId = self.safe_string(response[i], 'symbol')
4350
+ tickerMarket = self.safe_market(marketId, None, None, 'spot')
4351
+ parsedTicker = self.parse_ticker(response[i])
4352
+ parsedTicker['symbol'] = tickerMarket['symbol']
4353
+ results.append(parsedTicker)
4354
+ return self.filter_by_array(results, 'symbol', symbols)
4355
+
4300
4356
  async def fetch_mark_price(self, symbol: str, params={}) -> Ticker:
4301
4357
  """
4302
4358
  fetches mark price for the market
@@ -32,7 +32,11 @@ class binancecoinm(binance, ImplicitAPI):
32
32
  'createStopMarketOrder': True,
33
33
  },
34
34
  'options': {
35
- 'fetchMarkets': ['inverse'],
35
+ 'fetchMarkets': {
36
+ 'types': [
37
+ 'inverse',
38
+ ],
39
+ },
36
40
  'defaultSubType': 'inverse',
37
41
  'leverageBrackets': None,
38
42
  },
@@ -43,7 +43,9 @@ class binanceus(binance, ImplicitAPI):
43
43
  },
44
44
  },
45
45
  'options': {
46
- 'fetchMarkets': ['spot'],
46
+ 'fetchMarkets': {
47
+ 'types': ['spot'],
48
+ },
47
49
  'defaultType': 'spot',
48
50
  'fetchMargins': False,
49
51
  'quoteOrderQty': False,
@@ -33,7 +33,9 @@ class binanceusdm(binance, ImplicitAPI):
33
33
  'createStopMarketOrder': True,
34
34
  },
35
35
  'options': {
36
- 'fetchMarkets': ['linear'],
36
+ 'fetchMarkets': {
37
+ 'types': ['linear'],
38
+ },
37
39
  'defaultSubType': 'linear',
38
40
  # https://www.binance.com/en/support/faq/360033162192
39
41
  # tier amount, maintenance margin, initial margin,
@@ -5058,7 +5058,7 @@ class bingx(Exchange, ImplicitAPI):
5058
5058
  id = self.safe_string(transaction, 'id', dataId)
5059
5059
  address = self.safe_string(transaction, 'address')
5060
5060
  tag = self.safe_string(transaction, 'addressTag')
5061
- timestamp = self.safe_integer(transaction, 'insertTime')
5061
+ timestamp = self.safe_integer_2(transaction, 'insertTime', 'timestamp')
5062
5062
  datetime = self.iso8601(timestamp)
5063
5063
  if timestamp is None:
5064
5064
  datetime = self.safe_string(transaction, 'applyTime')
@@ -3817,6 +3817,9 @@ class bitget(Exchange, ImplicitAPI):
3817
3817
  if historicalEndpointNeeded:
3818
3818
  response = await self.publicSpotGetV2SpotMarketHistoryCandles(self.extend(request, params))
3819
3819
  else:
3820
+ if not limitDefined:
3821
+ request['limit'] = 1000
3822
+ limit = 1000
3820
3823
  response = await self.publicSpotGetV2SpotMarketCandles(self.extend(request, params))
3821
3824
  else:
3822
3825
  priceType = None
@@ -3825,8 +3828,14 @@ class bitget(Exchange, ImplicitAPI):
3825
3828
  productType, params = self.handle_product_type_and_params(market, params)
3826
3829
  request['productType'] = productType
3827
3830
  extended = self.extend(request, params)
3828
- # todo: mark & index also have their "recent" endpoints, but not priority now.
3829
- if priceType == 'mark':
3831
+ if not historicalEndpointNeeded and (priceType == 'mark' or priceType == 'index'):
3832
+ if not limitDefined:
3833
+ extended['limit'] = 1000
3834
+ limit = 1000
3835
+ # Recent endpoint for mark/index prices
3836
+ # https://www.bitget.com/api-doc/contract/market/Get-Candle-Data
3837
+ response = await self.publicMixGetV2MixMarketCandles(self.extend({'kLineType': priceType}, extended))
3838
+ elif priceType == 'mark':
3830
3839
  response = await self.publicMixGetV2MixMarketHistoryMarkCandles(extended)
3831
3840
  elif priceType == 'index':
3832
3841
  response = await self.publicMixGetV2MixMarketHistoryIndexCandles(extended)
@@ -3834,6 +3843,9 @@ class bitget(Exchange, ImplicitAPI):
3834
3843
  if historicalEndpointNeeded:
3835
3844
  response = await self.publicMixGetV2MixMarketHistoryCandles(extended)
3836
3845
  else:
3846
+ if not limitDefined:
3847
+ extended['limit'] = 1000
3848
+ limit = 1000
3837
3849
  response = await self.publicMixGetV2MixMarketCandles(extended)
3838
3850
  if response == '':
3839
3851
  return [] # happens when a new token is listed
@@ -221,7 +221,6 @@ class coinmetro(Exchange, ImplicitAPI):
221
221
  'options': {
222
222
  'currenciesByIdForParseMarket': None,
223
223
  'currencyIdsListForParseMarket': ['QRDO'],
224
- 'skippedMarkets': ['VXVUSDT'], # broken markets which do not have enough info in API
225
224
  },
226
225
  'features': {
227
226
  'spot': {
@@ -462,11 +461,11 @@ class coinmetro(Exchange, ImplicitAPI):
462
461
  # ...
463
462
  # ]
464
463
  #
465
- skippedMarkets = self.safe_list(self.options, 'skippedMarkets', [])
466
464
  result = []
467
465
  for i in range(0, len(response)):
468
466
  market = self.parse_market(response[i])
469
- if self.in_array(market['id'], skippedMarkets):
467
+ # there are several broken(unavailable info) markets
468
+ if market['base'] is None or market['quote'] is None:
470
469
  continue
471
470
  result.append(market)
472
471
  return result
@@ -6,7 +6,8 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.cryptocom import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction
9
+ import math
10
+ from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, TradingFees, Transaction
10
11
  from typing import List
11
12
  from ccxt.base.errors import ExchangeError
12
13
  from ccxt.base.errors import AuthenticationError
@@ -79,7 +80,7 @@ class cryptocom(Exchange, ImplicitAPI):
79
80
  'fetchDepositWithdrawFee': 'emulated',
80
81
  'fetchDepositWithdrawFees': True,
81
82
  'fetchFundingHistory': False,
82
- 'fetchFundingRate': False,
83
+ 'fetchFundingRate': True,
83
84
  'fetchFundingRateHistory': True,
84
85
  'fetchFundingRates': False,
85
86
  'fetchGreeks': False,
@@ -480,6 +481,7 @@ class cryptocom(Exchange, ImplicitAPI):
480
481
  'exceptions': {
481
482
  'exact': {
482
483
  '219': InvalidOrder,
484
+ '306': InsufficientFunds, # {"id" : 1753xxx, "method" : "private/amend-order", "code" : 306, "message" : "INSUFFICIENT_AVAILABLE_BALANCE", "result" : {"client_oid" : "1753xxx", "order_id" : "6530xxx"}}
483
485
  '314': InvalidOrder, # {"id" : 1700xxx, "method" : "private/create-order", "code" : 314, "message" : "EXCEEDS_MAX_ORDER_SIZE", "result" : {"client_oid" : "1700xxx", "order_id" : "6530xxx"}}
484
486
  '325': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 325, "message" : "EXCEED_DAILY_VOL_LIMIT", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
485
487
  '415': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 415, "message" : "BELOW_MIN_ORDER_SIZE", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
@@ -2849,6 +2851,79 @@ class cryptocom(Exchange, ImplicitAPI):
2849
2851
  result.append(self.parse_settlement(settlements[i], market))
2850
2852
  return result
2851
2853
 
2854
+ async def fetch_funding_rate(self, symbol: str, params={}):
2855
+ """
2856
+ fetches historical funding rates
2857
+
2858
+ https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-valuations
2859
+
2860
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
2861
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2862
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
2863
+ """
2864
+ await self.load_markets()
2865
+ market = self.market(symbol)
2866
+ if not market['swap']:
2867
+ raise BadSymbol(self.id + ' fetchFundingRate() supports swap contracts only')
2868
+ request: dict = {
2869
+ 'instrument_name': market['id'],
2870
+ 'valuation_type': 'estimated_funding_rate',
2871
+ 'count': 1,
2872
+ }
2873
+ response = await self.v1PublicGetPublicGetValuations(self.extend(request, params))
2874
+ #
2875
+ # {
2876
+ # "id": -1,
2877
+ # "method": "public/get-valuations",
2878
+ # "code": 0,
2879
+ # "result": {
2880
+ # "data": [
2881
+ # {
2882
+ # "v": "-0.000001884",
2883
+ # "t": 1687892400000
2884
+ # },
2885
+ # ],
2886
+ # "instrument_name": "BTCUSD-PERP"
2887
+ # }
2888
+ # }
2889
+ #
2890
+ result = self.safe_dict(response, 'result', {})
2891
+ data = self.safe_list(result, 'data', [])
2892
+ entry = self.safe_dict(data, 0, {})
2893
+ return self.parse_funding_rate(entry, market)
2894
+
2895
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
2896
+ #
2897
+ # {
2898
+ # "v": "-0.000001884",
2899
+ # "t": 1687892400000
2900
+ # },
2901
+ #
2902
+ timestamp = self.safe_integer(contract, 't')
2903
+ fundingTimestamp = None
2904
+ if timestamp is not None:
2905
+ fundingTimestamp = int(math.ceil(timestamp / 3600000)) * 3600000 # end of the next hour
2906
+ return {
2907
+ 'info': contract,
2908
+ 'symbol': self.safe_symbol(None, market),
2909
+ 'markPrice': None,
2910
+ 'indexPrice': None,
2911
+ 'interestRate': None,
2912
+ 'estimatedSettlePrice': None,
2913
+ 'timestamp': timestamp,
2914
+ 'datetime': self.iso8601(timestamp),
2915
+ 'fundingRate': self.safe_number(contract, 'v'),
2916
+ 'fundingTimestamp': fundingTimestamp,
2917
+ 'fundingDatetime': self.iso8601(fundingTimestamp),
2918
+ 'nextFundingRate': None,
2919
+ 'nextFundingTimestamp': None,
2920
+ 'nextFundingDatetime': None,
2921
+ 'previousFundingRate': None,
2922
+ 'previousFundingTimestamp': None,
2923
+ 'previousFundingDatetime': None,
2924
+ 'interval': '1h',
2925
+ }
2926
+
2852
2927
  async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2853
2928
  """
2854
2929
  fetches historical funding rates
@@ -957,7 +957,7 @@ class exmo(Exchange, ImplicitAPI):
957
957
  request['from'] = to - (limit * duration) - 1
958
958
  request['to'] = to
959
959
  else:
960
- request['from'] = self.parse_to_int(since / 1000) - 1
960
+ request['from'] = self.parse_to_int(since / 1000)
961
961
  if untilIsDefined:
962
962
  request['to'] = min(until, now)
963
963
  else:
@@ -95,7 +95,7 @@ class foxbit(Exchange, ImplicitAPI):
95
95
  '1M': '1M',
96
96
  },
97
97
  'urls': {
98
- 'logo': 'https://github.com/user-attachments/assets/63be1a3a-775d-459b-8c03-493c71c0253c',
98
+ 'logo': 'https://github.com/user-attachments/assets/ba1435eb-1d59-4393-8de7-0db10a002fb3',
99
99
  'api': {
100
100
  'public': 'https://api.foxbit.com.br',
101
101
  'private': 'https://api.foxbit.com.br',
@@ -687,7 +687,6 @@ class gate(Exchange, ImplicitAPI):
687
687
  'SOL': 'SOL',
688
688
  'POLYGON': 'POL',
689
689
  'MATIC': 'POL',
690
- 'OP': 'OPETH',
691
690
  'OPTIMISM': 'OPETH',
692
691
  'ADA': 'ADA', # CARDANO
693
692
  'AVAXC': 'AVAX_C',
@@ -3789,7 +3788,7 @@ class gate(Exchange, ImplicitAPI):
3789
3788
  start = self.parse_to_int(since / 1000)
3790
3789
  request['from'] = start
3791
3790
  request['to'] = self.sum(start, 30 * 24 * 60 * 60)
3792
- request, params = self.handle_until_option('to', request, params)
3791
+ request, params = self.handle_until_option('to', request, params, 0.001)
3793
3792
  response = await self.privateWalletGetWithdrawals(self.extend(request, params))
3794
3793
  return self.parse_transactions(response, currency)
3795
3794