ccxt 4.2.93__py2.py3-none-any.whl → 4.2.95__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 (190) hide show
  1. ccxt/__init__.py +2 -2
  2. ccxt/abstract/binance.py +1 -0
  3. ccxt/abstract/binancecoinm.py +1 -0
  4. ccxt/abstract/binanceus.py +1 -0
  5. ccxt/abstract/binanceusdm.py +1 -0
  6. ccxt/abstract/bitstamp.py +6 -0
  7. ccxt/ace.py +1 -1
  8. ccxt/ascendex.py +1 -1
  9. ccxt/async_support/__init__.py +2 -2
  10. ccxt/async_support/ace.py +1 -1
  11. ccxt/async_support/ascendex.py +1 -1
  12. ccxt/async_support/base/exchange.py +7 -1
  13. ccxt/async_support/bigone.py +1 -1
  14. ccxt/async_support/binance.py +63 -5
  15. ccxt/async_support/bingx.py +1 -1
  16. ccxt/async_support/bit2c.py +1 -1
  17. ccxt/async_support/bitbank.py +1 -1
  18. ccxt/async_support/bitfinex.py +1 -1
  19. ccxt/async_support/bitfinex2.py +1 -1
  20. ccxt/async_support/bitget.py +136 -2
  21. ccxt/async_support/bithumb.py +1 -1
  22. ccxt/async_support/bitmart.py +1 -1
  23. ccxt/async_support/bitmex.py +1 -1
  24. ccxt/async_support/bitopro.py +1 -1
  25. ccxt/async_support/bitrue.py +1 -1
  26. ccxt/async_support/bitso.py +1 -1
  27. ccxt/async_support/bitstamp.py +7 -1
  28. ccxt/async_support/bitteam.py +1 -1
  29. ccxt/async_support/bitvavo.py +1 -1
  30. ccxt/async_support/blockchaincom.py +1 -1
  31. ccxt/async_support/blofin.py +1 -1
  32. ccxt/async_support/btcalpha.py +1 -1
  33. ccxt/async_support/btcbox.py +1 -1
  34. ccxt/async_support/bybit.py +2 -2
  35. ccxt/async_support/cex.py +1 -1
  36. ccxt/async_support/coinbase.py +1 -1
  37. ccxt/async_support/coinbaseinternational.py +1 -1
  38. ccxt/async_support/coinbasepro.py +1 -1
  39. ccxt/async_support/coincheck.py +1 -1
  40. ccxt/async_support/coinex.py +62 -56
  41. ccxt/async_support/coinlist.py +1 -1
  42. ccxt/async_support/coinmate.py +1 -1
  43. ccxt/async_support/coinsph.py +1 -1
  44. ccxt/async_support/cryptocom.py +1 -1
  45. ccxt/async_support/currencycom.py +1 -1
  46. ccxt/async_support/delta.py +1 -1
  47. ccxt/async_support/deribit.py +1 -1
  48. ccxt/async_support/digifinex.py +1 -1
  49. ccxt/async_support/exmo.py +1 -1
  50. ccxt/async_support/gate.py +1 -1
  51. ccxt/async_support/gemini.py +3 -2
  52. ccxt/async_support/hitbtc.py +1 -1
  53. ccxt/async_support/hollaex.py +1 -1
  54. ccxt/async_support/htx.py +117 -116
  55. ccxt/async_support/huobijp.py +1 -1
  56. ccxt/async_support/idex.py +1 -1
  57. ccxt/async_support/indodax.py +1 -1
  58. ccxt/async_support/kraken.py +1 -1
  59. ccxt/async_support/krakenfutures.py +2 -2
  60. ccxt/async_support/kucoin.py +1 -1
  61. ccxt/async_support/kucoinfutures.py +1 -1
  62. ccxt/async_support/latoken.py +1 -1
  63. ccxt/async_support/lbank.py +1 -1
  64. ccxt/async_support/mexc.py +1 -1
  65. ccxt/async_support/ndax.py +1 -1
  66. ccxt/async_support/novadax.py +1 -1
  67. ccxt/async_support/oceanex.py +1 -1
  68. ccxt/async_support/okcoin.py +1 -1
  69. ccxt/async_support/okx.py +191 -43
  70. ccxt/async_support/onetrading.py +1 -1
  71. ccxt/async_support/p2b.py +1 -1
  72. ccxt/async_support/phemex.py +1 -1
  73. ccxt/async_support/poloniex.py +1 -1
  74. ccxt/async_support/poloniexfutures.py +1 -1
  75. ccxt/async_support/probit.py +1 -1
  76. ccxt/async_support/timex.py +1 -1
  77. ccxt/async_support/tokocrypto.py +1 -1
  78. ccxt/async_support/tradeogre.py +1 -1
  79. ccxt/async_support/upbit.py +2 -2
  80. ccxt/async_support/wavesexchange.py +1 -1
  81. ccxt/async_support/whitebit.py +1 -1
  82. ccxt/async_support/woo.py +136 -2
  83. ccxt/async_support/yobit.py +1 -1
  84. ccxt/async_support/zonda.py +1 -1
  85. ccxt/base/errors.py +7 -7
  86. ccxt/base/exchange.py +18 -1
  87. ccxt/base/types.py +13 -0
  88. ccxt/bigone.py +1 -1
  89. ccxt/binance.py +63 -5
  90. ccxt/bingx.py +1 -1
  91. ccxt/bit2c.py +1 -1
  92. ccxt/bitbank.py +1 -1
  93. ccxt/bitfinex.py +1 -1
  94. ccxt/bitfinex2.py +1 -1
  95. ccxt/bitget.py +136 -2
  96. ccxt/bithumb.py +1 -1
  97. ccxt/bitmart.py +1 -1
  98. ccxt/bitmex.py +1 -1
  99. ccxt/bitopro.py +1 -1
  100. ccxt/bitrue.py +1 -1
  101. ccxt/bitso.py +1 -1
  102. ccxt/bitstamp.py +7 -1
  103. ccxt/bitteam.py +1 -1
  104. ccxt/bitvavo.py +1 -1
  105. ccxt/blockchaincom.py +1 -1
  106. ccxt/blofin.py +1 -1
  107. ccxt/btcalpha.py +1 -1
  108. ccxt/btcbox.py +1 -1
  109. ccxt/bybit.py +2 -2
  110. ccxt/cex.py +1 -1
  111. ccxt/coinbase.py +1 -1
  112. ccxt/coinbaseinternational.py +1 -1
  113. ccxt/coinbasepro.py +1 -1
  114. ccxt/coincheck.py +1 -1
  115. ccxt/coinex.py +62 -56
  116. ccxt/coinlist.py +1 -1
  117. ccxt/coinmate.py +1 -1
  118. ccxt/coinsph.py +1 -1
  119. ccxt/cryptocom.py +1 -1
  120. ccxt/currencycom.py +1 -1
  121. ccxt/delta.py +1 -1
  122. ccxt/deribit.py +1 -1
  123. ccxt/digifinex.py +1 -1
  124. ccxt/exmo.py +1 -1
  125. ccxt/gate.py +1 -1
  126. ccxt/gemini.py +3 -2
  127. ccxt/hitbtc.py +1 -1
  128. ccxt/hollaex.py +1 -1
  129. ccxt/htx.py +117 -116
  130. ccxt/huobijp.py +1 -1
  131. ccxt/idex.py +1 -1
  132. ccxt/indodax.py +1 -1
  133. ccxt/kraken.py +1 -1
  134. ccxt/krakenfutures.py +2 -2
  135. ccxt/kucoin.py +1 -1
  136. ccxt/kucoinfutures.py +1 -1
  137. ccxt/latoken.py +1 -1
  138. ccxt/lbank.py +1 -1
  139. ccxt/mexc.py +1 -1
  140. ccxt/ndax.py +1 -1
  141. ccxt/novadax.py +1 -1
  142. ccxt/oceanex.py +1 -1
  143. ccxt/okcoin.py +1 -1
  144. ccxt/okx.py +191 -43
  145. ccxt/onetrading.py +1 -1
  146. ccxt/p2b.py +1 -1
  147. ccxt/phemex.py +1 -1
  148. ccxt/poloniex.py +1 -1
  149. ccxt/poloniexfutures.py +1 -1
  150. ccxt/pro/__init__.py +1 -1
  151. ccxt/pro/ascendex.py +1 -1
  152. ccxt/pro/bitfinex2.py +1 -1
  153. ccxt/pro/bitget.py +1 -1
  154. ccxt/pro/bitmart.py +1 -1
  155. ccxt/pro/bitmex.py +1 -1
  156. ccxt/pro/bitstamp.py +1 -1
  157. ccxt/pro/bitvavo.py +1 -1
  158. ccxt/pro/blockchaincom.py +1 -1
  159. ccxt/pro/bybit.py +1 -1
  160. ccxt/pro/coinbase.py +12 -0
  161. ccxt/pro/coinbaseinternational.py +1 -1
  162. ccxt/pro/coinbasepro.py +1 -1
  163. ccxt/pro/coinex.py +1 -1
  164. ccxt/pro/cryptocom.py +1 -1
  165. ccxt/pro/gate.py +1 -1
  166. ccxt/pro/hitbtc.py +1 -1
  167. ccxt/pro/hollaex.py +1 -1
  168. ccxt/pro/htx.py +1 -1
  169. ccxt/pro/kraken.py +97 -19
  170. ccxt/pro/krakenfutures.py +105 -40
  171. ccxt/pro/kucoin.py +25 -16
  172. ccxt/pro/okcoin.py +1 -1
  173. ccxt/pro/okx.py +1 -1
  174. ccxt/pro/poloniex.py +1 -1
  175. ccxt/pro/poloniexfutures.py +1 -1
  176. ccxt/pro/whitebit.py +1 -1
  177. ccxt/probit.py +1 -1
  178. ccxt/timex.py +1 -1
  179. ccxt/tokocrypto.py +1 -1
  180. ccxt/tradeogre.py +1 -1
  181. ccxt/upbit.py +2 -2
  182. ccxt/wavesexchange.py +1 -1
  183. ccxt/whitebit.py +1 -1
  184. ccxt/woo.py +136 -2
  185. ccxt/yobit.py +1 -1
  186. ccxt/zonda.py +1 -1
  187. {ccxt-4.2.93.dist-info → ccxt-4.2.95.dist-info}/METADATA +4 -4
  188. {ccxt-4.2.93.dist-info → ccxt-4.2.95.dist-info}/RECORD +190 -190
  189. {ccxt-4.2.93.dist-info → ccxt-4.2.95.dist-info}/WHEEL +0 -0
  190. {ccxt-4.2.93.dist-info → ccxt-4.2.95.dist-info}/top_level.txt +0 -0
ccxt/pro/blockchaincom.py CHANGED
@@ -9,8 +9,8 @@ from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Ticker, Trade
9
9
  from ccxt.async_support.base.ws.client import Client
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
- from ccxt.base.errors import NotSupported
13
12
  from ccxt.base.errors import AuthenticationError
13
+ from ccxt.base.errors import NotSupported
14
14
 
15
15
 
16
16
  class blockchaincom(ccxt.async_support.blockchaincom):
ccxt/pro/bybit.py CHANGED
@@ -11,9 +11,9 @@ from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Stri
11
11
  from ccxt.async_support.base.ws.client import Client
12
12
  from typing import List
13
13
  from ccxt.base.errors import ExchangeError
14
+ from ccxt.base.errors import AuthenticationError
14
15
  from ccxt.base.errors import ArgumentsRequired
15
16
  from ccxt.base.errors import BadRequest
16
- from ccxt.base.errors import AuthenticationError
17
17
 
18
18
 
19
19
  class bybit(ccxt.async_support.bybit):
ccxt/pro/coinbase.py CHANGED
@@ -182,6 +182,8 @@ class coinbase(ccxt.async_support.coinbase):
182
182
  messageHash = channel + '::' + wsMarketId
183
183
  newTickers.append(result)
184
184
  client.resolve(result, messageHash)
185
+ if messageHash.endswith('USD'):
186
+ client.resolve(result, messageHash + 'C') # sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
185
187
  messageHashes = self.find_message_hashes(client, 'ticker_batch::')
186
188
  for i in range(0, len(messageHashes)):
187
189
  messageHash = messageHashes[i]
@@ -191,6 +193,8 @@ class coinbase(ccxt.async_support.coinbase):
191
193
  tickers = self.filter_by_array(newTickers, 'symbol', symbols)
192
194
  if not self.is_empty(tickers):
193
195
  client.resolve(tickers, messageHash)
196
+ if messageHash.endswith('USD'):
197
+ client.resolve(tickers, messageHash + 'C') # sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
194
198
  return message
195
199
 
196
200
  def parse_ws_ticker(self, ticker, market=None):
@@ -327,6 +331,8 @@ class coinbase(ccxt.async_support.coinbase):
327
331
  item = currentTrades[i]
328
332
  tradesArray.append(self.parse_trade(item))
329
333
  client.resolve(tradesArray, messageHash)
334
+ if marketId.endswith('USD'):
335
+ client.resolve(tradesArray, messageHash + 'C') # sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
330
336
  return message
331
337
 
332
338
  def handle_order(self, client, message):
@@ -378,6 +384,8 @@ class coinbase(ccxt.async_support.coinbase):
378
384
  marketId = marketIds[i]
379
385
  messageHash = 'user::' + marketId
380
386
  client.resolve(self.orders, messageHash)
387
+ if messageHash.endswith('USD'):
388
+ client.resolve(self.orders, messageHash + 'C') # sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
381
389
  client.resolve(self.orders, 'user')
382
390
  return message
383
391
 
@@ -488,6 +496,8 @@ class coinbase(ccxt.async_support.coinbase):
488
496
  orderbook['datetime'] = None
489
497
  orderbook['symbol'] = symbol
490
498
  client.resolve(orderbook, messageHash)
499
+ if messageHash.endswith('USD'):
500
+ client.resolve(orderbook, messageHash + 'C') # sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
491
501
  elif type == 'update':
492
502
  orderbook = self.orderbooks[symbol]
493
503
  self.handle_order_book_helper(orderbook, updates)
@@ -495,6 +505,8 @@ class coinbase(ccxt.async_support.coinbase):
495
505
  orderbook['timestamp'] = self.parse8601(datetime)
496
506
  orderbook['symbol'] = symbol
497
507
  client.resolve(orderbook, messageHash)
508
+ if messageHash.endswith('USD'):
509
+ client.resolve(orderbook, messageHash + 'C') # sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
498
510
  return message
499
511
 
500
512
  def handle_subscription_status(self, client, message):
@@ -10,8 +10,8 @@ from ccxt.base.types import Int, Market, OrderBook, Strings, Ticker, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
- from ccxt.base.errors import NotSupported
14
13
  from ccxt.base.errors import AuthenticationError
14
+ from ccxt.base.errors import NotSupported
15
15
 
16
16
 
17
17
  class coinbaseinternational(ccxt.async_support.coinbaseinternational):
ccxt/pro/coinbasepro.py CHANGED
@@ -10,10 +10,10 @@ from ccxt.base.types import Int, Order, OrderBook, Str, Strings, Ticker, Tickers
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
+ from ccxt.base.errors import AuthenticationError
13
14
  from ccxt.base.errors import ArgumentsRequired
14
15
  from ccxt.base.errors import BadRequest
15
16
  from ccxt.base.errors import BadSymbol
16
- from ccxt.base.errors import AuthenticationError
17
17
 
18
18
 
19
19
  class coinbasepro(ccxt.async_support.coinbasepro):
ccxt/pro/coinex.py CHANGED
@@ -9,11 +9,11 @@ from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Strings, Ticke
9
9
  from ccxt.async_support.base.ws.client import Client
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
12
13
  from ccxt.base.errors import BadRequest
13
14
  from ccxt.base.errors import NotSupported
14
15
  from ccxt.base.errors import ExchangeNotAvailable
15
16
  from ccxt.base.errors import RequestTimeout
16
- from ccxt.base.errors import AuthenticationError
17
17
  from ccxt.base.precise import Precise
18
18
 
19
19
 
ccxt/pro/cryptocom.py CHANGED
@@ -9,9 +9,9 @@ import hashlib
9
9
  from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
+ from ccxt.base.errors import AuthenticationError
12
13
  from ccxt.base.errors import NetworkError
13
14
  from ccxt.base.errors import InvalidNonce
14
- from ccxt.base.errors import AuthenticationError
15
15
 
16
16
 
17
17
  class cryptocom(ccxt.async_support.cryptocom):
ccxt/pro/gate.py CHANGED
@@ -9,10 +9,10 @@ import hashlib
9
9
  from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
+ from ccxt.base.errors import AuthenticationError
12
13
  from ccxt.base.errors import ArgumentsRequired
13
14
  from ccxt.base.errors import BadRequest
14
15
  from ccxt.base.errors import InvalidNonce
15
- from ccxt.base.errors import AuthenticationError
16
16
 
17
17
 
18
18
  class gate(ccxt.async_support.gate):
ccxt/pro/hitbtc.py CHANGED
@@ -10,8 +10,8 @@ from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, Ord
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
- from ccxt.base.errors import NotSupported
14
13
  from ccxt.base.errors import AuthenticationError
14
+ from ccxt.base.errors import NotSupported
15
15
 
16
16
 
17
17
  class hitbtc(ccxt.async_support.hitbtc):
ccxt/pro/hollaex.py CHANGED
@@ -9,9 +9,9 @@ import hashlib
9
9
  from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
+ from ccxt.base.errors import AuthenticationError
12
13
  from ccxt.base.errors import BadRequest
13
14
  from ccxt.base.errors import BadSymbol
14
- from ccxt.base.errors import AuthenticationError
15
15
 
16
16
 
17
17
  class hollaex(ccxt.async_support.hollaex):
ccxt/pro/htx.py CHANGED
@@ -10,12 +10,12 @@ from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Stri
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
+ from ccxt.base.errors import AuthenticationError
13
14
  from ccxt.base.errors import ArgumentsRequired
14
15
  from ccxt.base.errors import BadRequest
15
16
  from ccxt.base.errors import BadSymbol
16
17
  from ccxt.base.errors import NetworkError
17
18
  from ccxt.base.errors import InvalidNonce
18
- from ccxt.base.errors import AuthenticationError
19
19
 
20
20
 
21
21
  class htx(ccxt.async_support.htx):
ccxt/pro/kraken.py CHANGED
@@ -5,10 +5,11 @@
5
5
 
6
6
  import ccxt.async_support
7
7
  from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
8
- from ccxt.base.types import Int, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade
8
+ from ccxt.base.types import Int, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade
9
9
  from ccxt.async_support.base.ws.client import Client
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
12
13
  from ccxt.base.errors import PermissionDenied
13
14
  from ccxt.base.errors import AccountSuspended
14
15
  from ccxt.base.errors import BadRequest
@@ -20,7 +21,6 @@ from ccxt.base.errors import NotSupported
20
21
  from ccxt.base.errors import RateLimitExceeded
21
22
  from ccxt.base.errors import ExchangeNotAvailable
22
23
  from ccxt.base.errors import InvalidNonce
23
- from ccxt.base.errors import AuthenticationError
24
24
  from ccxt.base.precise import Precise
25
25
 
26
26
 
@@ -34,10 +34,12 @@ class kraken(ccxt.async_support.kraken):
34
34
  'watchMyTrades': True,
35
35
  'watchOHLCV': True,
36
36
  'watchOrderBook': True,
37
+ 'watchOrderBookForSymbols': True,
37
38
  'watchOrders': True,
38
39
  'watchTicker': True,
39
- 'watchTickers': False, # for now
40
+ 'watchTickers': True,
40
41
  'watchTrades': True,
42
+ 'watchTradesForSymbols': True,
41
43
  'createOrderWs': True,
42
44
  'editOrderWs': True,
43
45
  'cancelOrderWs': True,
@@ -317,10 +319,9 @@ class kraken(ccxt.async_support.kraken):
317
319
  # ]
318
320
  #
319
321
  wsName = message[3]
320
- name = 'ticker'
321
- messageHash = name + ':' + wsName
322
322
  market = self.safe_value(self.options['marketsByWsName'], wsName)
323
323
  symbol = market['symbol']
324
+ messageHash = self.get_message_hash('ticker', None, symbol)
324
325
  ticker = message[1]
325
326
  vwap = self.safe_string(ticker['p'], 0)
326
327
  quoteVolume = None
@@ -350,9 +351,6 @@ class kraken(ccxt.async_support.kraken):
350
351
  'quoteVolume': quoteVolume,
351
352
  'info': ticker,
352
353
  })
353
- # todo add support for multiple tickers(may be tricky)
354
- # kraken confirms multi-pair subscriptions separately one by one
355
- # trigger correct watchTickers calls upon receiving any of symbols
356
354
  self.tickers[symbol] = result
357
355
  client.resolve(result, messageHash)
358
356
 
@@ -370,9 +368,9 @@ class kraken(ccxt.async_support.kraken):
370
368
  #
371
369
  wsName = self.safe_string(message, 3)
372
370
  name = self.safe_string(message, 2)
373
- messageHash = name + ':' + wsName
374
371
  market = self.safe_value(self.options['marketsByWsName'], wsName)
375
372
  symbol = market['symbol']
373
+ messageHash = self.get_message_hash(name, None, symbol)
376
374
  stored = self.safe_value(self.trades, symbol)
377
375
  if stored is None:
378
376
  limit = self.safe_integer(self.options, 'tradesLimit', 1000)
@@ -467,43 +465,85 @@ class kraken(ccxt.async_support.kraken):
467
465
  :param dict [params]: extra parameters specific to the exchange API endpoint
468
466
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
469
467
  """
470
- return await self.watch_public('ticker', symbol, params)
468
+ await self.load_markets()
469
+ symbol = self.symbol(symbol)
470
+ tickers = await self.watch_tickers([symbol], params)
471
+ return tickers[symbol]
472
+
473
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
474
+ """
475
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
476
+ :param str symbol: unified symbol of the market to fetch the ticker for
477
+ :param dict [params]: extra parameters specific to the exchange API endpoint
478
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
479
+ """
480
+ await self.load_markets()
481
+ symbols = self.market_symbols(symbols, None, False)
482
+ ticker = await self.watch_multi_helper('ticker', 'ticker', symbols, None, params)
483
+ if self.newUpdates:
484
+ result = {}
485
+ result[ticker['symbol']] = ticker
486
+ return result
487
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
471
488
 
472
489
  async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
473
490
  """
474
491
  get the list of most recent trades for a particular symbol
492
+ :see: https://docs.kraken.com/websockets/#message-trade
475
493
  :param str symbol: unified symbol of the market to fetch trades for
476
494
  :param int [since]: timestamp in ms of the earliest trade to fetch
477
495
  :param int [limit]: the maximum amount of trades to fetch
478
496
  :param dict [params]: extra parameters specific to the exchange API endpoint
479
497
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
480
498
  """
481
- await self.load_markets()
482
- symbol = self.symbol(symbol)
483
- name = 'trade'
484
- trades = await self.watch_public(name, symbol, params)
499
+ return await self.watch_trades_for_symbols([symbol], since, limit, params)
500
+
501
+ async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
502
+ """
503
+ :see: https://docs.kraken.com/websockets/#message-trade
504
+ get the list of most recent trades for a list of symbols
505
+ :param str[] symbols: unified symbol of the market to fetch trades for
506
+ :param int [since]: timestamp in ms of the earliest trade to fetch
507
+ :param int [limit]: the maximum amount of trades to fetch
508
+ :param dict [params]: extra parameters specific to the exchange API endpoint
509
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
510
+ """
511
+ trades = await self.watch_multi_helper('trade', 'trade', symbols, None, params)
485
512
  if self.newUpdates:
486
- limit = trades.getLimit(symbol, limit)
513
+ first = self.safe_list(trades, 0)
514
+ tradeSymbol = self.safe_string(first, 'symbol')
515
+ limit = trades.getLimit(tradeSymbol, limit)
487
516
  return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
488
517
 
489
518
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
490
519
  """
491
520
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
521
+ :see: https://docs.kraken.com/websockets/#message-book
492
522
  :param str symbol: unified symbol of the market to fetch the order book for
493
523
  :param int [limit]: the maximum amount of order book entries to return
494
524
  :param dict [params]: extra parameters specific to the exchange API endpoint
495
525
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
496
526
  """
497
- name = 'book'
527
+ return await self.watch_order_book_for_symbols([symbol], limit, params)
528
+
529
+ async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
530
+ """
531
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
532
+ :see: https://docs.kraken.com/websockets/#message-book
533
+ :param str[] symbols: unified array of symbols
534
+ :param int [limit]: the maximum amount of order book entries to return
535
+ :param dict [params]: extra parameters specific to the exchange API endpoint
536
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
537
+ """
498
538
  request = {}
499
539
  if limit is not None:
500
- if (limit == 10) or (limit == 25) or (limit == 100) or (limit == 500) or (limit == 1000):
540
+ if self.in_array(limit, [10, 25, 100, 500, 1000]):
501
541
  request['subscription'] = {
502
542
  'depth': limit, # default 10, valid options 10, 25, 100, 500, 1000
503
543
  }
504
544
  else:
505
545
  raise NotSupported(self.id + ' watchOrderBook accepts limit values of 10, 25, 100, 500 and 1000 only')
506
- orderbook = await self.watch_public(name, symbol, self.extend(request, params))
546
+ orderbook = await self.watch_multi_helper('orderbook', 'book', symbols, {'limit': limit}, self.extend(request, params))
507
547
  return orderbook.limit()
508
548
 
509
549
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
@@ -625,7 +665,7 @@ class kraken(ccxt.async_support.kraken):
625
665
  market = self.safe_value(self.options['marketsByWsName'], wsName)
626
666
  symbol = market['symbol']
627
667
  timestamp = None
628
- messageHash = 'book:' + wsName
668
+ messageHash = self.get_message_hash('orderbook', None, symbol)
629
669
  # if self is a snapshot
630
670
  if 'as' in message[1]:
631
671
  # todo get depth from marketsByWsName
@@ -695,6 +735,7 @@ class kraken(ccxt.async_support.kraken):
695
735
  if localChecksum != c:
696
736
  error = InvalidNonce(self.id + ' invalid checksum')
697
737
  client.reject(error, messageHash)
738
+ return
698
739
  orderbook['symbol'] = symbol
699
740
  orderbook['timestamp'] = timestamp
700
741
  orderbook['datetime'] = self.iso8601(timestamp)
@@ -1179,6 +1220,43 @@ class kraken(ccxt.async_support.kraken):
1179
1220
  'trades': trades,
1180
1221
  })
1181
1222
 
1223
+ async def watch_multi_helper(self, unifiedName: str, channelName: str, symbols: Strings = None, subscriptionArgs=None, params={}):
1224
+ await self.load_markets()
1225
+ # symbols are required
1226
+ symbols = self.market_symbols(symbols, None, False, True, False)
1227
+ messageHashes = []
1228
+ for i in range(0, len(symbols)):
1229
+ messageHashes.append(self.get_message_hash(unifiedName, None, self.symbol(symbols[i])))
1230
+ # for WS subscriptions, we can't use .market_ids(symbols), instead a custom is field needed
1231
+ markets = self.markets_for_symbols(symbols)
1232
+ wsMarketIds = []
1233
+ for i in range(0, len(markets)):
1234
+ wsMarketId = self.safe_string(markets[i]['info'], 'wsname')
1235
+ wsMarketIds.append(wsMarketId)
1236
+ request = {
1237
+ 'event': 'subscribe',
1238
+ 'reqid': self.request_id(),
1239
+ 'pair': wsMarketIds,
1240
+ 'subscription': {
1241
+ 'name': channelName,
1242
+ },
1243
+ }
1244
+ url = self.urls['api']['ws']['public']
1245
+ return await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscriptionArgs)
1246
+
1247
+ def get_message_hash(self, unifiedElementName: str, subChannelName: Str = None, symbol: Str = None):
1248
+ # unifiedElementName can be : orderbook, trade, ticker, bidask ...
1249
+ # subChannelName only applies to channel that needs specific variation(i.e. depth_50, depth_100..) to be selected
1250
+ withSymbol = symbol is not None
1251
+ messageHash = unifiedElementName
1252
+ if not withSymbol:
1253
+ messageHash += 's'
1254
+ else:
1255
+ messageHash += '@' + symbol
1256
+ if subChannelName is not None:
1257
+ messageHash += '#' + subChannelName
1258
+ return messageHash
1259
+
1182
1260
  def handle_subscription_status(self, client: Client, message):
1183
1261
  #
1184
1262
  # public