ccxt 4.4.77__py2.py3-none-any.whl → 4.4.78__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 (103) hide show
  1. ccxt/__init__.py +3 -3
  2. ccxt/abstract/apex.py +31 -0
  3. ccxt/apex.py +1884 -0
  4. ccxt/ascendex.py +2 -2
  5. ccxt/async_support/__init__.py +3 -3
  6. ccxt/async_support/apex.py +1884 -0
  7. ccxt/async_support/ascendex.py +2 -2
  8. ccxt/async_support/base/exchange.py +1 -1
  9. ccxt/async_support/binance.py +3 -3
  10. ccxt/async_support/bingx.py +1 -1
  11. ccxt/async_support/bitfinex.py +2 -2
  12. ccxt/async_support/bitflyer.py +2 -2
  13. ccxt/async_support/bitget.py +134 -64
  14. ccxt/async_support/bitmart.py +2 -2
  15. ccxt/async_support/bitmex.py +6 -6
  16. ccxt/async_support/cex.py +1 -1
  17. ccxt/async_support/coinbase.py +29 -4
  18. ccxt/async_support/coincatch.py +66 -0
  19. ccxt/async_support/coinex.py +1 -1
  20. ccxt/async_support/cryptocom.py +2 -2
  21. ccxt/async_support/defx.py +1 -1
  22. ccxt/async_support/delta.py +1 -1
  23. ccxt/async_support/deribit.py +2 -2
  24. ccxt/async_support/derive.py +2 -2
  25. ccxt/async_support/digifinex.py +2 -2
  26. ccxt/async_support/gate.py +1 -1
  27. ccxt/async_support/hitbtc.py +5 -2
  28. ccxt/async_support/htx.py +2 -2
  29. ccxt/async_support/hyperliquid.py +13 -6
  30. ccxt/async_support/kraken.py +2 -2
  31. ccxt/async_support/krakenfutures.py +2 -2
  32. ccxt/async_support/kucoinfutures.py +2 -2
  33. ccxt/async_support/mexc.py +50 -52
  34. ccxt/async_support/okx.py +1 -1
  35. ccxt/async_support/oxfun.py +2 -2
  36. ccxt/async_support/paradex.py +2 -2
  37. ccxt/async_support/phemex.py +4 -3
  38. ccxt/async_support/poloniex.py +3 -3
  39. ccxt/async_support/probit.py +1 -0
  40. ccxt/async_support/tradeogre.py +2 -1
  41. ccxt/async_support/upbit.py +201 -43
  42. ccxt/async_support/vertex.py +2 -2
  43. ccxt/async_support/whitebit.py +1 -0
  44. ccxt/async_support/woo.py +5 -3
  45. ccxt/async_support/woofipro.py +2 -2
  46. ccxt/async_support/xt.py +9 -2
  47. ccxt/base/errors.py +6 -0
  48. ccxt/base/exchange.py +69 -2
  49. ccxt/binance.py +3 -3
  50. ccxt/bingx.py +1 -1
  51. ccxt/bitfinex.py +2 -2
  52. ccxt/bitflyer.py +2 -2
  53. ccxt/bitget.py +134 -64
  54. ccxt/bitmart.py +2 -2
  55. ccxt/bitmex.py +6 -6
  56. ccxt/cex.py +1 -1
  57. ccxt/coinbase.py +29 -4
  58. ccxt/coincatch.py +66 -0
  59. ccxt/coinex.py +1 -1
  60. ccxt/cryptocom.py +2 -2
  61. ccxt/defx.py +1 -1
  62. ccxt/delta.py +1 -1
  63. ccxt/deribit.py +2 -2
  64. ccxt/derive.py +2 -2
  65. ccxt/digifinex.py +2 -2
  66. ccxt/gate.py +1 -1
  67. ccxt/hitbtc.py +5 -2
  68. ccxt/htx.py +2 -2
  69. ccxt/hyperliquid.py +13 -6
  70. ccxt/kraken.py +2 -2
  71. ccxt/krakenfutures.py +2 -2
  72. ccxt/kucoinfutures.py +2 -2
  73. ccxt/mexc.py +50 -52
  74. ccxt/okx.py +1 -1
  75. ccxt/oxfun.py +2 -2
  76. ccxt/paradex.py +2 -2
  77. ccxt/phemex.py +4 -3
  78. ccxt/poloniex.py +3 -3
  79. ccxt/pro/__init__.py +5 -1
  80. ccxt/pro/apex.py +984 -0
  81. ccxt/pro/coinbase.py +4 -6
  82. ccxt/pro/gate.py +22 -2
  83. ccxt/pro/hollaex.py +2 -2
  84. ccxt/pro/p2b.py +2 -2
  85. ccxt/pro/tradeogre.py +272 -0
  86. ccxt/probit.py +1 -0
  87. ccxt/test/tests_async.py +4 -0
  88. ccxt/test/tests_sync.py +4 -0
  89. ccxt/tradeogre.py +2 -1
  90. ccxt/upbit.py +201 -43
  91. ccxt/vertex.py +2 -2
  92. ccxt/whitebit.py +1 -0
  93. ccxt/woo.py +5 -3
  94. ccxt/woofipro.py +2 -2
  95. ccxt/xt.py +9 -2
  96. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/METADATA +4 -4
  97. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/RECORD +100 -98
  98. ccxt/abstract/ace.py +0 -15
  99. ccxt/ace.py +0 -1152
  100. ccxt/async_support/ace.py +0 -1152
  101. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/LICENSE.txt +0 -0
  102. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/WHEEL +0 -0
  103. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.ascendex import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Int, Leverage, Leverages, LeverageTier, LeverageTiers, MarginMode, MarginModes, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
10
+ from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Int, Leverage, Leverages, LeverageTier, LeverageTiers, MarginMode, MarginModes, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -2633,7 +2633,7 @@ class ascendex(Exchange, ImplicitAPI):
2633
2633
  'internal': False,
2634
2634
  }
2635
2635
 
2636
- async def fetch_positions(self, symbols: Strings = None, params={}):
2636
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2637
2637
  """
2638
2638
  fetch all open positions
2639
2639
  :param str[]|None symbols: list of unified market symbols
@@ -2,7 +2,7 @@
2
2
 
3
3
  # -----------------------------------------------------------------------------
4
4
 
5
- __version__ = '4.4.77'
5
+ __version__ = '4.4.78'
6
6
 
7
7
  # -----------------------------------------------------------------------------
8
8
 
@@ -8,7 +8,7 @@ from ccxt.abstract.binance import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
10
  import json
11
- from ccxt.base.types import Any, Balances, BorrowInterest, Conversion, CrossBorrowRate, Currencies, Currency, DepositAddress, Greeks, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, Leverage, Leverages, LeverageTier, LeverageTiers, LongShortRatio, MarginMode, MarginModes, MarginModification, Market, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, MarketInterface, TransferEntry
11
+ from ccxt.base.types import Any, Balances, BorrowInterest, Conversion, CrossBorrowRate, Currencies, Currency, DepositAddress, Greeks, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, Leverage, Leverages, LeverageTier, LeverageTiers, LongShortRatio, MarginMode, MarginModes, MarginModification, Market, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, MarketInterface, TransferEntry
12
12
  from typing import List
13
13
  from ccxt.base.errors import ExchangeError
14
14
  from ccxt.base.errors import AuthenticationError
@@ -44,7 +44,7 @@ class binance(Exchange, ImplicitAPI):
44
44
  return self.deep_extend(super(binance, self).describe(), {
45
45
  'id': 'binance',
46
46
  'name': 'Binance',
47
- 'countries': ['JP', 'MT'], # Japan, Malta
47
+ 'countries': [], # Japan
48
48
  'rateLimit': 50,
49
49
  'certified': True,
50
50
  'pro': True,
@@ -10111,7 +10111,7 @@ class binance(Exchange, ImplicitAPI):
10111
10111
  'percentage': None,
10112
10112
  })
10113
10113
 
10114
- async def fetch_positions(self, symbols: Strings = None, params={}):
10114
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
10115
10115
  """
10116
10116
  fetch all open positions
10117
10117
 
@@ -2372,7 +2372,7 @@ class bingx(Exchange, ImplicitAPI):
2372
2372
  positions = self.parse_positions(records)
2373
2373
  return self.filter_by_symbol_since_limit(positions, symbol, since, limit)
2374
2374
 
2375
- async def fetch_positions(self, symbols: Strings = None, params={}):
2375
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2376
2376
  """
2377
2377
  fetch all open positions
2378
2378
 
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.bitfinex import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
10
+ from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -2676,7 +2676,7 @@ class bitfinex(Exchange, ImplicitAPI):
2676
2676
  self.throw_broadly_matched_exception(self.exceptions['broad'], text, text)
2677
2677
  return self.parse_transaction(response, currency)
2678
2678
 
2679
- async def fetch_positions(self, symbols: Strings = None, params={}):
2679
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2680
2680
  """
2681
2681
  fetch all open positions
2682
2682
 
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.bitflyer import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Any, Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, FundingRate, Trade, TradingFeeInterface, Transaction, MarketInterface
9
+ from ccxt.base.types import Any, Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, FundingRate, Trade, TradingFeeInterface, Transaction, MarketInterface
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
@@ -842,7 +842,7 @@ class bitflyer(Exchange, ImplicitAPI):
842
842
  #
843
843
  return self.parse_trades(response, market, since, limit)
844
844
 
845
- async def fetch_positions(self, symbols: Strings = None, params={}):
845
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
846
846
  """
847
847
  fetch all open positions
848
848
 
@@ -1393,28 +1393,44 @@ class bitget(Exchange, ImplicitAPI):
1393
1393
  'fillResponseFromRequest': True,
1394
1394
  },
1395
1395
  'fetchOHLCV': {
1396
- 'spot': {
1397
- 'method': 'publicSpotGetV2SpotMarketCandles', # publicSpotGetV2SpotMarketCandles or publicSpotGetV2SpotMarketHistoryCandles
1398
- },
1399
- 'swap': {
1400
- 'method': 'publicMixGetV2MixMarketCandles', # publicMixGetV2MixMarketCandles or publicMixGetV2MixMarketHistoryCandles or publicMixGetV2MixMarketHistoryIndexCandles or publicMixGetV2MixMarketHistoryMarkCandles
1401
- },
1402
- 'maxDaysPerTimeframe': {
1396
+ # ### Timeframe settings ###
1397
+ # after testing, the below values are real ones, because the values provided by API DOCS are wrong
1398
+ # so, start timestamp should be within these thresholds to be able to call "recent" candles endpoint
1399
+ 'maxRecentDaysPerTimeframe': {
1403
1400
  '1m': 30,
1404
1401
  '3m': 30,
1405
1402
  '5m': 30,
1406
- '10m': 30,
1407
- '15m': 52,
1408
- '30m': 62,
1409
- '1h': 83,
1410
- '2h': 120,
1403
+ '15m': 30,
1404
+ '30m': 30,
1405
+ '1h': 60,
1411
1406
  '4h': 240,
1412
1407
  '6h': 360,
1413
- '12h': 360,
1414
- '1d': 300,
1415
- '3d': 300,
1416
- '1w': 300,
1417
- '1M': 300,
1408
+ '12h': 720,
1409
+ '1d': 1440,
1410
+ '3d': 1440 * 3,
1411
+ '1w': 1440 * 7,
1412
+ '1M': 1440 * 30,
1413
+ },
1414
+ 'spot': {
1415
+ 'maxLimitPerTimeframe': {
1416
+ '1d': 300,
1417
+ '3d': 100,
1418
+ '1w': 100,
1419
+ '1M': 100,
1420
+ },
1421
+ 'method': 'publicSpotGetV2SpotMarketCandles', # publicSpotGetV2SpotMarketCandles or publicSpotGetV2SpotMarketHistoryCandles
1422
+ },
1423
+ 'swap': {
1424
+ 'maxLimitPerTimeframe': {
1425
+ '4h': 540,
1426
+ '6h': 360,
1427
+ '12h': 180,
1428
+ '1d': 90,
1429
+ '3d': 30,
1430
+ '1w': 13,
1431
+ '1M': 4,
1432
+ },
1433
+ 'method': 'publicMixGetV2MixMarketCandles', # publicMixGetV2MixMarketCandles or publicMixGetV2MixMarketHistoryCandles or publicMixGetV2MixMarketHistoryIndexCandles or publicMixGetV2MixMarketHistoryMarkCandles
1418
1434
  },
1419
1435
  },
1420
1436
  'fetchTrades': {
@@ -1425,6 +1441,9 @@ class bitget(Exchange, ImplicitAPI):
1425
1441
  'method': 'publicMixGetV2MixMarketFillsHistory', # or publicMixGetV2MixMarketFills
1426
1442
  },
1427
1443
  },
1444
+ 'fetchFundingRate': {
1445
+ 'method': 'publicMixGetV2MixMarketCurrentFundRate', # or publicMixGetV2MixMarketFundingTime
1446
+ },
1428
1447
  'accountsByType': {
1429
1448
  'spot': 'spot',
1430
1449
  'cross': 'crossed_margin',
@@ -1622,7 +1641,7 @@ class bitget(Exchange, ImplicitAPI):
1622
1641
  'symbolRequired': False,
1623
1642
  },
1624
1643
  'fetchOHLCV': {
1625
- 'limit': 1000, # variable timespans for recent endpoint, 200 for historical
1644
+ 'limit': 200, # variable timespans for recent endpoint, 200 for historical
1626
1645
  },
1627
1646
  },
1628
1647
  'forPerps': {
@@ -1697,11 +1716,12 @@ class bitget(Exchange, ImplicitAPI):
1697
1716
  defaultProductType = None
1698
1717
  if (subType is not None) and (market is None):
1699
1718
  # set default only if subType is defined and market is not defined, since there is also USDC productTypes which are also linear
1700
- sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1701
- if sandboxMode:
1702
- defaultProductType = 'SUSDT-FUTURES' if (subType == 'linear') else 'SCOIN-FUTURES'
1703
- else:
1704
- defaultProductType = 'USDT-FUTURES' if (subType == 'linear') else 'COIN-FUTURES'
1719
+ # sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1720
+ # if sandboxMode:
1721
+ # defaultProductType = 'SUSDT-FUTURES' if (subType == 'linear') else 'SCOIN-FUTURES'
1722
+ # else:
1723
+ defaultProductType = 'USDT-FUTURES' if (subType == 'linear') else 'COIN-FUTURES'
1724
+ # }
1705
1725
  productType = self.safe_string(params, 'productType', defaultProductType)
1706
1726
  if (productType is None) and (market is not None):
1707
1727
  settle = market['settle']
@@ -3416,29 +3436,31 @@ class bitget(Exchange, ImplicitAPI):
3416
3436
  market = self.market(symbol)
3417
3437
  marketType = 'spot' if market['spot'] else 'swap'
3418
3438
  timeframes = self.options['timeframes'][marketType]
3419
- msInDay = 86400000
3420
- duration = self.parse_timeframe(timeframe) * 1000
3421
3439
  request: dict = {
3422
3440
  'symbol': market['id'],
3423
3441
  'granularity': self.safe_string(timeframes, timeframe, timeframe),
3424
3442
  }
3443
+ msInDay = 86400000
3444
+ now = self.milliseconds()
3445
+ duration = self.parse_timeframe(timeframe) * 1000
3425
3446
  until = self.safe_integer(params, 'until')
3426
3447
  limitDefined = limit is not None
3427
3448
  sinceDefined = since is not None
3428
3449
  untilDefined = until is not None
3429
3450
  params = self.omit(params, ['until'])
3430
- response = None
3431
- now = self.milliseconds()
3432
3451
  # retrievable periods listed here:
3433
3452
  # - https://www.bitget.com/api-doc/spot/market/Get-Candle-Data#request-parameters
3434
3453
  # - https://www.bitget.com/api-doc/contract/market/Get-Candle-Data#description
3435
- ohlcOptions = self.safe_dict(self.options, 'fetchOHLCV', {})
3436
- retrievableDaysMap = self.safe_dict(ohlcOptions, 'maxDaysPerTimeframe', {})
3437
- maxRetrievableDaysForRecent = self.safe_integer(retrievableDaysMap, timeframe, 30) # default to safe minimum
3438
- endpointTsBoundary = now - (maxRetrievableDaysForRecent - 1) * msInDay
3454
+ key = 'spot' if market['spot'] else 'swap'
3455
+ ohlcOptions = self.safe_dict(self.options['fetchOHLCV'], key, {})
3456
+ maxLimitPerTimeframe = self.safe_dict(ohlcOptions, 'maxLimitPerTimeframe', {})
3457
+ maxLimitForThisTimeframe = self.safe_integer(maxLimitPerTimeframe, timeframe, limit)
3458
+ recentEndpointDaysMap = self.safe_dict(self.options['fetchOHLCV'], 'maxRecentDaysPerTimeframe', {})
3459
+ recentEndpointAvailableDays = self.safe_integer(recentEndpointDaysMap, timeframe)
3460
+ recentEndpointBoundaryTs = now - (recentEndpointAvailableDays - 1) * msInDay
3439
3461
  if limitDefined:
3440
3462
  limit = min(limit, maxLimitForRecentEndpoint)
3441
- request['limit'] = limit
3463
+ limit = min(limit, maxLimitForThisTimeframe)
3442
3464
  else:
3443
3465
  limit = defaultLimit
3444
3466
  limitMultipliedDuration = limit * duration
@@ -3458,26 +3480,33 @@ class bitget(Exchange, ImplicitAPI):
3458
3480
  if not sinceDefined:
3459
3481
  calculatedStartTime = calculatedEndTime - limitMultipliedDuration
3460
3482
  # we do not need to set "startTime" here
3461
- historicalEndpointNeeded = (calculatedStartTime is not None) and (calculatedStartTime <= endpointTsBoundary)
3462
- if historicalEndpointNeeded:
3483
+ # if historical endpoint is needed, we should re-set the variables
3484
+ historicalEndpointNeeded = False
3485
+ if (calculatedStartTime is not None and calculatedStartTime <= recentEndpointBoundaryTs) or useHistoryEndpoint:
3486
+ historicalEndpointNeeded = True
3463
3487
  # only for "historical-candles" - ensure we use correct max limit
3464
- if limitDefined:
3465
- request['limit'] = min(limit, maxLimitForHistoryEndpoint)
3488
+ limit = min(limit, maxLimitForHistoryEndpoint)
3489
+ limitMultipliedDuration = limit * duration
3490
+ calculatedStartTime = calculatedEndTime - limitMultipliedDuration
3491
+ request['startTime'] = calculatedStartTime
3492
+ # for contract, maximum 90 days allowed between start-end times
3493
+ if not market['spot']:
3494
+ maxDistanceDaysForContracts = 90
3495
+ # only correct if request is larger
3496
+ if calculatedEndTime - calculatedStartTime > maxDistanceDaysForContracts * msInDay:
3497
+ calculatedEndTime = self.sum(calculatedStartTime, maxDistanceDaysForContracts * msInDay)
3498
+ request['endTime'] = calculatedEndTime
3499
+ # we need to set limit to safely cover the period
3500
+ request['limit'] = limit
3466
3501
  # make request
3502
+ response = None
3467
3503
  if market['spot']:
3468
3504
  # checks if we need history endpoint
3469
- if historicalEndpointNeeded or useHistoryEndpoint:
3505
+ if historicalEndpointNeeded:
3470
3506
  response = await self.publicSpotGetV2SpotMarketHistoryCandles(self.extend(request, params))
3471
3507
  else:
3472
3508
  response = await self.publicSpotGetV2SpotMarketCandles(self.extend(request, params))
3473
3509
  else:
3474
- maxDistanceDaysForContracts = 90 # for contract, maximum 90 days allowed between start-end times
3475
- # only correct the request to fix 90 days if until was auto-calculated
3476
- if sinceDefined:
3477
- if not untilDefined:
3478
- request['endTime'] = min(calculatedEndTime, self.sum(since, maxDistanceDaysForContracts * msInDay))
3479
- elif calculatedEndTime - calculatedStartTime > maxDistanceDaysForContracts * msInDay:
3480
- raise BadRequest(self.id + ' fetchOHLCV() between start and end must be less than ' + str(maxDistanceDaysForContracts) + ' days')
3481
3510
  priceType = None
3482
3511
  priceType, params = self.handle_param_string(params, 'price')
3483
3512
  productType = None
@@ -3490,7 +3519,7 @@ class bitget(Exchange, ImplicitAPI):
3490
3519
  elif priceType == 'index':
3491
3520
  response = await self.publicMixGetV2MixMarketHistoryIndexCandles(extended)
3492
3521
  else:
3493
- if historicalEndpointNeeded or useHistoryEndpoint:
3522
+ if historicalEndpointNeeded:
3494
3523
  response = await self.publicMixGetV2MixMarketHistoryCandles(extended)
3495
3524
  else:
3496
3525
  response = await self.publicMixGetV2MixMarketCandles(extended)
@@ -6444,9 +6473,11 @@ class bitget(Exchange, ImplicitAPI):
6444
6473
  fetch the current funding rate
6445
6474
 
6446
6475
  https://www.bitget.com/api-doc/contract/market/Get-Current-Funding-Rate
6476
+ https://www.bitget.com/api-doc/contract/market/Get-Symbol-Next-Funding-Time
6447
6477
 
6448
6478
  :param str symbol: unified market symbol
6449
6479
  :param dict [params]: extra parameters specific to the exchange API endpoint
6480
+ :param str [params.method]: either(default) 'publicMixGetV2MixMarketCurrentFundRate' or 'publicMixGetV2MixMarketFundingTime'
6450
6481
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
6451
6482
  """
6452
6483
  await self.load_markets()
@@ -6459,21 +6490,45 @@ class bitget(Exchange, ImplicitAPI):
6459
6490
  'symbol': market['id'],
6460
6491
  'productType': productType,
6461
6492
  }
6462
- response = await self.publicMixGetV2MixMarketCurrentFundRate(self.extend(request, params))
6463
- #
6464
- # {
6465
- # "code": "00000",
6466
- # "msg": "success",
6467
- # "requestTime": 1700811542124,
6468
- # "data": [
6469
- # {
6470
- # "symbol": "BTCUSDT",
6471
- # "fundingRate": "0.000106"
6472
- # }
6473
- # ]
6474
- # }
6475
- #
6476
- data = self.safe_value(response, 'data', [])
6493
+ method = None
6494
+ method, params = self.handle_option_and_params(params, 'fetchFundingRate', 'method', 'publicMixGetV2MixMarketCurrentFundRate')
6495
+ response = None
6496
+ if method == 'publicMixGetV2MixMarketCurrentFundRate':
6497
+ response = await self.publicMixGetV2MixMarketCurrentFundRate(self.extend(request, params))
6498
+ #
6499
+ # {
6500
+ # "code": "00000",
6501
+ # "msg": "success",
6502
+ # "requestTime": 1745500709429,
6503
+ # "data": [
6504
+ # {
6505
+ # "symbol": "BTCUSDT",
6506
+ # "fundingRate": "-0.000013",
6507
+ # "fundingRateInterval": "8",
6508
+ # "nextUpdate": "1745510400000",
6509
+ # "minFundingRate": "-0.003",
6510
+ # "maxFundingRate": "0.003"
6511
+ # }
6512
+ # ]
6513
+ # }
6514
+ #
6515
+ elif method == 'publicMixGetV2MixMarketFundingTime':
6516
+ response = await self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
6517
+ #
6518
+ # {
6519
+ # "code": "00000",
6520
+ # "msg": "success",
6521
+ # "requestTime": 1745402092428,
6522
+ # "data": [
6523
+ # {
6524
+ # "symbol": "BTCUSDT",
6525
+ # "nextFundingTime": "1745424000000",
6526
+ # "ratePeriod": "8"
6527
+ # }
6528
+ # ]
6529
+ # }
6530
+ #
6531
+ data = self.safe_list(response, 'data', [])
6477
6532
  return self.parse_funding_rate(data[0], market)
6478
6533
 
6479
6534
  async def fetch_funding_rates(self, symbols: Strings = None, params={}) -> FundingRates:
@@ -6536,11 +6591,23 @@ class bitget(Exchange, ImplicitAPI):
6536
6591
 
6537
6592
  def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
6538
6593
  #
6539
- # fetchFundingRate
6594
+ # fetchFundingRate: publicMixGetV2MixMarketCurrentFundRate
6540
6595
  #
6541
6596
  # {
6542
6597
  # "symbol": "BTCUSDT",
6543
- # "fundingRate": "-0.000182"
6598
+ # "fundingRate": "-0.000013",
6599
+ # "fundingRateInterval": "8",
6600
+ # "nextUpdate": "1745510400000",
6601
+ # "minFundingRate": "-0.003",
6602
+ # "maxFundingRate": "0.003"
6603
+ # }
6604
+ #
6605
+ # fetchFundingRate: publicMixGetV2MixMarketFundingTime
6606
+ #
6607
+ # {
6608
+ # "symbol": "BTCUSDT",
6609
+ # "nextFundingTime": "1745424000000",
6610
+ # "ratePeriod": "8"
6544
6611
  # }
6545
6612
  #
6546
6613
  # fetchFundingInterval
@@ -6550,7 +6617,9 @@ class bitget(Exchange, ImplicitAPI):
6550
6617
  # "nextFundingTime": "1727942400000",
6551
6618
  # "ratePeriod": "8"
6552
6619
  # }
6620
+ #
6553
6621
  # fetchFundingRates
6622
+ #
6554
6623
  # {
6555
6624
  # "symbol": "BTCUSD",
6556
6625
  # "lastPr": "29904.5",
@@ -6576,10 +6645,11 @@ class bitget(Exchange, ImplicitAPI):
6576
6645
  # "open24h": "0",
6577
6646
  # "markPrice": "12345"
6578
6647
  # }
6648
+ #
6579
6649
  marketId = self.safe_string(contract, 'symbol')
6580
6650
  symbol = self.safe_symbol(marketId, market, None, 'swap')
6581
- fundingTimestamp = self.safe_integer(contract, 'nextFundingTime')
6582
- interval = self.safe_string(contract, 'ratePeriod')
6651
+ fundingTimestamp = self.safe_integer_2(contract, 'nextFundingTime', 'nextUpdate')
6652
+ interval = self.safe_string_2(contract, 'ratePeriod', 'fundingRateInterval')
6583
6653
  timestamp = self.safe_integer(contract, 'ts')
6584
6654
  markPrice = self.safe_number(contract, 'markPrice')
6585
6655
  indexPrice = self.safe_number(contract, 'indexPrice')
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.bitmart import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Any, Balances, BorrowInterest, Currencies, Currency, DepositAddress, FundingHistory, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, MarketInterface, TransferEntry
9
+ from ccxt.base.types import Any, Balances, BorrowInterest, Currencies, Currency, DepositAddress, FundingHistory, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, MarketInterface, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -4654,7 +4654,7 @@ class bitmart(Exchange, ImplicitAPI):
4654
4654
  first = self.safe_dict(data, 0, {})
4655
4655
  return self.parse_position(first, market)
4656
4656
 
4657
- async def fetch_positions(self, symbols: Strings = None, params={}):
4657
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
4658
4658
  """
4659
4659
  fetch all open contract positions
4660
4660
 
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.bitmex import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, Leverage, Leverages, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, Transaction
9
+ from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, Leverage, Leverages, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -729,7 +729,7 @@ class bitmex(Exchange, ImplicitAPI):
729
729
  isQuanto = self.safe_value(market, 'isQuanto') # self is True when BASE and SETTLE are different, i.e. AXS/XXX:BTC
730
730
  linear = (not isInverse and not isQuanto) if contract else None
731
731
  status = self.safe_string(market, 'state')
732
- active = status != 'Unlisted'
732
+ active = status == 'Open' # Open, Settled, Unlisted
733
733
  expiry = None
734
734
  expiryDatetime = None
735
735
  symbol = None
@@ -743,9 +743,9 @@ class bitmex(Exchange, ImplicitAPI):
743
743
  else:
744
744
  multiplierString = Precise.string_abs(self.safe_string(market, 'multiplier'))
745
745
  contractSize = self.parse_number(multiplierString)
746
- if future:
747
- expiryDatetime = self.safe_string(market, 'expiry')
748
- expiry = self.parse8601(expiryDatetime)
746
+ expiryDatetime = self.safe_string(market, 'expiry')
747
+ expiry = self.parse8601(expiryDatetime)
748
+ if expiry is not None:
749
749
  symbol = symbol + '-' + self.yymmdd(expiry)
750
750
  else:
751
751
  # for index/exotic markets, default to id
@@ -2182,7 +2182,7 @@ class bitmex(Exchange, ImplicitAPI):
2182
2182
  'shortLeverage': self.safe_integer(leverage, 'leverage'),
2183
2183
  }
2184
2184
 
2185
- async def fetch_positions(self, symbols: Strings = None, params={}):
2185
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2186
2186
  """
2187
2187
  fetch all open positions
2188
2188
 
ccxt/async_support/cex.py CHANGED
@@ -555,7 +555,7 @@ class cex(Exchange, ImplicitAPI):
555
555
  'askVolume': None,
556
556
  'vwap': None,
557
557
  'open': None,
558
- 'close': self.safe_string(ticker, 'lastTradePrice'),
558
+ 'close': self.safe_string(ticker, 'last'), # last indicative price per api docs(difference also seen here: https://github.com/ccxt/ccxt/actions/runs/14593899575/job/40935513901?pr=25767#step:11:456 )
559
559
  'previousClose': None,
560
560
  'change': self.safe_number(ticker, 'priceChange'),
561
561
  'percentage': self.safe_number(ticker, 'priceChangePercentage'),
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.coinbase import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Account, Any, Balances, Conversion, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, MarketInterface
10
+ from ccxt.base.types import Account, Any, Balances, Conversion, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, MarketInterface
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -387,6 +387,7 @@ class coinbase(Exchange, ImplicitAPI):
387
387
  'fetchBalance': 'v2PrivateGetAccounts', # 'v2PrivateGetAccounts' or 'v3PrivateGetBrokerageAccounts'
388
388
  'fetchTime': 'v2PublicGetTime', # 'v2PublicGetTime' or 'v3PublicGetBrokerageTime'
389
389
  'user_native_currency': 'USD', # needed to get fees for v3
390
+ 'aliasCbMarketIds': {},
390
391
  },
391
392
  'features': {
392
393
  'default': {
@@ -1474,7 +1475,29 @@ class coinbase(Exchange, ImplicitAPI):
1474
1475
  perpetualData = self.safe_list(perpetualFutures, 'products', [])
1475
1476
  for i in range(0, len(perpetualData)):
1476
1477
  result.append(self.parse_contract_market(perpetualData[i], perpetualFeeTier))
1477
- return result
1478
+ # remove aliases
1479
+ self.options['aliasCbMarketIds'] = {}
1480
+ newMarkets = []
1481
+ for i in range(0, len(result)):
1482
+ market = result[i]
1483
+ info = self.safe_value(market, 'info', {})
1484
+ realMarketIds = self.safe_list(info, 'alias_to', [])
1485
+ length = len(realMarketIds)
1486
+ if length > 0:
1487
+ self.options['aliasCbMarketIds'][market['id']] = realMarketIds[0]
1488
+ self.options['aliasCbMarketIds'][market['symbol']] = realMarketIds[0]
1489
+ else:
1490
+ newMarkets.append(market)
1491
+ return newMarkets
1492
+
1493
+ def market(self, symbol: str) -> MarketInterface:
1494
+ finalSymbol = self.safe_string(self.options['aliasCbMarketIds'], symbol, symbol)
1495
+ return super(coinbase, self).market(finalSymbol)
1496
+
1497
+ def safe_market(self, marketId: Str = None, market: Market = None, delimiter: Str = None, marketType: Str = None) -> MarketInterface:
1498
+ if marketId in self.options['aliasCbMarketIds']:
1499
+ return self.market(marketId)
1500
+ return super(coinbase, self).safe_market(marketId, market, delimiter, marketType)
1478
1501
 
1479
1502
  def parse_spot_market(self, market, feeTier) -> MarketInterface:
1480
1503
  #
@@ -1883,6 +1906,7 @@ class coinbase(Exchange, ImplicitAPI):
1883
1906
  'withdraw': None,
1884
1907
  'fee': None,
1885
1908
  'precision': None,
1909
+ 'networks': {},
1886
1910
  'limits': {
1887
1911
  'amount': {
1888
1912
  'min': self.safe_number(currency, 'min_size'),
@@ -2194,10 +2218,11 @@ class coinbase(Exchange, ImplicitAPI):
2194
2218
  ask = self.safe_number(asks[0], 'price')
2195
2219
  askVolume = self.safe_number(asks[0], 'size')
2196
2220
  marketId = self.safe_string(ticker, 'product_id')
2221
+ market = self.safe_market(marketId, market)
2197
2222
  last = self.safe_number(ticker, 'price')
2198
2223
  datetime = self.safe_string(ticker, 'time')
2199
2224
  return self.safe_ticker({
2200
- 'symbol': self.safe_symbol(marketId, market),
2225
+ 'symbol': market['symbol'],
2201
2226
  'timestamp': self.parse8601(datetime),
2202
2227
  'datetime': datetime,
2203
2228
  'bid': bid,
@@ -4410,7 +4435,7 @@ class coinbase(Exchange, ImplicitAPI):
4410
4435
  order = self.safe_dict(response, 'success_response', {})
4411
4436
  return self.parse_order(order)
4412
4437
 
4413
- async def fetch_positions(self, symbols: Strings = None, params={}):
4438
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
4414
4439
  """
4415
4440
  fetch all open positions
4416
4441
 
@@ -90,6 +90,7 @@ class coincatch(Exchange, ImplicitAPI):
90
90
  'fetchDepositAddress': True,
91
91
  'fetchDeposits': True,
92
92
  'fetchDepositsWithdrawals': False,
93
+ 'fetchDepositWithdrawFees': True,
93
94
  'fetchFundingHistory': False,
94
95
  'fetchFundingRate': True,
95
96
  'fetchFundingRateHistory': True,
@@ -724,6 +725,71 @@ class coincatch(Exchange, ImplicitAPI):
724
725
  self.options['currencyIdsListForParseMarket'] = currenciesIds
725
726
  return result
726
727
 
728
+ async def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
729
+ """
730
+ fetch deposit and withdraw fees
731
+
732
+ https://coincatch.github.io/github.io/en/spot/#get-coin-list
733
+
734
+ :param str[] [codes]: list of unified currency codes
735
+ :param dict [params]: extra parameters specific to the exchange API endpoint
736
+ :returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
737
+ """
738
+ await self.load_markets()
739
+ response = await self.publicGetApiSpotV1PublicCurrencies(params)
740
+ data = self.safe_list(response, 'data', [])
741
+ return self.parse_deposit_withdraw_fees(data, codes, 'coinName')
742
+
743
+ def parse_deposit_withdraw_fee(self, fee, currency: Currency = None):
744
+ #
745
+ # {
746
+ # "coinId":"1",
747
+ # "coinName":"BTC",
748
+ # "transfer":"true",
749
+ # "chains":[
750
+ # {
751
+ # "chain":null,
752
+ # "needTag":"false",
753
+ # "withdrawable":"true",
754
+ # "rechargeAble":"true",
755
+ # "withdrawFee":"0.005",
756
+ # "depositConfirm":"1",
757
+ # "withdrawConfirm":"1",
758
+ # "minDepositAmount":"0.001",
759
+ # "minWithdrawAmount":"0.001",
760
+ # "browserUrl":"https://blockchair.com/bitcoin/testnet/transaction/"
761
+ # }
762
+ # ]
763
+ # }
764
+ #
765
+ chains = self.safe_list(fee, 'chains', [])
766
+ chainsLength = len(chains)
767
+ result: dict = {
768
+ 'info': fee,
769
+ 'withdraw': {
770
+ 'fee': None,
771
+ 'percentage': None,
772
+ },
773
+ 'deposit': {
774
+ 'fee': None,
775
+ 'percentage': None,
776
+ },
777
+ 'networks': {},
778
+ }
779
+ for i in range(0, chainsLength):
780
+ chain = chains[i]
781
+ networkId = self.safe_string(chain, 'chain')
782
+ currencyCode = self.safe_string(currency, 'code')
783
+ networkCode = self.network_id_to_code(networkId, currencyCode)
784
+ result['networks'][networkCode] = {
785
+ 'deposit': {'fee': None, 'percentage': None},
786
+ 'withdraw': {'fee': self.safe_number(chain, 'withdrawFee'), 'percentage': False},
787
+ }
788
+ if chainsLength == 1:
789
+ result['withdraw']['fee'] = self.safe_number(chain, 'withdrawFee')
790
+ result['withdraw']['percentage'] = False
791
+ return result
792
+
727
793
  async def fetch_markets(self, params={}) -> List[Market]:
728
794
  """
729
795
  retrieves data on all markets for the exchange