ccxt 4.4.12__py2.py3-none-any.whl → 4.4.13__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 (58) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/async_support/__init__.py +1 -1
  3. ccxt/async_support/base/exchange.py +4 -1
  4. ccxt/async_support/bigone.py +2 -0
  5. ccxt/async_support/binance.py +44 -1
  6. ccxt/async_support/bingx.py +69 -3
  7. ccxt/async_support/bitget.py +1 -0
  8. ccxt/async_support/bitmex.py +1 -0
  9. ccxt/async_support/bybit.py +2 -0
  10. ccxt/async_support/coinbaseinternational.py +2 -0
  11. ccxt/async_support/coinex.py +2 -0
  12. ccxt/async_support/delta.py +2 -0
  13. ccxt/async_support/deribit.py +2 -0
  14. ccxt/async_support/digifinex.py +2 -0
  15. ccxt/async_support/gate.py +2 -0
  16. ccxt/async_support/htx.py +2 -2
  17. ccxt/async_support/krakenfutures.py +2 -0
  18. ccxt/async_support/kucoinfutures.py +2 -0
  19. ccxt/async_support/okx.py +36 -0
  20. ccxt/async_support/oxfun.py +1 -0
  21. ccxt/async_support/paradex.py +1 -0
  22. ccxt/async_support/poloniex.py +1 -0
  23. ccxt/base/exchange.py +7 -1
  24. ccxt/base/types.py +2 -0
  25. ccxt/bigone.py +2 -0
  26. ccxt/binance.py +44 -1
  27. ccxt/bingx.py +69 -3
  28. ccxt/bitget.py +1 -0
  29. ccxt/bitmex.py +1 -0
  30. ccxt/bybit.py +2 -0
  31. ccxt/coinbaseinternational.py +2 -0
  32. ccxt/coinex.py +2 -0
  33. ccxt/delta.py +2 -0
  34. ccxt/deribit.py +2 -0
  35. ccxt/digifinex.py +2 -0
  36. ccxt/gate.py +2 -0
  37. ccxt/htx.py +2 -2
  38. ccxt/krakenfutures.py +2 -0
  39. ccxt/kucoinfutures.py +2 -0
  40. ccxt/okx.py +36 -0
  41. ccxt/oxfun.py +1 -0
  42. ccxt/paradex.py +1 -0
  43. ccxt/poloniex.py +1 -0
  44. ccxt/pro/__init__.py +1 -1
  45. ccxt/pro/binance.py +72 -5
  46. ccxt/pro/bitfinex.py +8 -8
  47. ccxt/pro/krakenfutures.py +2 -0
  48. ccxt/pro/phemex.py +2 -0
  49. ccxt/pro/woo.py +69 -0
  50. ccxt/test/tests_async.py +31 -3
  51. ccxt/test/tests_helpers.py +13 -36
  52. ccxt/test/tests_init.py +6 -2
  53. ccxt/test/tests_sync.py +31 -3
  54. {ccxt-4.4.12.dist-info → ccxt-4.4.13.dist-info}/METADATA +4 -5
  55. {ccxt-4.4.12.dist-info → ccxt-4.4.13.dist-info}/RECORD +58 -58
  56. {ccxt-4.4.12.dist-info → ccxt-4.4.13.dist-info}/LICENSE.txt +0 -0
  57. {ccxt-4.4.12.dist-info → ccxt-4.4.13.dist-info}/WHEEL +0 -0
  58. {ccxt-4.4.12.dist-info → ccxt-4.4.13.dist-info}/top_level.txt +0 -0
ccxt/bingx.py CHANGED
@@ -80,6 +80,7 @@ class bingx(Exchange, ImplicitAPI):
80
80
  'fetchMarginMode': True,
81
81
  'fetchMarkets': True,
82
82
  'fetchMarkOHLCV': True,
83
+ 'fetchMarkPrices': True,
83
84
  'fetchMyLiquidations': True,
84
85
  'fetchOHLCV': True,
85
86
  'fetchOpenInterest': True,
@@ -590,8 +591,8 @@ class bingx(Exchange, ImplicitAPI):
590
591
  networkList = self.safe_list(entry, 'networkList')
591
592
  networks: dict = {}
592
593
  fee = None
593
- depositEnabled = None
594
- withdrawEnabled = None
594
+ depositEnabled = False
595
+ withdrawEnabled = False
595
596
  defaultLimits: dict = {}
596
597
  for j in range(0, len(networkList)):
597
598
  rawNetwork = networkList[j]
@@ -602,7 +603,7 @@ class bingx(Exchange, ImplicitAPI):
602
603
  if networkDepositEnabled:
603
604
  depositEnabled = True
604
605
  networkWithdrawEnabled = self.safe_bool(rawNetwork, 'withdrawEnable')
605
- if networkDepositEnabled:
606
+ if networkWithdrawEnabled:
606
607
  withdrawEnabled = True
607
608
  limits: dict = {
608
609
  'withdraw': {
@@ -1654,7 +1655,70 @@ class bingx(Exchange, ImplicitAPI):
1654
1655
  tickers = self.safe_list(response, 'data')
1655
1656
  return self.parse_tickers(tickers, symbols)
1656
1657
 
1658
+ def fetch_mark_prices(self, symbols: Strings = None, params={}) -> Tickers:
1659
+ """
1660
+ fetches mark prices for multiple markets
1661
+ :see: https://bingx-api.github.io/docs/#/en-us/swapV2/market-api.html#Mark%20Price%20and%20Funding%20Rate
1662
+ :param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1663
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1664
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1665
+ """
1666
+ self.load_markets()
1667
+ market = None
1668
+ if symbols is not None:
1669
+ symbols = self.market_symbols(symbols)
1670
+ firstSymbol = self.safe_string(symbols, 0)
1671
+ if firstSymbol is not None:
1672
+ market = self.market(firstSymbol)
1673
+ subType = None
1674
+ subType, params = self.handle_sub_type_and_params('fetchMarkPrices', market, params, 'linear')
1675
+ response = None
1676
+ if subType == 'inverse':
1677
+ response = self.cswapV1PublicGetMarketPremiumIndex(params)
1678
+ else:
1679
+ response = self.swapV2PublicGetQuotePremiumIndex(params)
1680
+ #
1681
+ # spot and swap
1682
+ #
1683
+ # {
1684
+ # "code": 0,
1685
+ # "msg": "",
1686
+ # "timestamp": 1720647285296,
1687
+ # "data": [
1688
+ # {
1689
+ # "symbol": "SOL-USD",
1690
+ # "priceChange": "-2.418",
1691
+ # "priceChangePercent": "-1.6900%",
1692
+ # "lastPrice": "140.574",
1693
+ # "lastQty": "1",
1694
+ # "highPrice": "146.190",
1695
+ # "lowPrice": "138.586",
1696
+ # "volume": "1464648.00",
1697
+ # "quoteVolume": "102928.12",
1698
+ # "openPrice": "142.994",
1699
+ # "closeTime": "1720647284976",
1700
+ # "bidPrice": "140.573",
1701
+ # "bidQty": "372",
1702
+ # "askPrice": "140.577",
1703
+ # "askQty": "58"
1704
+ # },
1705
+ # ...
1706
+ # ]
1707
+ # }
1708
+ #
1709
+ tickers = self.safe_list(response, 'data')
1710
+ return self.parse_tickers(tickers, symbols)
1711
+
1657
1712
  def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1713
+ #
1714
+ # mark price
1715
+ # {
1716
+ # "symbol": "string",
1717
+ # "lastFundingRate": "string",
1718
+ # "markPrice": "string",
1719
+ # "indexPrice": "string",
1720
+ # "nextFundingTime": "int64"
1721
+ # }
1658
1722
  #
1659
1723
  # spot
1660
1724
  # {
@@ -1740,6 +1804,8 @@ class bingx(Exchange, ImplicitAPI):
1740
1804
  'average': None,
1741
1805
  'baseVolume': baseVolume,
1742
1806
  'quoteVolume': quoteVolume,
1807
+ 'markPrice': self.safe_string(ticker, 'markPrice'),
1808
+ 'indexPrice': self.safe_string(ticker, 'indexPrice'),
1743
1809
  'info': ticker,
1744
1810
  }, market)
1745
1811
 
ccxt/bitget.py CHANGED
@@ -2569,6 +2569,7 @@ class bitget(Exchange, ImplicitAPI):
2569
2569
  'average': None,
2570
2570
  'baseVolume': self.safe_string(ticker, 'baseVolume'),
2571
2571
  'quoteVolume': self.safe_string(ticker, 'quoteVolume'),
2572
+ 'indexPrice': self.safe_string(ticker, 'indexPrice'),
2572
2573
  'info': ticker,
2573
2574
  }, market)
2574
2575
 
ccxt/bitmex.py CHANGED
@@ -1370,6 +1370,7 @@ class bitmex(Exchange, ImplicitAPI):
1370
1370
  'average': None,
1371
1371
  'baseVolume': self.safe_string(ticker, 'homeNotional24h'),
1372
1372
  'quoteVolume': self.safe_string(ticker, 'foreignNotional24h'),
1373
+ 'markPrice': self.safe_string(ticker, 'markPrice'),
1373
1374
  'info': ticker,
1374
1375
  }, market)
1375
1376
 
ccxt/bybit.py CHANGED
@@ -2053,6 +2053,8 @@ class bybit(Exchange, ImplicitAPI):
2053
2053
  'average': None,
2054
2054
  'baseVolume': baseVolume,
2055
2055
  'quoteVolume': quoteVolume,
2056
+ 'markPrice': self.safe_string(ticker, 'markPrice'),
2057
+ 'indexPrice': self.safe_string(ticker, 'indexPrice'),
2056
2058
  'info': ticker,
2057
2059
  }, market)
2058
2060
 
@@ -1426,6 +1426,8 @@ class coinbaseinternational(Exchange, ImplicitAPI):
1426
1426
  'baseVolume': None,
1427
1427
  'quoteVolume': None,
1428
1428
  'previousClose': None,
1429
+ 'markPrice': self.safe_number(ticker, 'mark_price'),
1430
+ 'indexPrice': self.safe_number(ticker, 'index_price'),
1429
1431
  })
1430
1432
 
1431
1433
  def fetch_balance(self, params={}) -> Balances:
ccxt/coinex.py CHANGED
@@ -921,6 +921,8 @@ class coinex(Exchange, ImplicitAPI):
921
921
  'average': None,
922
922
  'baseVolume': self.safe_string(ticker, 'volume'),
923
923
  'quoteVolume': None,
924
+ 'markPrice': self.safe_string(ticker, 'mark_price'),
925
+ 'indexPrice': self.safe_string(ticker, 'index_price'),
924
926
  'info': ticker,
925
927
  }, market)
926
928
 
ccxt/delta.py CHANGED
@@ -946,6 +946,8 @@ class delta(Exchange, ImplicitAPI):
946
946
  'average': None,
947
947
  'baseVolume': self.safe_number(ticker, 'volume'),
948
948
  'quoteVolume': self.safe_number(ticker, 'turnover'),
949
+ 'markPrice': self.safe_number(ticker, 'mark_price'),
950
+ 'indexPrice': self.safe_number(ticker, 'spot_price'),
949
951
  'info': ticker,
950
952
  }, market)
951
953
 
ccxt/deribit.py CHANGED
@@ -1133,6 +1133,8 @@ class deribit(Exchange, ImplicitAPI):
1133
1133
  'average': None,
1134
1134
  'baseVolume': None,
1135
1135
  'quoteVolume': self.safe_string(stats, 'volume'),
1136
+ 'markPrice': self.safe_string(ticker, 'mark_price'),
1137
+ 'indexPrice': self.safe_string(ticker, 'index_price'),
1136
1138
  'info': ticker,
1137
1139
  }, market)
1138
1140
 
ccxt/digifinex.py CHANGED
@@ -1163,6 +1163,8 @@ class digifinex(Exchange, ImplicitAPI):
1163
1163
  'average': None,
1164
1164
  'baseVolume': self.safe_string_2(ticker, 'vol', 'volume_24h'),
1165
1165
  'quoteVolume': self.safe_string(ticker, 'base_vol'),
1166
+ 'markPrice': self.safe_string(ticker, 'mark_price'),
1167
+ 'indexPrice': indexPrice,
1166
1168
  'info': ticker,
1167
1169
  }, market)
1168
1170
 
ccxt/gate.py CHANGED
@@ -2514,6 +2514,8 @@ class gate(Exchange, ImplicitAPI):
2514
2514
  'average': None,
2515
2515
  'baseVolume': baseVolume,
2516
2516
  'quoteVolume': quoteVolume,
2517
+ 'markPrice': self.safe_string(ticker, 'mark_price'),
2518
+ 'indexPrice': self.safe_string(ticker, 'index_price'),
2517
2519
  'info': ticker,
2518
2520
  }, market)
2519
2521
 
ccxt/htx.py CHANGED
@@ -4087,7 +4087,7 @@ class htx(Exchange, ImplicitAPI):
4087
4087
  self.load_accounts()
4088
4088
  for i in range(0, len(self.accounts)):
4089
4089
  account = self.accounts[i]
4090
- if account['type'] == 'spot':
4090
+ if self.safe_string(account, 'type') == 'spot':
4091
4091
  accountId = self.safe_string(account, 'id')
4092
4092
  if accountId is not None:
4093
4093
  break
@@ -4742,7 +4742,7 @@ class htx(Exchange, ImplicitAPI):
4742
4742
  cost = self.safe_string(order, 'amount')
4743
4743
  else:
4744
4744
  amount = self.safe_string_2(order, 'volume', 'amount')
4745
- cost = self.safe_string_n(order, ['filled-cash-amount', 'field-cash-amount', 'trade_turnover']) # same typo
4745
+ cost = self.safe_string_n(order, ['filled-cash-amount', 'field-cash-amount', 'trade_turnover']) # same typo here
4746
4746
  filled = self.safe_string_n(order, ['filled-amount', 'field-amount', 'trade_volume']) # typo in their API, filled amount
4747
4747
  price = self.safe_string_2(order, 'price', 'order_price')
4748
4748
  feeCost = self.safe_string_2(order, 'filled-fees', 'field-fees') # typo in their API, filled feeSide
ccxt/krakenfutures.py CHANGED
@@ -611,6 +611,8 @@ class krakenfutures(Exchange, ImplicitAPI):
611
611
  'average': average,
612
612
  'baseVolume': baseVolume,
613
613
  'quoteVolume': quoteVolume,
614
+ 'markPrice': self.safe_string(ticker, 'markPrice'),
615
+ 'indexPrice': self.safe_string(ticker, 'indexPrice'),
614
616
  'info': ticker,
615
617
  })
616
618
 
ccxt/kucoinfutures.py CHANGED
@@ -944,6 +944,8 @@ class kucoinfutures(kucoin, ImplicitAPI):
944
944
  'average': None,
945
945
  'baseVolume': self.safe_string(ticker, 'volumeOf24h'),
946
946
  'quoteVolume': self.safe_string(ticker, 'turnoverOf24h'),
947
+ 'markPrice': self.safe_string(ticker, 'markPrice'),
948
+ 'indexPrice': self.safe_string(ticker, 'indexPrice'),
947
949
  'info': ticker,
948
950
  }, market)
949
951
 
ccxt/okx.py CHANGED
@@ -120,6 +120,7 @@ class okx(Exchange, ImplicitAPI):
120
120
  'fetchMarketLeverageTiers': True,
121
121
  'fetchMarkets': True,
122
122
  'fetchMarkOHLCV': True,
123
+ 'fetchMarkPrices': True,
123
124
  'fetchMySettlementHistory': False,
124
125
  'fetchMyTrades': True,
125
126
  'fetchOHLCV': True,
@@ -1784,6 +1785,13 @@ class okx(Exchange, ImplicitAPI):
1784
1785
  return self.parse_order_book(first, symbol, timestamp)
1785
1786
 
1786
1787
  def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1788
+ #
1789
+ # {
1790
+ # "instType":"SWAP",
1791
+ # "instId":"BTC-USDT-SWAP",
1792
+ # "markPx":"200",
1793
+ # "ts":"1597026383085"
1794
+ # }
1787
1795
  #
1788
1796
  # {
1789
1797
  # "instType": "SPOT",
@@ -1835,6 +1843,7 @@ class okx(Exchange, ImplicitAPI):
1835
1843
  'average': None,
1836
1844
  'baseVolume': baseVolume,
1837
1845
  'quoteVolume': quoteVolume,
1846
+ 'markPrice': self.safe_string(ticker, 'markPx'),
1838
1847
  'info': ticker,
1839
1848
  }, market)
1840
1849
 
@@ -1935,6 +1944,33 @@ class okx(Exchange, ImplicitAPI):
1935
1944
  tickers = self.safe_list(response, 'data', [])
1936
1945
  return self.parse_tickers(tickers, symbols)
1937
1946
 
1947
+ def fetch_mark_prices(self, symbols: Strings = None, params={}) -> Tickers:
1948
+ """
1949
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1950
+ :see: https://www.okx.com/docs-v5/en/#public-data-rest-api-get-mark-price
1951
+ :param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1952
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1953
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1954
+ """
1955
+ self.load_markets()
1956
+ symbols = self.market_symbols(symbols)
1957
+ market = self.get_market_from_symbols(symbols)
1958
+ marketType = None
1959
+ marketType, params = self.handle_market_type_and_params('fetchTickers', market, params, 'swap')
1960
+ request: dict = {
1961
+ 'instType': self.convert_to_instrument_type(marketType),
1962
+ }
1963
+ if marketType == 'option':
1964
+ defaultUnderlying = self.safe_string(self.options, 'defaultUnderlying', 'BTC-USD')
1965
+ currencyId = self.safe_string_2(params, 'uly', 'marketId', defaultUnderlying)
1966
+ if currencyId is None:
1967
+ raise ArgumentsRequired(self.id + ' fetchTickers() requires an underlying uly or marketId parameter for options markets')
1968
+ else:
1969
+ request['uly'] = currencyId
1970
+ response = self.publicGetPublicMarkPrice(self.extend(request, params))
1971
+ tickers = self.safe_list(response, 'data', [])
1972
+ return self.parse_tickers(tickers, symbols)
1973
+
1938
1974
  def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1939
1975
  #
1940
1976
  # public fetchTrades
ccxt/oxfun.py CHANGED
@@ -858,6 +858,7 @@ class oxfun(Exchange, ImplicitAPI):
858
858
  'average': None,
859
859
  'baseVolume': self.safe_string(ticker, 'currencyVolume24h'),
860
860
  'quoteVolume': None, # the exchange returns cost in OX
861
+ 'markPrice': self.safe_string(ticker, 'markPrice'),
861
862
  'info': ticker,
862
863
  }, market)
863
864
 
ccxt/paradex.py CHANGED
@@ -652,6 +652,7 @@ class paradex(Exchange, ImplicitAPI):
652
652
  'average': None,
653
653
  'baseVolume': None,
654
654
  'quoteVolume': self.safe_string(ticker, 'volume_24h'),
655
+ 'markPrice': self.safe_string(ticker, 'mark_price'),
655
656
  'info': ticker,
656
657
  }, market)
657
658
 
ccxt/poloniex.py CHANGED
@@ -633,6 +633,7 @@ class poloniex(Exchange, ImplicitAPI):
633
633
  'average': None,
634
634
  'baseVolume': self.safe_string(ticker, 'quantity'),
635
635
  'quoteVolume': self.safe_string(ticker, 'amount'),
636
+ 'markPrice': self.safe_string(ticker, 'markPrice'),
636
637
  'info': ticker,
637
638
  }, market)
638
639
 
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.12'
7
+ __version__ = '4.4.13'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -43,6 +43,8 @@ class binance(ccxt.async_support.binance):
43
43
  'watchPositions': True,
44
44
  'watchTicker': True,
45
45
  'watchTickers': True,
46
+ 'watchMarkPrices': True,
47
+ 'watchMarkPrice': True,
46
48
  'watchTrades': True,
47
49
  'watchTradesForSymbols': True,
48
50
  'createOrderWs': True,
@@ -159,6 +161,7 @@ class binance(ccxt.async_support.binance):
159
161
  'tickerChannelsMap': {
160
162
  '24hrTicker': 'ticker',
161
163
  '24hrMiniTicker': 'miniTicker',
164
+ 'markPriceUpdate': 'markPrice',
162
165
  # rolling window tickers
163
166
  '1hTicker': 'ticker_1h',
164
167
  '4hTicker': 'ticker_4h',
@@ -1641,6 +1644,39 @@ class binance(ccxt.async_support.binance):
1641
1644
  tickers = await self.watch_tickers([symbol], self.extend(params, {'callerMethodName': 'watchTicker'}))
1642
1645
  return tickers[symbol]
1643
1646
 
1647
+ async def watch_mark_price(self, symbol: str, params={}) -> Ticker:
1648
+ """
1649
+ :see: https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream
1650
+ watches a mark price for a specific market
1651
+ :param str symbol: unified symbol of the market to fetch the ticker for
1652
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1653
+ :param boolean [params.use1sFreq]: *default is True* if set to True, the mark price will be updated every second, otherwise every 3 seconds
1654
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1655
+ """
1656
+ await self.load_markets()
1657
+ symbol = self.symbol(symbol)
1658
+ tickers = await self.watch_mark_prices([symbol], self.extend(params, {'callerMethodName': 'watchMarkPrice'}))
1659
+ return tickers[symbol]
1660
+
1661
+ async def watch_mark_prices(self, symbols: Strings = None, params={}) -> Tickers:
1662
+ """
1663
+ :see: https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream-for-All-market
1664
+ watches the mark price for all markets
1665
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
1666
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1667
+ :param boolean [params.use1sFreq]: *default is True* if set to True, the mark price will be updated every second, otherwise every 3 seconds
1668
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1669
+ """
1670
+ channelName = None
1671
+ # for now watchmarkPrice uses the same messageHash
1672
+ # so it's impossible to watch both at the same time
1673
+ # refactor self to use different messageHashes
1674
+ channelName, params = self.handle_option_and_params(params, 'watchMarkPrices', 'name', 'markPrice')
1675
+ newTickers = await self.watch_multi_ticker_helper('watchMarkPrices', channelName, symbols, params)
1676
+ if self.newUpdates:
1677
+ return newTickers
1678
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
1679
+
1644
1680
  async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1645
1681
  """
1646
1682
  :see: https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-mini-ticker-stream
@@ -1775,12 +1811,16 @@ class binance(ccxt.async_support.binance):
1775
1811
  async def watch_multi_ticker_helper(self, methodName, channelName: str, symbols: Strings = None, params={}):
1776
1812
  await self.load_markets()
1777
1813
  symbols = self.market_symbols(symbols, None, True, False, True)
1814
+ isBidAsk = (channelName == 'bookTicker')
1815
+ isMarkPrice = (channelName == 'markPrice')
1816
+ use1sFreq = self.safe_bool(params, 'use1sFreq', True)
1778
1817
  firstMarket = None
1779
1818
  marketType = None
1780
1819
  symbolsDefined = (symbols is not None)
1781
1820
  if symbolsDefined:
1782
1821
  firstMarket = self.market(symbols[0])
1783
- marketType, params = self.handle_market_type_and_params(methodName, firstMarket, params)
1822
+ defaultMarket = 'swap' if (isMarkPrice) else 'spot'
1823
+ marketType, params = self.handle_market_type_and_params(methodName, firstMarket, params, defaultMarket)
1784
1824
  subType = None
1785
1825
  subType, params = self.handle_sub_type_and_params(methodName, firstMarket, params)
1786
1826
  rawMarketType = None
@@ -1792,20 +1832,24 @@ class binance(ccxt.async_support.binance):
1792
1832
  rawMarketType = marketType
1793
1833
  else:
1794
1834
  raise NotSupported(self.id + ' ' + methodName + '() does not support options markets')
1795
- isBidAsk = (channelName == 'bookTicker')
1796
1835
  subscriptionArgs = []
1797
1836
  messageHashes = []
1837
+ suffix = ''
1838
+ if isMarkPrice:
1839
+ suffix = '@1s' if (use1sFreq) else ''
1798
1840
  if symbolsDefined:
1799
1841
  for i in range(0, len(symbols)):
1800
1842
  symbol = symbols[i]
1801
1843
  market = self.market(symbol)
1802
- subscriptionArgs.append(market['lowercaseId'] + '@' + channelName)
1844
+ subscriptionArgs.append(market['lowercaseId'] + '@' + channelName + suffix)
1803
1845
  messageHashes.append(self.get_message_hash(channelName, market['symbol'], isBidAsk))
1804
1846
  else:
1805
1847
  if isBidAsk:
1806
1848
  if marketType == 'spot':
1807
1849
  raise ArgumentsRequired(self.id + ' ' + methodName + '() requires symbols for self channel for spot markets')
1808
1850
  subscriptionArgs.append('!' + channelName)
1851
+ elif isMarkPrice:
1852
+ subscriptionArgs.append('!' + channelName + '@arr' + suffix)
1809
1853
  else:
1810
1854
  subscriptionArgs.append('!' + channelName + '@arr')
1811
1855
  messageHashes.append(self.get_message_hash(channelName, None, isBidAsk))
@@ -1833,6 +1877,17 @@ class binance(ccxt.async_support.binance):
1833
1877
  return newDict
1834
1878
 
1835
1879
  def parse_ws_ticker(self, message, marketType):
1880
+ # markPrice
1881
+ # {
1882
+ # "e": "markPriceUpdate", # Event type
1883
+ # "E": 1562305380000, # Event time
1884
+ # "s": "BTCUSDT", # Symbol
1885
+ # "p": "11794.15000000", # Mark price
1886
+ # "i": "11784.62659091", # Index price
1887
+ # "P": "11784.25641265", # Estimated Settle Price, only useful in the last hour before the settlement starts
1888
+ # "r": "0.00038167", # Funding rate
1889
+ # "T": 1562306400000 # Next funding time
1890
+ # }
1836
1891
  #
1837
1892
  # ticker
1838
1893
  # {
@@ -1890,9 +1945,21 @@ class binance(ccxt.async_support.binance):
1890
1945
  # "time":1589437530011,
1891
1946
  # }
1892
1947
  #
1948
+ marketId = self.safe_string_2(message, 's', 'symbol')
1949
+ symbol = self.safe_symbol(marketId, None, None, marketType)
1893
1950
  event = self.safe_string(message, 'e', 'bookTicker')
1894
1951
  if event == '24hrTicker':
1895
1952
  event = 'ticker'
1953
+ if event == 'markPriceUpdate':
1954
+ # handle self separately because some fields clash with the ticker fields
1955
+ return self.safe_ticker({
1956
+ 'symbol': symbol,
1957
+ 'timestamp': self.safe_integer(message, 'E'),
1958
+ 'datetime': self.iso8601(self.safe_integer(message, 'E')),
1959
+ 'info': message,
1960
+ 'markPrice': self.safe_string(message, 'p'),
1961
+ 'indexPrice': self.safe_string(message, 'i'),
1962
+ })
1896
1963
  timestamp = None
1897
1964
  if event == 'bookTicker':
1898
1965
  # take the event timestamp, if available, for spot tickers it is not
@@ -1900,8 +1967,6 @@ class binance(ccxt.async_support.binance):
1900
1967
  else:
1901
1968
  # take the timestamp of the closing price for candlestick streams
1902
1969
  timestamp = self.safe_integer_n(message, ['C', 'E', 'time'])
1903
- marketId = self.safe_string_2(message, 's', 'symbol')
1904
- symbol = self.safe_symbol(marketId, None, None, marketType)
1905
1970
  market = self.safe_market(marketId, None, None, marketType)
1906
1971
  last = self.safe_string_2(message, 'c', 'price')
1907
1972
  return self.safe_ticker({
@@ -3864,6 +3929,8 @@ class binance(ccxt.async_support.binance):
3864
3929
  '1dTicker': self.handle_tickers,
3865
3930
  '24hrTicker': self.handle_tickers,
3866
3931
  '24hrMiniTicker': self.handle_tickers,
3932
+ 'markPriceUpdate': self.handle_tickers,
3933
+ 'markPriceUpdate@arr': self.handle_tickers,
3867
3934
  'bookTicker': self.handle_bids_asks, # there is no "bookTicker@arr" endpoint
3868
3935
  'outboundAccountPosition': self.handle_balance,
3869
3936
  'balanceUpdate': self.handle_balance,
ccxt/pro/bitfinex.py CHANGED
@@ -213,15 +213,15 @@ class bitfinex(ccxt.async_support.bitfinex):
213
213
  open = None
214
214
  if (last is not None) and (change is not None):
215
215
  open = Precise.string_sub(last, change)
216
- result = {
216
+ result = self.safe_ticker({
217
217
  'symbol': symbol,
218
218
  'timestamp': None,
219
219
  'datetime': None,
220
- 'high': self.safe_float(message, 9),
221
- 'low': self.safe_float(message, 10),
222
- 'bid': self.safe_float(message, 1),
220
+ 'high': self.safe_string(message, 9),
221
+ 'low': self.safe_string(message, 10),
222
+ 'bid': self.safe_string(message, 1),
223
223
  'bidVolume': None,
224
- 'ask': self.safe_float(message, 3),
224
+ 'ask': self.safe_string(message, 3),
225
225
  'askVolume': None,
226
226
  'vwap': None,
227
227
  'open': self.parse_number(open),
@@ -229,12 +229,12 @@ class bitfinex(ccxt.async_support.bitfinex):
229
229
  'last': self.parse_number(last),
230
230
  'previousClose': None,
231
231
  'change': self.parse_number(change),
232
- 'percentage': self.safe_float(message, 6),
232
+ 'percentage': self.safe_string(message, 6),
233
233
  'average': None,
234
- 'baseVolume': self.safe_float(message, 8),
234
+ 'baseVolume': self.safe_string(message, 8),
235
235
  'quoteVolume': None,
236
236
  'info': message,
237
- }
237
+ })
238
238
  self.tickers[symbol] = result
239
239
  client.resolve(result, messageHash)
240
240
 
ccxt/pro/krakenfutures.py CHANGED
@@ -998,6 +998,8 @@ class krakenfutures(ccxt.async_support.krakenfutures):
998
998
  'average': None,
999
999
  'baseVolume': self.safe_string(ticker, 'volume'),
1000
1000
  'quoteVolume': self.safe_string(ticker, 'volumeQuote'),
1001
+ 'markPrice': self.safe_string(ticker, 'markPrice'),
1002
+ 'indexPrice': self.safe_string(ticker, 'index'),
1001
1003
  })
1002
1004
 
1003
1005
  def handle_order_book_snapshot(self, client: Client, message):
ccxt/pro/phemex.py CHANGED
@@ -132,6 +132,8 @@ class phemex(ccxt.async_support.phemex):
132
132
  'average': average,
133
133
  'baseVolume': baseVolume,
134
134
  'quoteVolume': quoteVolume,
135
+ 'markPrice': self.parse_number(self.from_ep(self.safe_string(ticker, 'markPrice'), market)),
136
+ 'indexPrice': self.parse_number(self.from_ep(self.safe_string(ticker, 'indexPrice'), market)),
135
137
  'info': ticker,
136
138
  }
137
139
  return result
ccxt/pro/woo.py CHANGED
@@ -27,6 +27,7 @@ class woo(ccxt.async_support.woo):
27
27
  'watchOrders': True,
28
28
  'watchTicker': True,
29
29
  'watchTickers': True,
30
+ 'watchBidsAsks': True,
30
31
  'watchTrades': True,
31
32
  'watchTradesForSymbols': False,
32
33
  'watchPositions': True,
@@ -383,6 +384,73 @@ class woo(ccxt.async_support.woo):
383
384
  result.append(ticker)
384
385
  client.resolve(result, topic)
385
386
 
387
+ async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
388
+ """
389
+ :see: https://docs.woox.io/#bbos
390
+ watches best bid & ask for symbols
391
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
392
+ :param dict [params]: extra parameters specific to the exchange API endpoint
393
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
394
+ """
395
+ await self.load_markets()
396
+ symbols = self.market_symbols(symbols, None, False)
397
+ name = 'bbos'
398
+ topic = name
399
+ request: dict = {
400
+ 'event': 'subscribe',
401
+ 'topic': topic,
402
+ }
403
+ message = self.extend(request, params)
404
+ tickers = await self.watch_public(topic, message)
405
+ if self.newUpdates:
406
+ return tickers
407
+ return self.filter_by_array(self.bidsasks, 'symbol', symbols)
408
+
409
+ def handle_bid_ask(self, client: Client, message):
410
+ #
411
+ # {
412
+ # "topic": "bbos",
413
+ # "ts": 1618822376000,
414
+ # "data": [
415
+ # {
416
+ # "symbol": "SPOT_FIL_USDT",
417
+ # "ask": 159.0318,
418
+ # "askSize": 370.43,
419
+ # "bid": 158.9158,
420
+ # "bidSize": 16
421
+ # }
422
+ # ]
423
+ # }
424
+ #
425
+ topic = self.safe_string(message, 'topic')
426
+ data = self.safe_list(message, 'data', [])
427
+ timestamp = self.safe_integer(message, 'ts')
428
+ result: dict = {}
429
+ for i in range(0, len(data)):
430
+ ticker = self.safe_dict(data, i)
431
+ ticker['ts'] = timestamp
432
+ parsedTicker = self.parse_ws_bid_ask(ticker)
433
+ symbol = parsedTicker['symbol']
434
+ self.bidsasks[symbol] = parsedTicker
435
+ result[symbol] = parsedTicker
436
+ client.resolve(result, topic)
437
+
438
+ def parse_ws_bid_ask(self, ticker, market=None):
439
+ marketId = self.safe_string(ticker, 'symbol')
440
+ market = self.safe_market(marketId, market)
441
+ symbol = self.safe_string(market, 'symbol')
442
+ timestamp = self.safe_integer(ticker, 'ts')
443
+ return self.safe_ticker({
444
+ 'symbol': symbol,
445
+ 'timestamp': timestamp,
446
+ 'datetime': self.iso8601(timestamp),
447
+ 'ask': self.safe_string(ticker, 'ask'),
448
+ 'askVolume': self.safe_string(ticker, 'askSize'),
449
+ 'bid': self.safe_string(ticker, 'bid'),
450
+ 'bidVolume': self.safe_string(ticker, 'bidSize'),
451
+ 'info': ticker,
452
+ }, market)
453
+
386
454
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
387
455
  """
388
456
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
@@ -1101,6 +1169,7 @@ class woo(ccxt.async_support.woo):
1101
1169
  'trade': self.handle_trade,
1102
1170
  'balance': self.handle_balance,
1103
1171
  'position': self.handle_positions,
1172
+ 'bbos': self.handle_bid_ask,
1104
1173
  }
1105
1174
  event = self.safe_string(message, 'event')
1106
1175
  method = self.safe_value(methods, event)