ccxt 4.3.61__py2.py3-none-any.whl → 4.3.63__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 (69) hide show
  1. ccxt/__init__.py +2 -1
  2. ccxt/abstract/binance.py +5 -5
  3. ccxt/abstract/binancecoinm.py +5 -5
  4. ccxt/abstract/binanceus.py +5 -5
  5. ccxt/abstract/binanceusdm.py +5 -5
  6. ccxt/abstract/cryptocom.py +11 -0
  7. ccxt/abstract/woo.py +3 -0
  8. ccxt/ace.py +33 -15
  9. ccxt/async_support/__init__.py +2 -1
  10. ccxt/async_support/ace.py +33 -15
  11. ccxt/async_support/base/exchange.py +1 -1
  12. ccxt/async_support/base/ws/fast_client.py +2 -2
  13. ccxt/async_support/binance.py +43 -38
  14. ccxt/async_support/bingx.py +492 -184
  15. ccxt/async_support/bybit.py +1 -1
  16. ccxt/async_support/coinbaseinternational.py +1 -1
  17. ccxt/async_support/cryptocom.py +17 -2
  18. ccxt/async_support/mercado.py +5 -1
  19. ccxt/async_support/tradeogre.py +1 -1
  20. ccxt/async_support/woo.py +296 -81
  21. ccxt/async_support/xt.py +4 -4
  22. ccxt/base/errors.py +8 -1
  23. ccxt/base/exchange.py +8 -2
  24. ccxt/binance.py +43 -38
  25. ccxt/bingx.py +492 -184
  26. ccxt/bybit.py +1 -1
  27. ccxt/coinbaseinternational.py +1 -1
  28. ccxt/cryptocom.py +17 -2
  29. ccxt/mercado.py +5 -1
  30. ccxt/pro/__init__.py +1 -1
  31. ccxt/pro/alpaca.py +3 -3
  32. ccxt/pro/binance.py +58 -39
  33. ccxt/pro/bingx.py +2 -2
  34. ccxt/pro/bitfinex2.py +8 -6
  35. ccxt/pro/bitget.py +6 -3
  36. ccxt/pro/bitmex.py +1 -1
  37. ccxt/pro/bitopro.py +1 -1
  38. ccxt/pro/bitvavo.py +1 -1
  39. ccxt/pro/bybit.py +46 -23
  40. ccxt/pro/coinbaseexchange.py +2 -2
  41. ccxt/pro/coincheck.py +1 -1
  42. ccxt/pro/coinone.py +1 -1
  43. ccxt/pro/cryptocom.py +8 -3
  44. ccxt/pro/deribit.py +1 -1
  45. ccxt/pro/gate.py +8 -5
  46. ccxt/pro/hollaex.py +1 -1
  47. ccxt/pro/htx.py +6 -2
  48. ccxt/pro/hyperliquid.py +3 -3
  49. ccxt/pro/independentreserve.py +6 -4
  50. ccxt/pro/kraken.py +80 -7
  51. ccxt/pro/kucoin.py +1 -1
  52. ccxt/pro/mexc.py +1 -1
  53. ccxt/pro/okx.py +5 -5
  54. ccxt/pro/oxfun.py +1 -1
  55. ccxt/pro/phemex.py +1 -1
  56. ccxt/pro/poloniexfutures.py +5 -2
  57. ccxt/pro/upbit.py +1 -1
  58. ccxt/pro/vertex.py +2 -2
  59. ccxt/pro/whitebit.py +1 -1
  60. ccxt/pro/woo.py +1 -1
  61. ccxt/pro/woofipro.py +1 -1
  62. ccxt/tradeogre.py +1 -1
  63. ccxt/woo.py +296 -81
  64. ccxt/xt.py +4 -4
  65. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/METADATA +4 -4
  66. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/RECORD +69 -69
  67. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/LICENSE.txt +0 -0
  68. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/WHEEL +0 -0
  69. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/top_level.txt +0 -0
ccxt/bybit.py CHANGED
@@ -5877,6 +5877,7 @@ class bybit(Exchange, ImplicitAPI):
5877
5877
  :param str [params.settleCoin]: Settle coin. Supports linear, inverse & option
5878
5878
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
5879
5879
  """
5880
+ self.load_markets()
5880
5881
  symbol = None
5881
5882
  if (symbols is not None) and isinstance(symbols, list):
5882
5883
  symbolsLength = len(symbols)
@@ -5888,7 +5889,6 @@ class bybit(Exchange, ImplicitAPI):
5888
5889
  elif symbols is not None:
5889
5890
  symbol = symbols
5890
5891
  symbols = [self.symbol(symbol)]
5891
- self.load_markets()
5892
5892
  enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
5893
5893
  isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
5894
5894
  request: dict = {}
@@ -571,7 +571,7 @@ class coinbaseinternational(Exchange, ImplicitAPI):
571
571
  }
572
572
  return self.v1PrivatePostPortfoliosMargin(self.extend(request, params))
573
573
 
574
- def fetch_deposits_withdrawals(self, code: str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
574
+ def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
575
575
  """
576
576
  fetch history of deposits and withdrawals
577
577
  :see: https://docs.cloud.coinbase.com/intx/reference/gettransfers
ccxt/cryptocom.py CHANGED
@@ -176,6 +176,9 @@ class cryptocom(Exchange, ImplicitAPI):
176
176
  'public/get-expired-settlement-price': 10 / 3,
177
177
  'public/get-insurance': 1,
178
178
  },
179
+ 'post': {
180
+ 'public/staking/get-conversion-rate': 2,
181
+ },
179
182
  },
180
183
  'private': {
181
184
  'post': {
@@ -205,6 +208,16 @@ class cryptocom(Exchange, ImplicitAPI):
205
208
  'private/get-accounts': 10 / 3,
206
209
  'private/get-withdrawal-history': 10 / 3,
207
210
  'private/get-deposit-history': 10 / 3,
211
+ 'private/staking/stake': 2,
212
+ 'private/staking/unstake': 2,
213
+ 'private/staking/get-staking-position': 2,
214
+ 'private/staking/get-staking-instruments': 2,
215
+ 'private/staking/get-open-stake': 2,
216
+ 'private/staking/get-stake-history': 2,
217
+ 'private/staking/get-reward-history': 2,
218
+ 'private/staking/convert': 2,
219
+ 'private/staking/get-open-convert': 2,
220
+ 'private/staking/get-convert-history': 2,
208
221
  },
209
222
  },
210
223
  },
@@ -799,15 +812,17 @@ class cryptocom(Exchange, ImplicitAPI):
799
812
  'timeframe': self.safe_string(self.timeframes, timeframe, timeframe),
800
813
  }
801
814
  if limit is not None:
815
+ if limit > 300:
816
+ limit = 300
802
817
  request['count'] = limit
803
818
  now = self.microseconds()
804
819
  duration = self.parse_timeframe(timeframe)
805
820
  until = self.safe_integer(params, 'until', now)
806
821
  params = self.omit(params, ['until'])
807
822
  if since is not None:
808
- request['start_ts'] = since
823
+ request['start_ts'] = since - duration * 1000
809
824
  if limit is not None:
810
- request['end_ts'] = self.sum(since, duration * (limit + 1) * 1000) - 1
825
+ request['end_ts'] = self.sum(since, duration * limit * 1000)
811
826
  else:
812
827
  request['end_ts'] = until
813
828
  else:
ccxt/mercado.py CHANGED
@@ -12,6 +12,7 @@ from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
13
13
  from ccxt.base.errors import InvalidOrder
14
14
  from ccxt.base.decimal_to_precision import TICK_SIZE
15
+ from ccxt.base.precise import Precise
15
16
 
16
17
 
17
18
  class mercado(Exchange, ImplicitAPI):
@@ -444,7 +445,10 @@ class mercado(Exchange, ImplicitAPI):
444
445
  if side == 'buy':
445
446
  if price is None:
446
447
  raise InvalidOrder(self.id + ' createOrder() requires the price argument with market buy orders to calculate total order cost(amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount')
447
- request['cost'] = self.price_to_precision(market['symbol'], amount * price)
448
+ amountString = self.number_to_string(amount)
449
+ priceString = self.number_to_string(price)
450
+ cost = self.parse_to_numeric(Precise.string_mul(amountString, priceString))
451
+ request['cost'] = self.price_to_precision(market['symbol'], cost)
448
452
  else:
449
453
  request['quantity'] = self.amount_to_precision(market['symbol'], amount)
450
454
  response = getattr(self, method)(self.extend(request, params))
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.61'
7
+ __version__ = '4.3.63'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/alpaca.py CHANGED
@@ -258,7 +258,7 @@ class alpaca(ccxt.async_support.alpaca):
258
258
  :param int [since]: the earliest time in ms to fetch orders for
259
259
  :param int [limit]: the maximum number of trade structures to retrieve
260
260
  :param dict [params]: extra parameters specific to the exchange API endpoint
261
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
261
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
262
262
  """
263
263
  url = self.urls['api']['ws']['crypto']
264
264
  await self.authenticate(url)
@@ -307,7 +307,7 @@ class alpaca(ccxt.async_support.alpaca):
307
307
  :param int [limit]: the maximum number of trade structures to retrieve
308
308
  :param dict [params]: extra parameters specific to the exchange API endpoint
309
309
  :param boolean [params.unifiedMargin]: use unified margin account
310
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
310
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
311
311
  """
312
312
  url = self.urls['api']['ws']['trading']
313
313
  await self.authenticate(url)
@@ -334,7 +334,7 @@ class alpaca(ccxt.async_support.alpaca):
334
334
  :param int [since]: the earliest time in ms to fetch orders for
335
335
  :param int [limit]: the maximum number of order structures to retrieve
336
336
  :param dict [params]: extra parameters specific to the exchange API endpoint
337
- :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
337
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
338
338
  """
339
339
  url = self.urls['api']['ws']['trading']
340
340
  await self.authenticate(url)
ccxt/pro/binance.py CHANGED
@@ -12,7 +12,7 @@ from typing import List
12
12
  from ccxt.base.errors import ArgumentsRequired
13
13
  from ccxt.base.errors import BadRequest
14
14
  from ccxt.base.errors import NotSupported
15
- from ccxt.base.errors import InvalidNonce
15
+ from ccxt.base.errors import ChecksumError
16
16
  from ccxt.base.precise import Precise
17
17
 
18
18
 
@@ -30,7 +30,7 @@ class binance(ccxt.async_support.binance):
30
30
  'watchBidsAsks': True,
31
31
  'watchMyTrades': True,
32
32
  'watchOHLCV': True,
33
- 'watchOHLCVForSymbols': False,
33
+ 'watchOHLCVForSymbols': True,
34
34
  'watchOrderBook': True,
35
35
  'watchOrderBookForSymbols': True,
36
36
  'watchOrders': True,
@@ -133,6 +133,7 @@ class binance(ccxt.async_support.binance):
133
133
  },
134
134
  'watchOrderBook': {
135
135
  'maxRetries': 3,
136
+ 'checksum': True,
136
137
  },
137
138
  'watchBalance': {
138
139
  'fetchBalanceSnapshot': False, # or True
@@ -679,10 +680,8 @@ class binance(ccxt.async_support.binance):
679
680
  client.resolve(orderbook, messageHash)
680
681
 
681
682
  async def fetch_order_book_snapshot(self, client, message, subscription):
682
- name = self.safe_string(subscription, 'name')
683
683
  symbol = self.safe_string(subscription, 'symbol')
684
- market = self.market(symbol)
685
- messageHash = market['lowercaseId'] + '@' + name
684
+ messageHash = 'orderbook::' + symbol
686
685
  try:
687
686
  defaultLimit = self.safe_integer(self.options, 'watchOrderBookLimit', 1000)
688
687
  type = self.safe_value(subscription, 'type')
@@ -807,10 +806,10 @@ class binance(ccxt.async_support.binance):
807
806
  if nonce < orderbook['nonce']:
808
807
  client.resolve(orderbook, messageHash)
809
808
  else:
810
- checksum = self.safe_bool(self.options, 'checksum', True)
809
+ checksum = self.handle_option('watchOrderBook', 'checksum', True)
811
810
  if checksum:
812
811
  # todo: client.reject from handleOrderBookMessage properly
813
- raise InvalidNonce(self.id + ' handleOrderBook received an out-of-order nonce')
812
+ raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
814
813
  else:
815
814
  # future
816
815
  # 4. Drop any event where u is < lastUpdateId in the snapshot
@@ -822,10 +821,10 @@ class binance(ccxt.async_support.binance):
822
821
  if nonce <= orderbook['nonce']:
823
822
  client.resolve(orderbook, messageHash)
824
823
  else:
825
- checksum = self.safe_bool(self.options, 'checksum', True)
824
+ checksum = self.handle_option('watchOrderBook', 'checksum', True)
826
825
  if checksum:
827
826
  # todo: client.reject from handleOrderBookMessage properly
828
- raise InvalidNonce(self.id + ' handleOrderBook received an out-of-order nonce')
827
+ raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
829
828
  except Exception as e:
830
829
  del self.orderbooks[symbol]
831
830
  del client.subscriptions[messageHash]
@@ -1106,37 +1105,57 @@ class binance(ccxt.async_support.binance):
1106
1105
  :param dict [params]: extra parameters specific to the exchange API endpoint
1107
1106
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
1108
1107
  """
1108
+ params['callerMethodName'] = 'watchOHLCV'
1109
+ result = await self.watch_ohlcv_for_symbols([[symbol, timeframe]], since, limit, params)
1110
+ return result[symbol][timeframe]
1111
+
1112
+ async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
1113
+ """
1114
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1115
+ :param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
1116
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1117
+ :param int [limit]: the maximum amount of candles to fetch
1118
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1119
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1120
+ """
1109
1121
  await self.load_markets()
1110
- market = self.market(symbol)
1111
- marketId = market['lowercaseId']
1112
- interval = self.safe_string(self.timeframes, timeframe, timeframe)
1113
- options = self.safe_value(self.options, 'watchOHLCV', {})
1114
- nameOption = self.safe_string(options, 'name', 'kline')
1115
- name = self.safe_string(params, 'name', nameOption)
1116
- if name == 'indexPriceKline':
1117
- marketId = marketId.replace('_perp', '')
1118
- # weird behavior for index price kline we can't use the perp suffix
1119
- params = self.omit(params, 'name')
1120
- messageHash = marketId + '@' + name + '_' + interval
1121
- type = market['type']
1122
- if market['contract']:
1123
- type = 'future' if market['linear'] else 'delivery'
1124
- url = self.urls['api']['ws'][type] + '/' + self.stream(type, messageHash)
1122
+ klineType = None
1123
+ klineType, params = self.handle_param_string_2(params, 'channel', 'name', 'kline')
1124
+ symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
1125
+ marketSymbols = self.market_symbols(symbols, None, False, False, True)
1126
+ firstMarket = self.market(marketSymbols[0])
1127
+ type = firstMarket['type']
1128
+ if firstMarket['contract']:
1129
+ type = 'future' if firstMarket['linear'] else 'delivery'
1130
+ rawHashes = []
1131
+ messageHashes = []
1132
+ for i in range(0, len(symbolsAndTimeframes)):
1133
+ symAndTf = symbolsAndTimeframes[i]
1134
+ symbolString = symAndTf[0]
1135
+ timeframeString = symAndTf[1]
1136
+ interval = self.safe_string(self.timeframes, timeframeString, timeframeString)
1137
+ market = self.market(symbolString)
1138
+ marketId = market['lowercaseId']
1139
+ if klineType == 'indexPriceKline':
1140
+ # weird behavior for index price kline we can't use the perp suffix
1141
+ marketId = marketId.replace('_perp', '')
1142
+ rawHashes.append(marketId + '@' + klineType + '_' + interval)
1143
+ messageHashes.append('ohlcv::' + symbolString + '::' + timeframeString)
1144
+ url = self.urls['api']['ws'][type] + '/' + self.stream(type, 'multipleOHLCV')
1125
1145
  requestId = self.request_id(url)
1126
- request: dict = {
1146
+ request = {
1127
1147
  'method': 'SUBSCRIBE',
1128
- 'params': [
1129
- messageHash,
1130
- ],
1148
+ 'params': rawHashes,
1131
1149
  'id': requestId,
1132
1150
  }
1133
- subscribe: dict = {
1151
+ subscribe = {
1134
1152
  'id': requestId,
1135
1153
  }
1136
- ohlcv = await self.watch(url, messageHash, self.extend(request, params), messageHash, subscribe)
1154
+ symbol, timeframe, candles = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscribe)
1137
1155
  if self.newUpdates:
1138
- limit = ohlcv.getLimit(symbol, limit)
1139
- return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
1156
+ limit = candles.getLimit(symbol, limit)
1157
+ filtered = self.filter_by_since_limit(candles, since, limit, 0, True)
1158
+ return self.create_ohlcv_object(symbol, timeframe, filtered)
1140
1159
 
1141
1160
  def handle_ohlcv(self, client: Client, message):
1142
1161
  #
@@ -1176,11 +1195,9 @@ class binance(ccxt.async_support.binance):
1176
1195
  if event == 'indexPriceKline':
1177
1196
  # indexPriceKline doesn't have the _PERP suffix
1178
1197
  marketId = self.safe_string(message, 'ps')
1179
- lowercaseMarketId = marketId.lower()
1180
1198
  interval = self.safe_string(kline, 'i')
1181
1199
  # use a reverse lookup in a static map instead
1182
- timeframe = self.find_timeframe(interval)
1183
- messageHash = lowercaseMarketId + '@' + event + '_' + interval
1200
+ unifiedTimeframe = self.find_timeframe(interval)
1184
1201
  parsed = [
1185
1202
  self.safe_integer(kline, 't'),
1186
1203
  self.safe_float(kline, 'o'),
@@ -1192,14 +1209,16 @@ class binance(ccxt.async_support.binance):
1192
1209
  isSpot = ((client.url.find('/stream') > -1) or (client.url.find('/testnet.binance') > -1))
1193
1210
  marketType = 'spot' if (isSpot) else 'contract'
1194
1211
  symbol = self.safe_symbol(marketId, None, None, marketType)
1212
+ messageHash = 'ohlcv::' + symbol + '::' + unifiedTimeframe
1195
1213
  self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
1196
- stored = self.safe_value(self.ohlcvs[symbol], timeframe)
1214
+ stored = self.safe_value(self.ohlcvs[symbol], unifiedTimeframe)
1197
1215
  if stored is None:
1198
1216
  limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
1199
1217
  stored = ArrayCacheByTimestamp(limit)
1200
- self.ohlcvs[symbol][timeframe] = stored
1218
+ self.ohlcvs[symbol][unifiedTimeframe] = stored
1201
1219
  stored.append(parsed)
1202
- client.resolve(stored, messageHash)
1220
+ resolveData = [symbol, unifiedTimeframe, stored]
1221
+ client.resolve(resolveData, messageHash)
1203
1222
 
1204
1223
  async def fetch_ticker_ws(self, symbol: str, params={}) -> Ticker:
1205
1224
  """
@@ -3260,7 +3279,7 @@ class binance(ccxt.async_support.binance):
3260
3279
  :param int [limit]: the maximum number of order structures to retrieve
3261
3280
  :param dict [params]: extra parameters specific to the exchange API endpoint
3262
3281
  :param boolean [params.portfolioMargin]: set to True if you would like to watch trades in a portfolio margin account
3263
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
3282
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
3264
3283
  """
3265
3284
  await self.load_markets()
3266
3285
  type = None
ccxt/pro/bingx.py CHANGED
@@ -409,7 +409,7 @@ class bingx(ccxt.async_support.bingx):
409
409
  :param int [since]: the earliest time in ms to fetch orders for
410
410
  :param int [limit]: the maximum number of order structures to retrieve
411
411
  :param dict [params]: extra parameters specific to the exchange API endpoint
412
- :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
412
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
413
413
  """
414
414
  await self.load_markets()
415
415
  market = self.market(symbol)
@@ -824,7 +824,7 @@ class bingx(ccxt.async_support.bingx):
824
824
  :param int [since]: the earliest time in ms to trades orders for
825
825
  :param int [limit]: the maximum number of trades structures to retrieve
826
826
  :param dict [params]: extra parameters specific to the exchange API endpoint
827
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
827
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
828
828
  """
829
829
  await self.load_markets()
830
830
  await self.authenticate()
ccxt/pro/bitfinex2.py CHANGED
@@ -11,7 +11,7 @@ from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
14
- from ccxt.base.errors import InvalidNonce
14
+ from ccxt.base.errors import ChecksumError
15
15
  from ccxt.base.precise import Precise
16
16
 
17
17
 
@@ -42,9 +42,9 @@ class bitfinex2(ccxt.async_support.bitfinex2):
42
42
  'watchOrderBook': {
43
43
  'prec': 'P0',
44
44
  'freq': 'F0',
45
+ 'checksum': True,
45
46
  },
46
47
  'ordersLimit': 1000,
47
- 'checksum': True,
48
48
  },
49
49
  })
50
50
 
@@ -205,7 +205,7 @@ class bitfinex2(ccxt.async_support.bitfinex2):
205
205
  :param int [since]: the earliest time in ms to fetch trades for
206
206
  :param int [limit]: the maximum number of trade structures to retrieve
207
207
  :param dict [params]: extra parameters specific to the exchange API endpoint
208
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
208
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
209
209
  """
210
210
  await self.load_markets()
211
211
  messageHash = 'myTrade'
@@ -641,10 +641,12 @@ class bitfinex2(ccxt.async_support.bitfinex2):
641
641
  localChecksum = self.crc32(payload, True)
642
642
  responseChecksum = self.safe_integer(message, 2)
643
643
  if responseChecksum != localChecksum:
644
- error = InvalidNonce(self.id + ' invalid checksum')
645
644
  del client.subscriptions[messageHash]
646
645
  del self.orderbooks[symbol]
647
- client.reject(error, messageHash)
646
+ checksum = self.handle_option('watchOrderBook', 'checksum', True)
647
+ if checksum:
648
+ error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
649
+ client.reject(error, messageHash)
648
650
 
649
651
  async def watch_balance(self, params={}) -> Balances:
650
652
  """
@@ -837,7 +839,7 @@ class bitfinex2(ccxt.async_support.bitfinex2):
837
839
  :param int [since]: the earliest time in ms to fetch orders for
838
840
  :param int [limit]: the maximum number of order structures to retrieve
839
841
  :param dict [params]: extra parameters specific to the exchange API endpoint
840
- :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
842
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
841
843
  """
842
844
  await self.load_markets()
843
845
  messageHash = 'orders'
ccxt/pro/bitget.py CHANGED
@@ -14,7 +14,7 @@ from ccxt.base.errors import AuthenticationError
14
14
  from ccxt.base.errors import ArgumentsRequired
15
15
  from ccxt.base.errors import BadRequest
16
16
  from ccxt.base.errors import RateLimitExceeded
17
- from ccxt.base.errors import InvalidNonce
17
+ from ccxt.base.errors import ChecksumError
18
18
  from ccxt.base.precise import Precise
19
19
 
20
20
 
@@ -68,6 +68,9 @@ class bitget(ccxt.async_support.bitget):
68
68
  '1d': '1D',
69
69
  '1w': '1W',
70
70
  },
71
+ 'watchOrderBook': {
72
+ 'checksum': True,
73
+ },
71
74
  },
72
75
  'streaming': {
73
76
  'ping': self.ping,
@@ -539,9 +542,9 @@ class bitget(ccxt.async_support.bitget):
539
542
  calculatedChecksum = self.crc32(payload, True)
540
543
  responseChecksum = self.safe_integer(rawOrderBook, 'checksum')
541
544
  if calculatedChecksum != responseChecksum:
542
- error = InvalidNonce(self.id + ' invalid checksum')
543
545
  del client.subscriptions[messageHash]
544
546
  del self.orderbooks[symbol]
547
+ error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
545
548
  client.reject(error, messageHash)
546
549
  return
547
550
  else:
@@ -920,7 +923,7 @@ class bitget(ccxt.async_support.bitget):
920
923
  :param str [params.marginMode]: 'isolated' or 'cross' for watching spot margin orders]
921
924
  :param str [params.type]: 'spot', 'swap'
922
925
  :param str [params.subType]: 'linear', 'inverse'
923
- :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
926
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
924
927
  """
925
928
  await self.load_markets()
926
929
  market = None
ccxt/pro/bitmex.py CHANGED
@@ -1104,7 +1104,7 @@ class bitmex(ccxt.async_support.bitmex):
1104
1104
  :param int [since]: the earliest time in ms to fetch trades for
1105
1105
  :param int [limit]: the maximum number of trade structures to retrieve
1106
1106
  :param dict [params]: extra parameters specific to the exchange API endpoint
1107
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
1107
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1108
1108
  """
1109
1109
  await self.load_markets()
1110
1110
  await self.authenticate()
ccxt/pro/bitopro.py CHANGED
@@ -176,7 +176,7 @@ class bitopro(ccxt.async_support.bitopro):
176
176
  :param int [since]: the earliest time in ms to fetch trades for
177
177
  :param int [limit]: the maximum number of trade structures to retrieve
178
178
  :param dict [params]: extra parameters specific to the exchange API endpoint
179
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
179
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
180
180
  """
181
181
  self.check_required_credentials()
182
182
  await self.load_markets()
ccxt/pro/bitvavo.py CHANGED
@@ -476,7 +476,7 @@ class bitvavo(ccxt.async_support.bitvavo):
476
476
  :param int [since]: the earliest time in ms to fetch trades for
477
477
  :param int [limit]: the maximum number of trade structures to retrieve
478
478
  :param dict [params]: extra parameters specific to the exchange API endpoint
479
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=ortradeder-structure
479
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
480
480
  """
481
481
  if symbol is None:
482
482
  raise ArgumentsRequired(self.id + ' watchMyTrades() requires a symbol argument')
ccxt/pro/bybit.py CHANGED
@@ -38,7 +38,7 @@ class bybit(ccxt.async_support.bybit):
38
38
  'watchMyLiquidationsForSymbols': False,
39
39
  'watchMyTrades': True,
40
40
  'watchOHLCV': True,
41
- 'watchOHLCVForSymbols': False,
41
+ 'watchOHLCVForSymbols': True,
42
42
  'watchOrderBook': True,
43
43
  'watchOrderBookForSymbols': True,
44
44
  'watchOrders': True,
@@ -513,19 +513,42 @@ class bybit(ccxt.async_support.bybit):
513
513
  :param dict [params]: extra parameters specific to the exchange API endpoint
514
514
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
515
515
  """
516
+ params['callerMethodName'] = 'watchOHLCV'
517
+ result = await self.watch_ohlcv_for_symbols([[symbol, timeframe]], since, limit, params)
518
+ return result[symbol][timeframe]
519
+
520
+ async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
521
+ """
522
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
523
+ :see: https://bybit-exchange.github.io/docs/v5/websocket/public/kline
524
+ :see: https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
525
+ :param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
526
+ :param int [since]: timestamp in ms of the earliest candle to fetch
527
+ :param int [limit]: the maximum amount of candles to fetch
528
+ :param dict [params]: extra parameters specific to the exchange API endpoint
529
+ :returns dict: A list of candles ordered, open, high, low, close, volume
530
+ """
516
531
  await self.load_markets()
517
- market = self.market(symbol)
518
- symbol = market['symbol']
519
- url = await self.get_url_by_market_type(symbol, False, 'watchOHLCV', params)
520
- params = self.clean_params(params)
521
- ohlcv = None
522
- timeframeId = self.safe_string(self.timeframes, timeframe, timeframe)
523
- topics = ['kline.' + timeframeId + '.' + market['id']]
524
- messageHash = 'kline' + ':' + timeframeId + ':' + symbol
525
- ohlcv = await self.watch_topics(url, [messageHash], topics, params)
532
+ symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
533
+ marketSymbols = self.market_symbols(symbols, None, False, True, True)
534
+ firstSymbol = marketSymbols[0]
535
+ url = await self.get_url_by_market_type(firstSymbol, False, 'watchOHLCVForSymbols', params)
536
+ rawHashes = []
537
+ messageHashes = []
538
+ for i in range(0, len(symbolsAndTimeframes)):
539
+ data = symbolsAndTimeframes[i]
540
+ symbolString = self.safe_string(data, 0)
541
+ market = self.market(symbolString)
542
+ symbolString = market['symbol']
543
+ unfiedTimeframe = self.safe_string(data, 1)
544
+ timeframeId = self.safe_string(self.timeframes, unfiedTimeframe, unfiedTimeframe)
545
+ rawHashes.append('kline.' + timeframeId + '.' + market['id'])
546
+ messageHashes.append('ohlcv::' + symbolString + '::' + unfiedTimeframe)
547
+ symbol, timeframe, stored = await self.watch_topics(url, messageHashes, rawHashes, params)
526
548
  if self.newUpdates:
527
- limit = ohlcv.getLimit(symbol, limit)
528
- return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
549
+ limit = stored.getLimit(symbol, limit)
550
+ filtered = self.filter_by_since_limit(stored, since, limit, 0, True)
551
+ return self.create_ohlcv_object(symbol, timeframe, filtered)
529
552
 
530
553
  def handle_ohlcv(self, client: Client, message):
531
554
  #
@@ -564,16 +587,16 @@ class bybit(ccxt.async_support.bybit):
564
587
  ohlcvsByTimeframe = self.safe_value(self.ohlcvs, symbol)
565
588
  if ohlcvsByTimeframe is None:
566
589
  self.ohlcvs[symbol] = {}
567
- stored = self.safe_value(ohlcvsByTimeframe, timeframe)
568
- if stored is None:
590
+ if self.safe_value(ohlcvsByTimeframe, timeframe) is None:
569
591
  limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
570
- stored = ArrayCacheByTimestamp(limit)
571
- self.ohlcvs[symbol][timeframe] = stored
592
+ self.ohlcvs[symbol][timeframe] = ArrayCacheByTimestamp(limit)
593
+ stored = self.ohlcvs[symbol][timeframe]
572
594
  for i in range(0, len(data)):
573
595
  parsed = self.parse_ws_ohlcv(data[i])
574
596
  stored.append(parsed)
575
- messageHash = 'kline' + ':' + timeframeId + ':' + symbol
576
- client.resolve(stored, messageHash)
597
+ messageHash = 'ohlcv::' + symbol + '::' + timeframe
598
+ resolveData = [symbol, timeframe, stored]
599
+ client.resolve(resolveData, messageHash)
577
600
 
578
601
  def parse_ws_ohlcv(self, ohlcv, market=None) -> list:
579
602
  #
@@ -723,7 +746,7 @@ class bybit(ccxt.async_support.bybit):
723
746
  :param int [since]: the earliest time in ms to fetch trades for
724
747
  :param int [limit]: the maximum number of trade structures to retrieve
725
748
  :param dict [params]: extra parameters specific to the exchange API endpoint
726
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
749
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
727
750
  """
728
751
  return await self.watch_trades_for_symbols([symbol], since, limit, params)
729
752
 
@@ -885,7 +908,7 @@ class bybit(ccxt.async_support.bybit):
885
908
  :param int [limit]: the maximum number of order structures to retrieve
886
909
  :param dict [params]: extra parameters specific to the exchange API endpoint
887
910
  :param boolean [params.unifiedMargin]: use unified margin account
888
- :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
911
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
889
912
  """
890
913
  method = 'watchMyTrades'
891
914
  messageHash = 'myTrades'
@@ -1174,7 +1197,7 @@ class bybit(ccxt.async_support.bybit):
1174
1197
  rawLiquidation = self.safe_dict(message, 'data', {})
1175
1198
  marketId = self.safe_string(rawLiquidation, 'symbol')
1176
1199
  market = self.safe_market(marketId, None, '', 'contract')
1177
- symbol = self.safe_symbol(marketId)
1200
+ symbol = market['symbol']
1178
1201
  liquidation = self.parse_ws_liquidation(rawLiquidation, market)
1179
1202
  liquidations = self.safe_value(self.liquidations, symbol)
1180
1203
  if liquidations is None:
@@ -1200,7 +1223,7 @@ class bybit(ccxt.async_support.bybit):
1200
1223
  timestamp = self.safe_integer(liquidation, 'updatedTime')
1201
1224
  return self.safe_liquidation({
1202
1225
  'info': liquidation,
1203
- 'symbol': self.safe_symbol(marketId, market),
1226
+ 'symbol': market['symbol'],
1204
1227
  'contracts': self.safe_number(liquidation, 'size'),
1205
1228
  'contractSize': self.safe_number(market, 'contractSize'),
1206
1229
  'price': self.safe_number(liquidation, 'price'),
@@ -1218,7 +1241,7 @@ class bybit(ccxt.async_support.bybit):
1218
1241
  :param int [since]: the earliest time in ms to fetch orders for
1219
1242
  :param int [limit]: the maximum number of order structures to retrieve
1220
1243
  :param dict [params]: extra parameters specific to the exchange API endpoint
1221
- :returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
1244
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1222
1245
  """
1223
1246
  await self.load_markets()
1224
1247
  method = 'watchOrders'
@@ -189,7 +189,7 @@ class coinbaseexchange(ccxt.async_support.coinbaseexchange):
189
189
  :param int [since]: the earliest time in ms to fetch trades for
190
190
  :param int [limit]: the maximum number of trade structures to retrieve
191
191
  :param dict [params]: extra parameters specific to the exchange API endpoint
192
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
192
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
193
193
  """
194
194
  if symbol is None:
195
195
  raise ArgumentsRequired(self.id + ' watchMyTrades() requires a symbol argument')
@@ -210,7 +210,7 @@ class coinbaseexchange(ccxt.async_support.coinbaseexchange):
210
210
  :param int [since]: the earliest time in ms to fetch trades for
211
211
  :param int [limit]: the maximum number of trade structures to retrieve
212
212
  :param dict [params]: extra parameters specific to the exchange API endpoint
213
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
213
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
214
214
  """
215
215
  symbols = self.market_symbols(symbols, None, False)
216
216
  await self.load_markets()
ccxt/pro/coincheck.py CHANGED
@@ -111,7 +111,7 @@ class coincheck(ccxt.async_support.coincheck):
111
111
  :param int [since]: the earliest time in ms to fetch trades for
112
112
  :param int [limit]: the maximum number of trade structures to retrieve
113
113
  :param dict [params]: extra parameters specific to the exchange API endpoint
114
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
114
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
115
115
  """
116
116
  await self.load_markets()
117
117
  market = self.market(symbol)
ccxt/pro/coinone.py CHANGED
@@ -252,7 +252,7 @@ class coinone(ccxt.async_support.coinone):
252
252
  :param int [since]: the earliest time in ms to fetch trades for
253
253
  :param int [limit]: the maximum number of trade structures to retrieve
254
254
  :param dict [params]: extra parameters specific to the exchange API endpoint
255
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
255
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
256
256
  """
257
257
  await self.load_markets()
258
258
  market = self.market(symbol)