ccxt 4.4.90__py2.py3-none-any.whl → 4.4.91__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 (57) hide show
  1. ccxt/__init__.py +1 -3
  2. ccxt/async_support/__init__.py +1 -3
  3. ccxt/async_support/base/exchange.py +6 -3
  4. ccxt/async_support/base/ws/client.py +173 -64
  5. ccxt/async_support/base/ws/future.py +23 -50
  6. ccxt/async_support/binance.py +1 -1
  7. ccxt/async_support/bitmex.py +2 -1
  8. ccxt/async_support/cex.py +61 -0
  9. ccxt/async_support/cryptocom.py +17 -2
  10. ccxt/async_support/cryptomus.py +1 -1
  11. ccxt/async_support/exmo.py +14 -7
  12. ccxt/async_support/gate.py +2 -2
  13. ccxt/async_support/hyperliquid.py +104 -53
  14. ccxt/async_support/kraken.py +26 -1
  15. ccxt/async_support/mexc.py +1 -0
  16. ccxt/async_support/modetrade.py +2 -2
  17. ccxt/async_support/paradex.py +1 -1
  18. ccxt/base/exchange.py +8 -5
  19. ccxt/binance.py +1 -1
  20. ccxt/bitmex.py +2 -1
  21. ccxt/cex.py +61 -0
  22. ccxt/cryptocom.py +17 -2
  23. ccxt/cryptomus.py +1 -1
  24. ccxt/exmo.py +13 -7
  25. ccxt/gate.py +2 -2
  26. ccxt/hyperliquid.py +104 -53
  27. ccxt/kraken.py +26 -1
  28. ccxt/mexc.py +1 -0
  29. ccxt/modetrade.py +2 -2
  30. ccxt/paradex.py +1 -1
  31. ccxt/pro/__init__.py +1 -1
  32. ccxt/pro/bitstamp.py +1 -1
  33. ccxt/pro/bybit.py +6 -136
  34. ccxt/pro/kraken.py +246 -258
  35. ccxt/pro/mexc.py +0 -1
  36. {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/METADATA +6 -7
  37. {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/RECORD +40 -57
  38. ccxt/abstract/coinlist.py +0 -57
  39. ccxt/async_support/base/ws/aiohttp_client.py +0 -147
  40. ccxt/async_support/bitcoincom.py +0 -18
  41. ccxt/async_support/bitfinex1.py +0 -1711
  42. ccxt/async_support/bitpanda.py +0 -17
  43. ccxt/async_support/coinlist.py +0 -2542
  44. ccxt/async_support/poloniexfutures.py +0 -1875
  45. ccxt/bitcoincom.py +0 -18
  46. ccxt/bitfinex1.py +0 -1710
  47. ccxt/bitpanda.py +0 -17
  48. ccxt/coinlist.py +0 -2542
  49. ccxt/poloniexfutures.py +0 -1875
  50. ccxt/pro/bitcoincom.py +0 -35
  51. ccxt/pro/bitfinex1.py +0 -635
  52. ccxt/pro/bitpanda.py +0 -16
  53. ccxt/pro/poloniexfutures.py +0 -1004
  54. ccxt/pro/wazirx.py +0 -766
  55. {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/LICENSE.txt +0 -0
  56. {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/WHEEL +0 -0
  57. {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/top_level.txt +0 -0
@@ -461,7 +461,7 @@ class cryptomus(Exchange, ImplicitAPI):
461
461
  #
462
462
  # {
463
463
  # "currency_pair": "XMR_USDT",
464
- # "last_price": "158.04829771",
464
+ # "last_price": "158.04829772",
465
465
  # "base_volume": "0.35185785",
466
466
  # "quote_volume": "55.523761128544"
467
467
  # }
@@ -5,6 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.exmo import ImplicitAPI
8
+ import asyncio
8
9
  import hashlib
9
10
  from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, OrderBooks, Trade, TradingFees, Transaction
10
11
  from typing import List
@@ -779,7 +780,8 @@ class exmo(Exchange, ImplicitAPI):
779
780
  :param dict [params]: extra parameters specific to the exchange API endpoint
780
781
  :returns dict[]: an array of objects representing market data
781
782
  """
782
- response = await self.publicGetPairSettings(params)
783
+ promises = []
784
+ promises.append(self.publicGetPairSettings(params))
783
785
  #
784
786
  # {
785
787
  # "BTC_USD":{
@@ -796,8 +798,9 @@ class exmo(Exchange, ImplicitAPI):
796
798
  # }
797
799
  #
798
800
  marginPairsDict: dict = {}
799
- if self.check_required_credentials(False):
800
- marginPairs = await self.privatePostMarginPairList(params)
801
+ fetchMargin = self.check_required_credentials(False)
802
+ if fetchMargin:
803
+ promises.append(self.privatePostMarginPairList(params))
801
804
  #
802
805
  # {
803
806
  # "pairs": [
@@ -827,14 +830,18 @@ class exmo(Exchange, ImplicitAPI):
827
830
  # ]
828
831
  # }
829
832
  #
830
- pairs = self.safe_value(marginPairs, 'pairs')
833
+ responses = await asyncio.gather(*promises)
834
+ spotResponse = responses[0]
835
+ if fetchMargin:
836
+ marginPairs = responses[1]
837
+ pairs = self.safe_list(marginPairs, 'pairs')
831
838
  marginPairsDict = self.index_by(pairs, 'name')
832
- keys = list(response.keys())
839
+ keys = list(spotResponse.keys())
833
840
  result = []
834
841
  for i in range(0, len(keys)):
835
842
  id = keys[i]
836
- market = response[id]
837
- marginMarket = self.safe_value(marginPairsDict, id)
843
+ market = spotResponse[id]
844
+ marginMarket = self.safe_dict(marginPairsDict, id)
838
845
  symbol = id.replace('_', '/')
839
846
  baseId, quoteId = symbol.split('/')
840
847
  base = self.safe_currency_code(baseId)
@@ -1242,7 +1242,7 @@ class gate(Exchange, ImplicitAPI):
1242
1242
  self.fetch_option_markets(params),
1243
1243
  ]
1244
1244
  if not sandboxMode:
1245
- # gate does not have a sandbox for spot markets
1245
+ # gate doesn't have a sandbox for spot markets
1246
1246
  mainnetOnly = [self.fetch_spot_markets(params)]
1247
1247
  rawPromises = self.array_concat(rawPromises, mainnetOnly)
1248
1248
  promises = await asyncio.gather(*rawPromises)
@@ -1653,7 +1653,7 @@ class gate(Exchange, ImplicitAPI):
1653
1653
  'contractSize': self.parse_number('1'),
1654
1654
  'expiry': expiry,
1655
1655
  'expiryDatetime': self.iso8601(expiry),
1656
- 'strike': strike,
1656
+ 'strike': self.parse_number(strike),
1657
1657
  'optionType': optionType,
1658
1658
  'precision': {
1659
1659
  'amount': self.parse_number('1'), # all options have self step size
@@ -57,6 +57,7 @@ class hyperliquid(Exchange, ImplicitAPI):
57
57
  'createMarketSellOrderWithCost': False,
58
58
  'createOrder': True,
59
59
  'createOrders': True,
60
+ 'createOrderWithTakeProfitAndStopLoss': True,
60
61
  'createReduceOnlyOrder': True,
61
62
  'createStopOrder': True,
62
63
  'createTriggerOrder': True,
@@ -240,7 +241,16 @@ class hyperliquid(Exchange, ImplicitAPI):
240
241
  'triggerDirection': False,
241
242
  'stopLossPrice': False,
242
243
  'takeProfitPrice': False,
243
- 'attachedStopLossTakeProfit': None,
244
+ 'attachedStopLossTakeProfit': {
245
+ 'triggerPriceType': {
246
+ 'last': False,
247
+ 'mark': False,
248
+ 'index': False,
249
+ },
250
+ 'triggerPrice': True,
251
+ 'type': True,
252
+ 'price': True,
253
+ },
244
254
  'timeInForce': {
245
255
  'IOC': True,
246
256
  'FOK': False,
@@ -1404,6 +1414,65 @@ class hyperliquid(Exchange, ImplicitAPI):
1404
1414
  statuses = self.safe_list(data, 'statuses', [])
1405
1415
  return self.parse_orders(statuses, None)
1406
1416
 
1417
+ def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: str, price: Str = None, params={}):
1418
+ market = self.market(symbol)
1419
+ type = type.upper()
1420
+ side = side.upper()
1421
+ isMarket = (type == 'MARKET')
1422
+ isBuy = (side == 'BUY')
1423
+ clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_id')
1424
+ slippage = self.safe_string(params, 'slippage')
1425
+ defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
1426
+ postOnly = self.safe_bool(params, 'postOnly', False)
1427
+ if postOnly:
1428
+ defaultTimeInForce = 'alo'
1429
+ timeInForce = self.safe_string_lower(params, 'timeInForce', defaultTimeInForce)
1430
+ timeInForce = self.capitalize(timeInForce)
1431
+ triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
1432
+ stopLossPrice = self.safe_string(params, 'stopLossPrice', triggerPrice)
1433
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
1434
+ isTrigger = (stopLossPrice or takeProfitPrice)
1435
+ px = None
1436
+ if isMarket:
1437
+ if price is None:
1438
+ raise ArgumentsRequired(self.id + ' market orders require price to calculate the max slippage price. Default slippage can be set in options(default is 5%).')
1439
+ px = Precise.string_mul(price, Precise.string_add('1', slippage)) if (isBuy) else Precise.string_mul(price, Precise.string_sub('1', slippage))
1440
+ px = self.price_to_precision(symbol, px) # round after adding slippage
1441
+ else:
1442
+ px = self.price_to_precision(symbol, price)
1443
+ sz = self.amount_to_precision(symbol, amount)
1444
+ reduceOnly = self.safe_bool(params, 'reduceOnly', False)
1445
+ orderType: dict = {}
1446
+ if isTrigger:
1447
+ isTp = False
1448
+ if takeProfitPrice is not None:
1449
+ triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
1450
+ isTp = True
1451
+ else:
1452
+ triggerPrice = self.price_to_precision(symbol, stopLossPrice)
1453
+ orderType['trigger'] = {
1454
+ 'isMarket': isMarket,
1455
+ 'triggerPx': triggerPrice,
1456
+ 'tpsl': 'tp' if (isTp) else 'sl',
1457
+ }
1458
+ else:
1459
+ orderType['limit'] = {
1460
+ 'tif': timeInForce,
1461
+ }
1462
+ params = self.omit(params, ['clientOrderId', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce', 'client_id', 'reduceOnly', 'postOnly'])
1463
+ orderObj: dict = {
1464
+ 'a': self.parse_to_int(market['baseId']),
1465
+ 'b': isBuy,
1466
+ 'p': px,
1467
+ 's': sz,
1468
+ 'r': reduceOnly,
1469
+ 't': orderType,
1470
+ # 'c': clientOrderId,
1471
+ }
1472
+ if clientOrderId is not None:
1473
+ orderObj['c'] = clientOrderId
1474
+ return orderObj
1475
+
1407
1476
  def create_orders_request(self, orders, params={}) -> dict:
1408
1477
  """
1409
1478
  create a list of trade orders
@@ -1431,77 +1500,59 @@ class hyperliquid(Exchange, ImplicitAPI):
1431
1500
  params = self.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce'])
1432
1501
  nonce = self.milliseconds()
1433
1502
  orderReq = []
1503
+ grouping = 'na'
1434
1504
  for i in range(0, len(orders)):
1435
1505
  rawOrder = orders[i]
1436
1506
  marketId = self.safe_string(rawOrder, 'symbol')
1437
1507
  market = self.market(marketId)
1438
1508
  symbol = market['symbol']
1439
1509
  type = self.safe_string_upper(rawOrder, 'type')
1440
- isMarket = (type == 'MARKET')
1441
1510
  side = self.safe_string_upper(rawOrder, 'side')
1442
- isBuy = (side == 'BUY')
1443
1511
  amount = self.safe_string(rawOrder, 'amount')
1444
1512
  price = self.safe_string(rawOrder, 'price')
1445
1513
  orderParams = self.safe_dict(rawOrder, 'params', {})
1446
- clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1447
1514
  slippage = self.safe_string(orderParams, 'slippage', defaultSlippage)
1448
- defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
1449
- postOnly = self.safe_bool(orderParams, 'postOnly', False)
1450
- if postOnly:
1451
- defaultTimeInForce = 'alo'
1452
- timeInForce = self.safe_string_lower(orderParams, 'timeInForce', defaultTimeInForce)
1453
- timeInForce = self.capitalize(timeInForce)
1454
- triggerPrice = self.safe_string_2(orderParams, 'triggerPrice', 'stopPrice')
1455
- stopLossPrice = self.safe_string(orderParams, 'stopLossPrice', triggerPrice)
1456
- takeProfitPrice = self.safe_string(orderParams, 'takeProfitPrice')
1457
- isTrigger = (stopLossPrice or takeProfitPrice)
1458
- px = None
1459
- if isMarket:
1460
- if price is None:
1461
- raise ArgumentsRequired(self.id + ' market orders require price to calculate the max slippage price. Default slippage can be set in options(default is 5%).')
1462
- px = Precise.string_mul(price, Precise.string_add('1', slippage)) if (isBuy) else Precise.string_mul(price, Precise.string_sub('1', slippage))
1463
- px = self.price_to_precision(symbol, px) # round after adding slippage
1464
- else:
1465
- px = self.price_to_precision(symbol, price)
1466
- sz = self.amount_to_precision(symbol, amount)
1467
- reduceOnly = self.safe_bool(orderParams, 'reduceOnly', False)
1468
- orderType: dict = {}
1515
+ orderParams['slippage'] = slippage
1516
+ stopLoss = self.safe_value(orderParams, 'stopLoss')
1517
+ takeProfit = self.safe_value(orderParams, 'takeProfit')
1518
+ isTrigger = (stopLoss or takeProfit)
1519
+ orderParams = self.omit(orderParams, ['stopLoss', 'takeProfit'])
1520
+ mainOrderObj: dict = self.create_order_request(symbol, type, side, amount, price, orderParams)
1521
+ orderReq.append(mainOrderObj)
1469
1522
  if isTrigger:
1470
- isTp = False
1471
- if takeProfitPrice is not None:
1472
- triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
1473
- isTp = True
1523
+ # grouping opposed orders for sl/tp
1524
+ stopLossOrderTriggerPrice = self.safe_string_n(stopLoss, ['triggerPrice', 'stopPrice'])
1525
+ stopLossOrderType = self.safe_string(stopLoss, 'type')
1526
+ stopLossOrderLimitPrice = self.safe_string_n(stopLoss, ['price', 'stopLossPrice'], stopLossOrderTriggerPrice)
1527
+ takeProfitOrderTriggerPrice = self.safe_string_n(takeProfit, ['triggerPrice', 'stopPrice'])
1528
+ takeProfitOrderType = self.safe_string(takeProfit, 'type')
1529
+ takeProfitOrderLimitPrice = self.safe_string_n(takeProfit, ['price', 'takeProfitPrice'], takeProfitOrderTriggerPrice)
1530
+ grouping = 'normalTpsl'
1531
+ orderParams = self.omit(orderParams, ['stopLoss', 'takeProfit'])
1532
+ triggerOrderSide = ''
1533
+ if side == 'BUY':
1534
+ triggerOrderSide = 'sell'
1474
1535
  else:
1475
- triggerPrice = self.price_to_precision(symbol, stopLossPrice)
1476
- orderType['trigger'] = {
1477
- 'isMarket': isMarket,
1478
- 'triggerPx': triggerPrice,
1479
- 'tpsl': 'tp' if (isTp) else 'sl',
1480
- }
1481
- else:
1482
- orderType['limit'] = {
1483
- 'tif': timeInForce,
1484
- }
1485
- orderParams = self.omit(orderParams, ['clientOrderId', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce', 'client_id', 'reduceOnly', 'postOnly'])
1486
- orderObj: dict = {
1487
- 'a': self.parse_to_int(market['baseId']),
1488
- 'b': isBuy,
1489
- 'p': px,
1490
- 's': sz,
1491
- 'r': reduceOnly,
1492
- 't': orderType,
1493
- # 'c': clientOrderId,
1494
- }
1495
- if clientOrderId is not None:
1496
- orderObj['c'] = clientOrderId
1497
- orderReq.append(orderObj)
1536
+ triggerOrderSide = 'buy'
1537
+ if takeProfit is not None:
1538
+ orderObj: dict = self.create_order_request(symbol, takeProfitOrderType, triggerOrderSide, amount, takeProfitOrderLimitPrice, self.extend(orderParams, {
1539
+ 'takeProfitPrice': takeProfitOrderTriggerPrice,
1540
+ 'reduceOnly': True,
1541
+ }))
1542
+ orderReq.append(orderObj)
1543
+ if stopLoss is not None:
1544
+ orderObj: dict = self.create_order_request(symbol, stopLossOrderType, triggerOrderSide, amount, stopLossOrderLimitPrice, self.extend(orderParams, {
1545
+ 'stopLossPrice': stopLossOrderTriggerPrice,
1546
+ 'reduceOnly': True,
1547
+ }))
1548
+ orderReq.append(orderObj)
1498
1549
  vaultAddress = None
1499
1550
  vaultAddress, params = self.handle_option_and_params(params, 'createOrder', 'vaultAddress')
1500
1551
  vaultAddress = self.format_vault_address(vaultAddress)
1501
1552
  orderAction: dict = {
1502
1553
  'type': 'order',
1503
1554
  'orders': orderReq,
1504
- 'grouping': 'na',
1555
+ 'grouping': grouping,
1505
1556
  # 'brokerCode': 1, # cant
1506
1557
  }
1507
1558
  if vaultAddress is None:
@@ -1366,7 +1366,20 @@ class kraken(Exchange, ImplicitAPI):
1366
1366
  # "maker": False
1367
1367
  # }
1368
1368
  #
1369
+ # watchTrades
1370
+ #
1371
+ # {
1372
+ # "symbol": "BTC/USD",
1373
+ # "side": "buy",
1374
+ # "price": 109601.2,
1375
+ # "qty": 0.04561994,
1376
+ # "ord_type": "market",
1377
+ # "trade_id": 83449369,
1378
+ # "timestamp": "2025-05-27T11:24:03.847761Z"
1379
+ # }
1380
+ #
1369
1381
  timestamp = None
1382
+ datetime = None
1370
1383
  side = None
1371
1384
  type = None
1372
1385
  price = None
@@ -1409,6 +1422,14 @@ class kraken(Exchange, ImplicitAPI):
1409
1422
  'cost': self.safe_string(trade, 'fee'),
1410
1423
  'currency': currency,
1411
1424
  }
1425
+ else:
1426
+ symbol = self.safe_string(trade, 'symbol')
1427
+ datetime = self.safe_string(trade, 'timestamp')
1428
+ id = self.safe_string(trade, 'trade_id')
1429
+ side = self.safe_string(trade, 'side')
1430
+ type = self.safe_string(trade, 'ord_type')
1431
+ price = self.safe_string(trade, 'price')
1432
+ amount = self.safe_string(trade, 'qty')
1412
1433
  if market is not None:
1413
1434
  symbol = market['symbol']
1414
1435
  cost = self.safe_string(trade, 'cost')
@@ -1416,12 +1437,16 @@ class kraken(Exchange, ImplicitAPI):
1416
1437
  takerOrMaker = None
1417
1438
  if maker is not None:
1418
1439
  takerOrMaker = 'maker' if maker else 'taker'
1440
+ if datetime is None:
1441
+ datetime = self.iso8601(timestamp)
1442
+ else:
1443
+ timestamp = self.parse8601(datetime)
1419
1444
  return self.safe_trade({
1420
1445
  'id': id,
1421
1446
  'order': orderId,
1422
1447
  'info': trade,
1423
1448
  'timestamp': timestamp,
1424
- 'datetime': self.iso8601(timestamp),
1449
+ 'datetime': datetime,
1425
1450
  'symbol': symbol,
1426
1451
  'type': type,
1427
1452
  'side': side,
@@ -855,6 +855,7 @@ class mexc(Exchange, ImplicitAPI):
855
855
  'PROS': 'PROSFINANCE', # conflict with Prosper
856
856
  'SIN': 'SINCITYTOKEN',
857
857
  'SOUL': 'SOULSWAP',
858
+ 'XBT': 'XBT', # restore original mapping
858
859
  },
859
860
  'exceptions': {
860
861
  'exact': {
@@ -1651,7 +1651,7 @@ class modetrade(Exchange, ImplicitAPI):
1651
1651
  #
1652
1652
  # {
1653
1653
  # "success": True,
1654
- # "timestamp": 1702989203989,
1654
+ # "timestamp": 1702989203988,
1655
1655
  # "data": {
1656
1656
  # "status": "CANCEL_SENT"
1657
1657
  # }
@@ -1659,7 +1659,7 @@ class modetrade(Exchange, ImplicitAPI):
1659
1659
  #
1660
1660
  # {
1661
1661
  # "success": True,
1662
- # "timestamp": 1702989203989,
1662
+ # "timestamp": 1702989203988,
1663
1663
  # "status": "CANCEL_SENT"
1664
1664
  # }
1665
1665
  #
@@ -785,7 +785,7 @@ class paradex(Exchange, ImplicitAPI):
785
785
  # "ask": "69578.2",
786
786
  # "volume_24h": "5815541.397939004",
787
787
  # "total_volume": "584031465.525259686",
788
- # "created_at": 1718170156580,
788
+ # "created_at": 1718170156581,
789
789
  # "underlying_price": "67367.37268422",
790
790
  # "open_interest": "162.272",
791
791
  # "funding_rate": "0.01629574927887",
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.90'
7
+ __version__ = '4.4.91'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2580,6 +2580,9 @@ class Exchange(object):
2580
2580
  def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}):
2581
2581
  raise NotSupported(self.id + ' watchTrades() is not supported yet')
2582
2582
 
2583
+ def un_watch_orders(self, symbol: Str = None, params={}):
2584
+ raise NotSupported(self.id + ' unWatchOrders() is not supported yet')
2585
+
2583
2586
  def un_watch_trades(self, symbol: str, params={}):
2584
2587
  raise NotSupported(self.id + ' unWatchTrades() is not supported yet')
2585
2588
 
@@ -6894,7 +6897,7 @@ class Exchange(object):
6894
6897
  symbolAndTimeFrame = symbolsAndTimeFrames[i]
6895
6898
  symbol = self.safe_string(symbolAndTimeFrame, 0)
6896
6899
  timeframe = self.safe_string(symbolAndTimeFrame, 1)
6897
- if symbol in self.ohlcvs:
6900
+ if (self.ohlcvs is not None) and (symbol in self.ohlcvs):
6898
6901
  if timeframe in self.ohlcvs[symbol]:
6899
6902
  del self.ohlcvs[symbol][timeframe]
6900
6903
  elif symbolsLength > 0:
@@ -6910,7 +6913,7 @@ class Exchange(object):
6910
6913
  if symbol in self.tickers:
6911
6914
  del self.tickers[symbol]
6912
6915
  else:
6913
- if topic == 'myTrades':
6916
+ if topic == 'myTrades' and (self.myTrades is not None):
6914
6917
  # don't reset self.myTrades directly here
6915
6918
  # because in c# we need to use a different object(thread-safe dict)
6916
6919
  keys = list(self.myTrades.keys())
@@ -6918,13 +6921,13 @@ class Exchange(object):
6918
6921
  key = keys[i]
6919
6922
  if key in self.myTrades:
6920
6923
  del self.myTrades[key]
6921
- elif topic == 'orders':
6924
+ elif topic == 'orders' and (self.orders is not None):
6922
6925
  orderSymbols = list(self.orders.keys())
6923
6926
  for i in range(0, len(orderSymbols)):
6924
6927
  orderSymbol = orderSymbols[i]
6925
6928
  if orderSymbol in self.orders:
6926
6929
  del self.orders[orderSymbol]
6927
- elif topic == 'ticker':
6930
+ elif topic == 'ticker' and (self.tickers is not None):
6928
6931
  tickerSymbols = list(self.tickers.keys())
6929
6932
  for i in range(0, len(tickerSymbols)):
6930
6933
  tickerSymbol = tickerSymbols[i]
ccxt/binance.py CHANGED
@@ -3903,7 +3903,7 @@ class binance(Exchange, ImplicitAPI):
3903
3903
  #
3904
3904
  # {
3905
3905
  # "symbol": "BTCUSDT",
3906
- # "markPrice": "11793.63104562", # mark price
3906
+ # "markPrice": "11793.63104561", # mark price
3907
3907
  # "indexPrice": "11781.80495970", # index price
3908
3908
  # "estimatedSettlePrice": "11781.16138815", # Estimated Settle Price, only useful in the last hour before the settlement starts
3909
3909
  # "lastFundingRate": "0.00038246", # This is the lastest estimated funding rate
ccxt/bitmex.py CHANGED
@@ -101,6 +101,7 @@ class bitmex(Exchange, ImplicitAPI):
101
101
  'fetchTransactions': 'emulated',
102
102
  'fetchTransfer': False,
103
103
  'fetchTransfers': False,
104
+ 'index': True,
104
105
  'reduceMargin': None,
105
106
  'sandbox': True,
106
107
  'setLeverage': True,
@@ -427,8 +428,8 @@ class bitmex(Exchange, ImplicitAPI):
427
428
  # # "mediumPrecision": "8",
428
429
  # # "shorterPrecision": "4",
429
430
  # # "symbol": "₿",
430
- # # "weight": "1",
431
431
  # # "tickLog": "0",
432
+ # # "weight": "1",
432
433
  # "enabled": True,
433
434
  # "isMarginCurrency": True,
434
435
  # "minDepositAmount": "10000",
ccxt/cex.py CHANGED
@@ -35,34 +35,95 @@ class cex(Exchange, ImplicitAPI):
35
35
  'swap': False,
36
36
  'future': False,
37
37
  'option': False,
38
+ 'addMargin': False,
39
+ 'borrowCrossMargin': False,
40
+ 'borrowIsolatedMargin': False,
41
+ 'borrowMargin': False,
38
42
  'cancelAllOrders': True,
39
43
  'cancelOrder': True,
44
+ 'closeAllPositions': False,
45
+ 'closePosition': False,
40
46
  'createOrder': True,
47
+ 'createOrderWithTakeProfitAndStopLoss': False,
48
+ 'createOrderWithTakeProfitAndStopLossWs': False,
49
+ 'createPostOnlyOrder': False,
41
50
  'createReduceOnlyOrder': False,
42
51
  'createStopOrder': True,
43
52
  'createTriggerOrder': True,
44
53
  'fetchAccounts': True,
45
54
  'fetchBalance': True,
55
+ 'fetchBorrowInterest': False,
56
+ 'fetchBorrowRate': False,
57
+ 'fetchBorrowRateHistories': False,
58
+ 'fetchBorrowRateHistory': False,
59
+ 'fetchBorrowRates': False,
60
+ 'fetchBorrowRatesPerSymbol': False,
46
61
  'fetchClosedOrder': True,
47
62
  'fetchClosedOrders': True,
63
+ 'fetchCrossBorrowRate': False,
64
+ 'fetchCrossBorrowRates': False,
48
65
  'fetchCurrencies': True,
49
66
  'fetchDepositAddress': True,
50
67
  'fetchDepositsWithdrawals': True,
51
68
  'fetchFundingHistory': False,
69
+ 'fetchFundingInterval': False,
70
+ 'fetchFundingIntervals': False,
52
71
  'fetchFundingRate': False,
53
72
  'fetchFundingRateHistory': False,
54
73
  'fetchFundingRates': False,
74
+ 'fetchGreeks': False,
75
+ 'fetchIndexOHLCV': False,
76
+ 'fetchIsolatedBorrowRate': False,
77
+ 'fetchIsolatedBorrowRates': False,
78
+ 'fetchIsolatedPositions': False,
55
79
  'fetchLedger': True,
80
+ 'fetchLeverage': False,
81
+ 'fetchLeverages': False,
82
+ 'fetchLeverageTiers': False,
83
+ 'fetchLiquidations': False,
84
+ 'fetchLongShortRatio': False,
85
+ 'fetchLongShortRatioHistory': False,
86
+ 'fetchMarginAdjustmentHistory': False,
87
+ 'fetchMarginMode': False,
88
+ 'fetchMarginModes': False,
89
+ 'fetchMarketLeverageTiers': False,
56
90
  'fetchMarkets': True,
91
+ 'fetchMarkOHLCV': False,
92
+ 'fetchMarkPrices': False,
93
+ 'fetchMyLiquidations': False,
94
+ 'fetchMySettlementHistory': False,
57
95
  'fetchOHLCV': True,
96
+ 'fetchOpenInterest': False,
97
+ 'fetchOpenInterestHistory': False,
98
+ 'fetchOpenInterests': False,
58
99
  'fetchOpenOrder': True,
59
100
  'fetchOpenOrders': True,
101
+ 'fetchOption': False,
102
+ 'fetchOptionChain': False,
60
103
  'fetchOrderBook': True,
104
+ 'fetchPosition': False,
105
+ 'fetchPositionHistory': False,
106
+ 'fetchPositionMode': False,
107
+ 'fetchPositions': False,
108
+ 'fetchPositionsForSymbol': False,
109
+ 'fetchPositionsHistory': False,
110
+ 'fetchPositionsRisk': False,
111
+ 'fetchPremiumIndexOHLCV': False,
112
+ 'fetchSettlementHistory': False,
61
113
  'fetchTicker': True,
62
114
  'fetchTickers': True,
63
115
  'fetchTime': True,
64
116
  'fetchTrades': True,
65
117
  'fetchTradingFees': True,
118
+ 'fetchVolatilityHistory': False,
119
+ 'reduceMargin': False,
120
+ 'repayCrossMargin': False,
121
+ 'repayIsolatedMargin': False,
122
+ 'repayMargin': False,
123
+ 'setLeverage': False,
124
+ 'setMargin': False,
125
+ 'setMarginMode': False,
126
+ 'setPositionMode': False,
66
127
  'transfer': True,
67
128
  },
68
129
  'urls': {
ccxt/cryptocom.py CHANGED
@@ -548,7 +548,22 @@ class cryptocom(Exchange, ImplicitAPI):
548
548
  # self endpoint requires authentication
549
549
  if not self.check_required_credentials(False):
550
550
  return None
551
- response = self.v1PrivatePostPrivateGetCurrencyNetworks(params)
551
+ skipFetchCurrencies = False
552
+ skipFetchCurrencies, params = self.handle_option_and_params(params, 'fetchCurrencies', 'skipFetchCurrencies', False)
553
+ if skipFetchCurrencies:
554
+ # sub-accounts can't access self endpoint
555
+ return None
556
+ response = {}
557
+ try:
558
+ response = self.v1PrivatePostPrivateGetCurrencyNetworks(params)
559
+ except Exception as e:
560
+ if isinstance(e, ExchangeError):
561
+ # sub-accounts can't access self endpoint
562
+ # {"code":"10001","msg":"SYS_ERROR"}
563
+ return None
564
+ raise e
565
+ # do nothing
566
+ # sub-accounts can't access self endpoint
552
567
  #
553
568
  # {
554
569
  # "id": "1747502328559",
@@ -573,7 +588,7 @@ class cryptocom(Exchange, ImplicitAPI):
573
588
  # "network_id": "CRONOS",
574
589
  # "withdrawal_fee": "0.18000000",
575
590
  # "withdraw_enabled": True,
576
- # "min_withdrawal_amount": "0.36",
591
+ # "min_withdrawal_amount": "0.35",
577
592
  # "deposit_enabled": True,
578
593
  # "confirmation_required": "15"
579
594
  # },
ccxt/cryptomus.py CHANGED
@@ -461,7 +461,7 @@ class cryptomus(Exchange, ImplicitAPI):
461
461
  #
462
462
  # {
463
463
  # "currency_pair": "XMR_USDT",
464
- # "last_price": "158.04829771",
464
+ # "last_price": "158.04829772",
465
465
  # "base_volume": "0.35185785",
466
466
  # "quote_volume": "55.523761128544"
467
467
  # }
ccxt/exmo.py CHANGED
@@ -779,7 +779,8 @@ class exmo(Exchange, ImplicitAPI):
779
779
  :param dict [params]: extra parameters specific to the exchange API endpoint
780
780
  :returns dict[]: an array of objects representing market data
781
781
  """
782
- response = self.publicGetPairSettings(params)
782
+ promises = []
783
+ promises.append(self.publicGetPairSettings(params))
783
784
  #
784
785
  # {
785
786
  # "BTC_USD":{
@@ -796,8 +797,9 @@ class exmo(Exchange, ImplicitAPI):
796
797
  # }
797
798
  #
798
799
  marginPairsDict: dict = {}
799
- if self.check_required_credentials(False):
800
- marginPairs = self.privatePostMarginPairList(params)
800
+ fetchMargin = self.check_required_credentials(False)
801
+ if fetchMargin:
802
+ promises.append(self.privatePostMarginPairList(params))
801
803
  #
802
804
  # {
803
805
  # "pairs": [
@@ -827,14 +829,18 @@ class exmo(Exchange, ImplicitAPI):
827
829
  # ]
828
830
  # }
829
831
  #
830
- pairs = self.safe_value(marginPairs, 'pairs')
832
+ responses = promises
833
+ spotResponse = responses[0]
834
+ if fetchMargin:
835
+ marginPairs = responses[1]
836
+ pairs = self.safe_list(marginPairs, 'pairs')
831
837
  marginPairsDict = self.index_by(pairs, 'name')
832
- keys = list(response.keys())
838
+ keys = list(spotResponse.keys())
833
839
  result = []
834
840
  for i in range(0, len(keys)):
835
841
  id = keys[i]
836
- market = response[id]
837
- marginMarket = self.safe_value(marginPairsDict, id)
842
+ market = spotResponse[id]
843
+ marginMarket = self.safe_dict(marginPairsDict, id)
838
844
  symbol = id.replace('_', '/')
839
845
  baseId, quoteId = symbol.split('/')
840
846
  base = self.safe_currency_code(baseId)