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
ccxt/bitflyer.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.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
- def fetch_positions(self, symbols: Strings = None, params={}):
845
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
846
846
  """
847
847
  fetch all open positions
848
848
 
ccxt/bitget.py CHANGED
@@ -1392,28 +1392,44 @@ class bitget(Exchange, ImplicitAPI):
1392
1392
  'fillResponseFromRequest': True,
1393
1393
  },
1394
1394
  'fetchOHLCV': {
1395
- 'spot': {
1396
- 'method': 'publicSpotGetV2SpotMarketCandles', # publicSpotGetV2SpotMarketCandles or publicSpotGetV2SpotMarketHistoryCandles
1397
- },
1398
- 'swap': {
1399
- 'method': 'publicMixGetV2MixMarketCandles', # publicMixGetV2MixMarketCandles or publicMixGetV2MixMarketHistoryCandles or publicMixGetV2MixMarketHistoryIndexCandles or publicMixGetV2MixMarketHistoryMarkCandles
1400
- },
1401
- 'maxDaysPerTimeframe': {
1395
+ # ### Timeframe settings ###
1396
+ # after testing, the below values are real ones, because the values provided by API DOCS are wrong
1397
+ # so, start timestamp should be within these thresholds to be able to call "recent" candles endpoint
1398
+ 'maxRecentDaysPerTimeframe': {
1402
1399
  '1m': 30,
1403
1400
  '3m': 30,
1404
1401
  '5m': 30,
1405
- '10m': 30,
1406
- '15m': 52,
1407
- '30m': 62,
1408
- '1h': 83,
1409
- '2h': 120,
1402
+ '15m': 30,
1403
+ '30m': 30,
1404
+ '1h': 60,
1410
1405
  '4h': 240,
1411
1406
  '6h': 360,
1412
- '12h': 360,
1413
- '1d': 300,
1414
- '3d': 300,
1415
- '1w': 300,
1416
- '1M': 300,
1407
+ '12h': 720,
1408
+ '1d': 1440,
1409
+ '3d': 1440 * 3,
1410
+ '1w': 1440 * 7,
1411
+ '1M': 1440 * 30,
1412
+ },
1413
+ 'spot': {
1414
+ 'maxLimitPerTimeframe': {
1415
+ '1d': 300,
1416
+ '3d': 100,
1417
+ '1w': 100,
1418
+ '1M': 100,
1419
+ },
1420
+ 'method': 'publicSpotGetV2SpotMarketCandles', # publicSpotGetV2SpotMarketCandles or publicSpotGetV2SpotMarketHistoryCandles
1421
+ },
1422
+ 'swap': {
1423
+ 'maxLimitPerTimeframe': {
1424
+ '4h': 540,
1425
+ '6h': 360,
1426
+ '12h': 180,
1427
+ '1d': 90,
1428
+ '3d': 30,
1429
+ '1w': 13,
1430
+ '1M': 4,
1431
+ },
1432
+ 'method': 'publicMixGetV2MixMarketCandles', # publicMixGetV2MixMarketCandles or publicMixGetV2MixMarketHistoryCandles or publicMixGetV2MixMarketHistoryIndexCandles or publicMixGetV2MixMarketHistoryMarkCandles
1417
1433
  },
1418
1434
  },
1419
1435
  'fetchTrades': {
@@ -1424,6 +1440,9 @@ class bitget(Exchange, ImplicitAPI):
1424
1440
  'method': 'publicMixGetV2MixMarketFillsHistory', # or publicMixGetV2MixMarketFills
1425
1441
  },
1426
1442
  },
1443
+ 'fetchFundingRate': {
1444
+ 'method': 'publicMixGetV2MixMarketCurrentFundRate', # or publicMixGetV2MixMarketFundingTime
1445
+ },
1427
1446
  'accountsByType': {
1428
1447
  'spot': 'spot',
1429
1448
  'cross': 'crossed_margin',
@@ -1621,7 +1640,7 @@ class bitget(Exchange, ImplicitAPI):
1621
1640
  'symbolRequired': False,
1622
1641
  },
1623
1642
  'fetchOHLCV': {
1624
- 'limit': 1000, # variable timespans for recent endpoint, 200 for historical
1643
+ 'limit': 200, # variable timespans for recent endpoint, 200 for historical
1625
1644
  },
1626
1645
  },
1627
1646
  'forPerps': {
@@ -1696,11 +1715,12 @@ class bitget(Exchange, ImplicitAPI):
1696
1715
  defaultProductType = None
1697
1716
  if (subType is not None) and (market is None):
1698
1717
  # set default only if subType is defined and market is not defined, since there is also USDC productTypes which are also linear
1699
- sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1700
- if sandboxMode:
1701
- defaultProductType = 'SUSDT-FUTURES' if (subType == 'linear') else 'SCOIN-FUTURES'
1702
- else:
1703
- defaultProductType = 'USDT-FUTURES' if (subType == 'linear') else 'COIN-FUTURES'
1718
+ # sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1719
+ # if sandboxMode:
1720
+ # defaultProductType = 'SUSDT-FUTURES' if (subType == 'linear') else 'SCOIN-FUTURES'
1721
+ # else:
1722
+ defaultProductType = 'USDT-FUTURES' if (subType == 'linear') else 'COIN-FUTURES'
1723
+ # }
1704
1724
  productType = self.safe_string(params, 'productType', defaultProductType)
1705
1725
  if (productType is None) and (market is not None):
1706
1726
  settle = market['settle']
@@ -3415,29 +3435,31 @@ class bitget(Exchange, ImplicitAPI):
3415
3435
  market = self.market(symbol)
3416
3436
  marketType = 'spot' if market['spot'] else 'swap'
3417
3437
  timeframes = self.options['timeframes'][marketType]
3418
- msInDay = 86400000
3419
- duration = self.parse_timeframe(timeframe) * 1000
3420
3438
  request: dict = {
3421
3439
  'symbol': market['id'],
3422
3440
  'granularity': self.safe_string(timeframes, timeframe, timeframe),
3423
3441
  }
3442
+ msInDay = 86400000
3443
+ now = self.milliseconds()
3444
+ duration = self.parse_timeframe(timeframe) * 1000
3424
3445
  until = self.safe_integer(params, 'until')
3425
3446
  limitDefined = limit is not None
3426
3447
  sinceDefined = since is not None
3427
3448
  untilDefined = until is not None
3428
3449
  params = self.omit(params, ['until'])
3429
- response = None
3430
- now = self.milliseconds()
3431
3450
  # retrievable periods listed here:
3432
3451
  # - https://www.bitget.com/api-doc/spot/market/Get-Candle-Data#request-parameters
3433
3452
  # - https://www.bitget.com/api-doc/contract/market/Get-Candle-Data#description
3434
- ohlcOptions = self.safe_dict(self.options, 'fetchOHLCV', {})
3435
- retrievableDaysMap = self.safe_dict(ohlcOptions, 'maxDaysPerTimeframe', {})
3436
- maxRetrievableDaysForRecent = self.safe_integer(retrievableDaysMap, timeframe, 30) # default to safe minimum
3437
- endpointTsBoundary = now - (maxRetrievableDaysForRecent - 1) * msInDay
3453
+ key = 'spot' if market['spot'] else 'swap'
3454
+ ohlcOptions = self.safe_dict(self.options['fetchOHLCV'], key, {})
3455
+ maxLimitPerTimeframe = self.safe_dict(ohlcOptions, 'maxLimitPerTimeframe', {})
3456
+ maxLimitForThisTimeframe = self.safe_integer(maxLimitPerTimeframe, timeframe, limit)
3457
+ recentEndpointDaysMap = self.safe_dict(self.options['fetchOHLCV'], 'maxRecentDaysPerTimeframe', {})
3458
+ recentEndpointAvailableDays = self.safe_integer(recentEndpointDaysMap, timeframe)
3459
+ recentEndpointBoundaryTs = now - (recentEndpointAvailableDays - 1) * msInDay
3438
3460
  if limitDefined:
3439
3461
  limit = min(limit, maxLimitForRecentEndpoint)
3440
- request['limit'] = limit
3462
+ limit = min(limit, maxLimitForThisTimeframe)
3441
3463
  else:
3442
3464
  limit = defaultLimit
3443
3465
  limitMultipliedDuration = limit * duration
@@ -3457,26 +3479,33 @@ class bitget(Exchange, ImplicitAPI):
3457
3479
  if not sinceDefined:
3458
3480
  calculatedStartTime = calculatedEndTime - limitMultipliedDuration
3459
3481
  # we do not need to set "startTime" here
3460
- historicalEndpointNeeded = (calculatedStartTime is not None) and (calculatedStartTime <= endpointTsBoundary)
3461
- if historicalEndpointNeeded:
3482
+ # if historical endpoint is needed, we should re-set the variables
3483
+ historicalEndpointNeeded = False
3484
+ if (calculatedStartTime is not None and calculatedStartTime <= recentEndpointBoundaryTs) or useHistoryEndpoint:
3485
+ historicalEndpointNeeded = True
3462
3486
  # only for "historical-candles" - ensure we use correct max limit
3463
- if limitDefined:
3464
- request['limit'] = min(limit, maxLimitForHistoryEndpoint)
3487
+ limit = min(limit, maxLimitForHistoryEndpoint)
3488
+ limitMultipliedDuration = limit * duration
3489
+ calculatedStartTime = calculatedEndTime - limitMultipliedDuration
3490
+ request['startTime'] = calculatedStartTime
3491
+ # for contract, maximum 90 days allowed between start-end times
3492
+ if not market['spot']:
3493
+ maxDistanceDaysForContracts = 90
3494
+ # only correct if request is larger
3495
+ if calculatedEndTime - calculatedStartTime > maxDistanceDaysForContracts * msInDay:
3496
+ calculatedEndTime = self.sum(calculatedStartTime, maxDistanceDaysForContracts * msInDay)
3497
+ request['endTime'] = calculatedEndTime
3498
+ # we need to set limit to safely cover the period
3499
+ request['limit'] = limit
3465
3500
  # make request
3501
+ response = None
3466
3502
  if market['spot']:
3467
3503
  # checks if we need history endpoint
3468
- if historicalEndpointNeeded or useHistoryEndpoint:
3504
+ if historicalEndpointNeeded:
3469
3505
  response = self.publicSpotGetV2SpotMarketHistoryCandles(self.extend(request, params))
3470
3506
  else:
3471
3507
  response = self.publicSpotGetV2SpotMarketCandles(self.extend(request, params))
3472
3508
  else:
3473
- maxDistanceDaysForContracts = 90 # for contract, maximum 90 days allowed between start-end times
3474
- # only correct the request to fix 90 days if until was auto-calculated
3475
- if sinceDefined:
3476
- if not untilDefined:
3477
- request['endTime'] = min(calculatedEndTime, self.sum(since, maxDistanceDaysForContracts * msInDay))
3478
- elif calculatedEndTime - calculatedStartTime > maxDistanceDaysForContracts * msInDay:
3479
- raise BadRequest(self.id + ' fetchOHLCV() between start and end must be less than ' + str(maxDistanceDaysForContracts) + ' days')
3480
3509
  priceType = None
3481
3510
  priceType, params = self.handle_param_string(params, 'price')
3482
3511
  productType = None
@@ -3489,7 +3518,7 @@ class bitget(Exchange, ImplicitAPI):
3489
3518
  elif priceType == 'index':
3490
3519
  response = self.publicMixGetV2MixMarketHistoryIndexCandles(extended)
3491
3520
  else:
3492
- if historicalEndpointNeeded or useHistoryEndpoint:
3521
+ if historicalEndpointNeeded:
3493
3522
  response = self.publicMixGetV2MixMarketHistoryCandles(extended)
3494
3523
  else:
3495
3524
  response = self.publicMixGetV2MixMarketCandles(extended)
@@ -6443,9 +6472,11 @@ class bitget(Exchange, ImplicitAPI):
6443
6472
  fetch the current funding rate
6444
6473
 
6445
6474
  https://www.bitget.com/api-doc/contract/market/Get-Current-Funding-Rate
6475
+ https://www.bitget.com/api-doc/contract/market/Get-Symbol-Next-Funding-Time
6446
6476
 
6447
6477
  :param str symbol: unified market symbol
6448
6478
  :param dict [params]: extra parameters specific to the exchange API endpoint
6479
+ :param str [params.method]: either(default) 'publicMixGetV2MixMarketCurrentFundRate' or 'publicMixGetV2MixMarketFundingTime'
6449
6480
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
6450
6481
  """
6451
6482
  self.load_markets()
@@ -6458,21 +6489,45 @@ class bitget(Exchange, ImplicitAPI):
6458
6489
  'symbol': market['id'],
6459
6490
  'productType': productType,
6460
6491
  }
6461
- response = self.publicMixGetV2MixMarketCurrentFundRate(self.extend(request, params))
6462
- #
6463
- # {
6464
- # "code": "00000",
6465
- # "msg": "success",
6466
- # "requestTime": 1700811542124,
6467
- # "data": [
6468
- # {
6469
- # "symbol": "BTCUSDT",
6470
- # "fundingRate": "0.000106"
6471
- # }
6472
- # ]
6473
- # }
6474
- #
6475
- data = self.safe_value(response, 'data', [])
6492
+ method = None
6493
+ method, params = self.handle_option_and_params(params, 'fetchFundingRate', 'method', 'publicMixGetV2MixMarketCurrentFundRate')
6494
+ response = None
6495
+ if method == 'publicMixGetV2MixMarketCurrentFundRate':
6496
+ response = self.publicMixGetV2MixMarketCurrentFundRate(self.extend(request, params))
6497
+ #
6498
+ # {
6499
+ # "code": "00000",
6500
+ # "msg": "success",
6501
+ # "requestTime": 1745500709429,
6502
+ # "data": [
6503
+ # {
6504
+ # "symbol": "BTCUSDT",
6505
+ # "fundingRate": "-0.000013",
6506
+ # "fundingRateInterval": "8",
6507
+ # "nextUpdate": "1745510400000",
6508
+ # "minFundingRate": "-0.003",
6509
+ # "maxFundingRate": "0.003"
6510
+ # }
6511
+ # ]
6512
+ # }
6513
+ #
6514
+ elif method == 'publicMixGetV2MixMarketFundingTime':
6515
+ response = self.publicMixGetV2MixMarketFundingTime(self.extend(request, params))
6516
+ #
6517
+ # {
6518
+ # "code": "00000",
6519
+ # "msg": "success",
6520
+ # "requestTime": 1745402092428,
6521
+ # "data": [
6522
+ # {
6523
+ # "symbol": "BTCUSDT",
6524
+ # "nextFundingTime": "1745424000000",
6525
+ # "ratePeriod": "8"
6526
+ # }
6527
+ # ]
6528
+ # }
6529
+ #
6530
+ data = self.safe_list(response, 'data', [])
6476
6531
  return self.parse_funding_rate(data[0], market)
6477
6532
 
6478
6533
  def fetch_funding_rates(self, symbols: Strings = None, params={}) -> FundingRates:
@@ -6535,11 +6590,23 @@ class bitget(Exchange, ImplicitAPI):
6535
6590
 
6536
6591
  def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
6537
6592
  #
6538
- # fetchFundingRate
6593
+ # fetchFundingRate: publicMixGetV2MixMarketCurrentFundRate
6539
6594
  #
6540
6595
  # {
6541
6596
  # "symbol": "BTCUSDT",
6542
- # "fundingRate": "-0.000182"
6597
+ # "fundingRate": "-0.000013",
6598
+ # "fundingRateInterval": "8",
6599
+ # "nextUpdate": "1745510400000",
6600
+ # "minFundingRate": "-0.003",
6601
+ # "maxFundingRate": "0.003"
6602
+ # }
6603
+ #
6604
+ # fetchFundingRate: publicMixGetV2MixMarketFundingTime
6605
+ #
6606
+ # {
6607
+ # "symbol": "BTCUSDT",
6608
+ # "nextFundingTime": "1745424000000",
6609
+ # "ratePeriod": "8"
6543
6610
  # }
6544
6611
  #
6545
6612
  # fetchFundingInterval
@@ -6549,7 +6616,9 @@ class bitget(Exchange, ImplicitAPI):
6549
6616
  # "nextFundingTime": "1727942400000",
6550
6617
  # "ratePeriod": "8"
6551
6618
  # }
6619
+ #
6552
6620
  # fetchFundingRates
6621
+ #
6553
6622
  # {
6554
6623
  # "symbol": "BTCUSD",
6555
6624
  # "lastPr": "29904.5",
@@ -6575,10 +6644,11 @@ class bitget(Exchange, ImplicitAPI):
6575
6644
  # "open24h": "0",
6576
6645
  # "markPrice": "12345"
6577
6646
  # }
6647
+ #
6578
6648
  marketId = self.safe_string(contract, 'symbol')
6579
6649
  symbol = self.safe_symbol(marketId, market, None, 'swap')
6580
- fundingTimestamp = self.safe_integer(contract, 'nextFundingTime')
6581
- interval = self.safe_string(contract, 'ratePeriod')
6650
+ fundingTimestamp = self.safe_integer_2(contract, 'nextFundingTime', 'nextUpdate')
6651
+ interval = self.safe_string_2(contract, 'ratePeriod', 'fundingRateInterval')
6582
6652
  timestamp = self.safe_integer(contract, 'ts')
6583
6653
  markPrice = self.safe_number(contract, 'markPrice')
6584
6654
  indexPrice = self.safe_number(contract, 'indexPrice')
ccxt/bitmart.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.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
- def fetch_positions(self, symbols: Strings = None, params={}):
4657
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
4658
4658
  """
4659
4659
  fetch all open contract positions
4660
4660
 
ccxt/bitmex.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.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
- def fetch_positions(self, symbols: Strings = None, params={}):
2185
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2186
2186
  """
2187
2187
  fetch all open positions
2188
2188
 
ccxt/cex.py CHANGED
@@ -554,7 +554,7 @@ class cex(Exchange, ImplicitAPI):
554
554
  'askVolume': None,
555
555
  'vwap': None,
556
556
  'open': None,
557
- 'close': self.safe_string(ticker, 'lastTradePrice'),
557
+ '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 )
558
558
  'previousClose': None,
559
559
  'change': self.safe_number(ticker, 'priceChange'),
560
560
  'percentage': self.safe_number(ticker, 'priceChangePercentage'),
ccxt/coinbase.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.coinbase import ImplicitAPI
8
8
  import hashlib
9
- 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
9
+ 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
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -386,6 +386,7 @@ class coinbase(Exchange, ImplicitAPI):
386
386
  'fetchBalance': 'v2PrivateGetAccounts', # 'v2PrivateGetAccounts' or 'v3PrivateGetBrokerageAccounts'
387
387
  'fetchTime': 'v2PublicGetTime', # 'v2PublicGetTime' or 'v3PublicGetBrokerageTime'
388
388
  'user_native_currency': 'USD', # needed to get fees for v3
389
+ 'aliasCbMarketIds': {},
389
390
  },
390
391
  'features': {
391
392
  'default': {
@@ -1473,7 +1474,29 @@ class coinbase(Exchange, ImplicitAPI):
1473
1474
  perpetualData = self.safe_list(perpetualFutures, 'products', [])
1474
1475
  for i in range(0, len(perpetualData)):
1475
1476
  result.append(self.parse_contract_market(perpetualData[i], perpetualFeeTier))
1476
- return result
1477
+ # remove aliases
1478
+ self.options['aliasCbMarketIds'] = {}
1479
+ newMarkets = []
1480
+ for i in range(0, len(result)):
1481
+ market = result[i]
1482
+ info = self.safe_value(market, 'info', {})
1483
+ realMarketIds = self.safe_list(info, 'alias_to', [])
1484
+ length = len(realMarketIds)
1485
+ if length > 0:
1486
+ self.options['aliasCbMarketIds'][market['id']] = realMarketIds[0]
1487
+ self.options['aliasCbMarketIds'][market['symbol']] = realMarketIds[0]
1488
+ else:
1489
+ newMarkets.append(market)
1490
+ return newMarkets
1491
+
1492
+ def market(self, symbol: str) -> MarketInterface:
1493
+ finalSymbol = self.safe_string(self.options['aliasCbMarketIds'], symbol, symbol)
1494
+ return super(coinbase, self).market(finalSymbol)
1495
+
1496
+ def safe_market(self, marketId: Str = None, market: Market = None, delimiter: Str = None, marketType: Str = None) -> MarketInterface:
1497
+ if marketId in self.options['aliasCbMarketIds']:
1498
+ return self.market(marketId)
1499
+ return super(coinbase, self).safe_market(marketId, market, delimiter, marketType)
1477
1500
 
1478
1501
  def parse_spot_market(self, market, feeTier) -> MarketInterface:
1479
1502
  #
@@ -1882,6 +1905,7 @@ class coinbase(Exchange, ImplicitAPI):
1882
1905
  'withdraw': None,
1883
1906
  'fee': None,
1884
1907
  'precision': None,
1908
+ 'networks': {},
1885
1909
  'limits': {
1886
1910
  'amount': {
1887
1911
  'min': self.safe_number(currency, 'min_size'),
@@ -2193,10 +2217,11 @@ class coinbase(Exchange, ImplicitAPI):
2193
2217
  ask = self.safe_number(asks[0], 'price')
2194
2218
  askVolume = self.safe_number(asks[0], 'size')
2195
2219
  marketId = self.safe_string(ticker, 'product_id')
2220
+ market = self.safe_market(marketId, market)
2196
2221
  last = self.safe_number(ticker, 'price')
2197
2222
  datetime = self.safe_string(ticker, 'time')
2198
2223
  return self.safe_ticker({
2199
- 'symbol': self.safe_symbol(marketId, market),
2224
+ 'symbol': market['symbol'],
2200
2225
  'timestamp': self.parse8601(datetime),
2201
2226
  'datetime': datetime,
2202
2227
  'bid': bid,
@@ -4409,7 +4434,7 @@ class coinbase(Exchange, ImplicitAPI):
4409
4434
  order = self.safe_dict(response, 'success_response', {})
4410
4435
  return self.parse_order(order)
4411
4436
 
4412
- def fetch_positions(self, symbols: Strings = None, params={}):
4437
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
4413
4438
  """
4414
4439
  fetch all open positions
4415
4440
 
ccxt/coincatch.py CHANGED
@@ -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
+ 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
+ self.load_markets()
739
+ response = 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
  def fetch_markets(self, params={}) -> List[Market]:
728
794
  """
729
795
  retrieves data on all markets for the exchange
ccxt/coinex.py CHANGED
@@ -3858,7 +3858,7 @@ class coinex(Exchange, ImplicitAPI):
3858
3858
  data = self.safe_list(response, 'data', [])
3859
3859
  return self.parse_trades(data, market, since, limit)
3860
3860
 
3861
- def fetch_positions(self, symbols: Strings = None, params={}):
3861
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
3862
3862
  """
3863
3863
  fetch all open positions
3864
3864
 
ccxt/cryptocom.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.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, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction
9
+ from ccxt.base.types import Account, Any, Balances, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -2789,7 +2789,7 @@ class cryptocom(Exchange, ImplicitAPI):
2789
2789
  data = self.safe_list(result, 'data', [])
2790
2790
  return self.parse_position(self.safe_dict(data, 0), market)
2791
2791
 
2792
- def fetch_positions(self, symbols: Strings = None, params={}):
2792
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2793
2793
  """
2794
2794
  fetch all open positions
2795
2795
 
ccxt/defx.py CHANGED
@@ -1494,7 +1494,7 @@ class defx(Exchange, ImplicitAPI):
1494
1494
  first = self.safe_dict(data, 0, {})
1495
1495
  return self.parse_position(first, market)
1496
1496
 
1497
- def fetch_positions(self, symbols: Strings = None, params={}):
1497
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
1498
1498
  """
1499
1499
  fetch all open positions
1500
1500
 
ccxt/delta.py CHANGED
@@ -1660,7 +1660,7 @@ class delta(Exchange, ImplicitAPI):
1660
1660
  result = self.safe_dict(response, 'result', {})
1661
1661
  return self.parse_position(result, market)
1662
1662
 
1663
- def fetch_positions(self, symbols: Strings = None, params={}):
1663
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
1664
1664
  """
1665
1665
  fetch all open positions
1666
1666
 
ccxt/deribit.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.deribit import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Greeks, Int, Market, Num, Option, OptionChain, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFees, Transaction, MarketInterface, TransferEntry
9
+ from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Greeks, Int, Market, Num, Option, OptionChain, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFees, 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
@@ -2673,7 +2673,7 @@ class deribit(Exchange, ImplicitAPI):
2673
2673
  result = self.safe_dict(response, 'result')
2674
2674
  return self.parse_position(result)
2675
2675
 
2676
- def fetch_positions(self, symbols: Strings = None, params={}):
2676
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2677
2677
  """
2678
2678
  fetch all open positions
2679
2679
 
ccxt/derive.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.derive import ImplicitAPI
8
- from ccxt.base.types import Any, Balances, Bool, Currencies, Currency, Int, Market, MarketType, Num, Order, OrderSide, OrderType, Str, Strings, Ticker, FundingRate, Trade, Transaction
8
+ from ccxt.base.types import Any, Balances, Bool, Currencies, Currency, Int, Market, MarketType, Num, Order, OrderSide, OrderType, Position, Str, Strings, Ticker, FundingRate, Trade, Transaction
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import AuthenticationError
@@ -2027,7 +2027,7 @@ class derive(Exchange, ImplicitAPI):
2027
2027
  trades = self.safe_list(result, 'trades', [])
2028
2028
  return self.parse_trades(trades, market, since, limit, params)
2029
2029
 
2030
- def fetch_positions(self, symbols: Strings = None, params={}):
2030
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2031
2031
  """
2032
2032
  fetch all open positions
2033
2033