ccxt 4.5.0__py2.py3-none-any.whl → 4.5.2__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 (64) hide show
  1. ccxt/__init__.py +1 -5
  2. ccxt/ascendex.py +1 -1
  3. ccxt/async_support/__init__.py +1 -5
  4. ccxt/async_support/ascendex.py +1 -1
  5. ccxt/async_support/base/exchange.py +1 -1
  6. ccxt/async_support/binance.py +17 -12
  7. ccxt/async_support/bitget.py +1 -1
  8. ccxt/async_support/coinbase.py +46 -34
  9. ccxt/async_support/gate.py +31 -17
  10. ccxt/async_support/gemini.py +1 -1
  11. ccxt/async_support/hibachi.py +1 -1
  12. ccxt/async_support/hyperliquid.py +13 -2
  13. ccxt/async_support/indodax.py +11 -12
  14. ccxt/async_support/kraken.py +1 -8
  15. ccxt/async_support/krakenfutures.py +25 -25
  16. ccxt/async_support/mexc.py +2 -1
  17. ccxt/async_support/okx.py +2 -2
  18. ccxt/async_support/poloniex.py +1 -1
  19. ccxt/async_support/timex.py +35 -0
  20. ccxt/async_support/tradeogre.py +32 -0
  21. ccxt/async_support/wavesexchange.py +33 -0
  22. ccxt/async_support/zonda.py +12 -0
  23. ccxt/base/exchange.py +7 -1
  24. ccxt/binance.py +17 -12
  25. ccxt/bitget.py +1 -1
  26. ccxt/coinbase.py +46 -34
  27. ccxt/gate.py +31 -17
  28. ccxt/gemini.py +1 -1
  29. ccxt/hibachi.py +1 -1
  30. ccxt/hyperliquid.py +13 -2
  31. ccxt/indodax.py +11 -12
  32. ccxt/kraken.py +1 -8
  33. ccxt/krakenfutures.py +25 -25
  34. ccxt/mexc.py +2 -1
  35. ccxt/okx.py +2 -2
  36. ccxt/poloniex.py +1 -1
  37. ccxt/pro/__init__.py +1 -3
  38. ccxt/pro/bitget.py +328 -75
  39. ccxt/pro/bitmart.py +1 -1
  40. ccxt/pro/bybit.py +8 -10
  41. ccxt/pro/gate.py +8 -1
  42. ccxt/pro/gemini.py +6 -2
  43. ccxt/pro/hyperliquid.py +6 -0
  44. ccxt/pro/kraken.py +4 -6
  45. ccxt/pro/lbank.py +56 -2
  46. ccxt/pro/mexc.py +1 -1
  47. ccxt/test/tests_async.py +2 -25
  48. ccxt/test/tests_sync.py +2 -25
  49. ccxt/timex.py +35 -0
  50. ccxt/tradeogre.py +32 -0
  51. ccxt/wavesexchange.py +33 -0
  52. ccxt/zonda.py +12 -0
  53. {ccxt-4.5.0.dist-info → ccxt-4.5.2.dist-info}/METADATA +111 -113
  54. {ccxt-4.5.0.dist-info → ccxt-4.5.2.dist-info}/RECORD +57 -64
  55. ccxt/abstract/ellipx.py +0 -25
  56. ccxt/abstract/vertex.py +0 -19
  57. ccxt/async_support/ellipx.py +0 -2029
  58. ccxt/async_support/vertex.py +0 -3050
  59. ccxt/ellipx.py +0 -2029
  60. ccxt/pro/vertex.py +0 -948
  61. ccxt/vertex.py +0 -3050
  62. {ccxt-4.5.0.dist-info → ccxt-4.5.2.dist-info}/LICENSE.txt +0 -0
  63. {ccxt-4.5.0.dist-info → ccxt-4.5.2.dist-info}/WHEEL +0 -0
  64. {ccxt-4.5.0.dist-info → ccxt-4.5.2.dist-info}/top_level.txt +0 -0
ccxt/pro/bitget.py CHANGED
@@ -51,10 +51,14 @@ class bitget(ccxt.async_support.bitget):
51
51
  'ws': {
52
52
  'public': 'wss://ws.bitget.com/v2/ws/public',
53
53
  'private': 'wss://ws.bitget.com/v2/ws/private',
54
+ 'utaPublic': 'wss://ws.bitget.com/v3/ws/public',
55
+ 'utaPrivate': 'wss://ws.bitget.com/v3/ws/private',
54
56
  },
55
57
  'demo': {
56
58
  'public': 'wss://wspap.bitget.com/v2/ws/public',
57
59
  'private': 'wss://wspap.bitget.com/v2/ws/private',
60
+ 'utaPublic': 'wss://wspap.bitget.com/v3/ws/public',
61
+ 'utaPrivate': 'wss://wspap.bitget.com/v3/ws/private',
58
62
  },
59
63
  },
60
64
  },
@@ -64,6 +68,7 @@ class bitget(ccxt.async_support.bitget):
64
68
  # WS timeframes differ from REST timeframes
65
69
  'timeframes': {
66
70
  '1m': '1m',
71
+ '3m': '3m',
67
72
  '5m': '5m',
68
73
  '15m': '15m',
69
74
  '30m': '30m',
@@ -106,7 +111,9 @@ class bitget(ccxt.async_support.bitget):
106
111
  },
107
112
  })
108
113
 
109
- def get_inst_type(self, market, params={}):
114
+ def get_inst_type(self, market, uta: bool = False, params={}):
115
+ if (uta is None) or not uta:
116
+ uta, params = self.handle_option_and_params(params, 'getInstType', 'uta', False)
110
117
  instType = None
111
118
  if market is None:
112
119
  instType, params = self.handleProductTypeAndParams(None, params)
@@ -117,6 +124,8 @@ class bitget(ccxt.async_support.bitget):
117
124
  instypeAux = None
118
125
  instypeAux, params = self.handle_option_and_params(params, 'getInstType', 'instType', instType)
119
126
  instType = instypeAux
127
+ if uta:
128
+ instType = instType.lower()
120
129
  return [instType, params]
121
130
 
122
131
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
@@ -125,9 +134,11 @@ class bitget(ccxt.async_support.bitget):
125
134
 
126
135
  https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
127
136
  https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
137
+ https://www.bitget.com/api-doc/uta/websocket/public/Tickers-Channel
128
138
 
129
139
  :param str symbol: unified symbol of the market to watch the ticker for
130
140
  :param dict [params]: extra parameters specific to the exchange API endpoint
141
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
131
142
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
132
143
  """
133
144
  await self.load_markets()
@@ -135,12 +146,16 @@ class bitget(ccxt.async_support.bitget):
135
146
  symbol = market['symbol']
136
147
  messageHash = 'ticker:' + symbol
137
148
  instType = None
138
- instType, params = self.get_inst_type(market, params)
149
+ uta = None
150
+ uta, params = self.handle_option_and_params(params, 'watchTicker', 'uta', False)
151
+ instType, params = self.get_inst_type(market, uta, params)
139
152
  args: dict = {
140
153
  'instType': instType,
141
- 'channel': 'ticker',
142
- 'instId': market['id'],
143
154
  }
155
+ topicOrChannel = 'topic' if uta else 'channel'
156
+ symbolOrInstId = 'symbol' if uta else 'instId'
157
+ args[topicOrChannel] = 'ticker'
158
+ args[symbolOrInstId] = market['id']
144
159
  return await self.watch_public(messageHash, args, params)
145
160
 
146
161
  async def un_watch_ticker(self, symbol: str, params={}) -> Any:
@@ -163,16 +178,20 @@ class bitget(ccxt.async_support.bitget):
163
178
 
164
179
  https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
165
180
  https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
181
+ https://www.bitget.com/api-doc/uta/websocket/public/Tickers-Channel
166
182
 
167
183
  :param str[] symbols: unified symbol of the market to watch the tickers for
168
184
  :param dict [params]: extra parameters specific to the exchange API endpoint
185
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
169
186
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
170
187
  """
171
188
  await self.load_markets()
172
189
  symbols = self.market_symbols(symbols, None, False)
173
190
  market = self.market(symbols[0])
174
191
  instType = None
175
- instType, params = self.get_inst_type(market, params)
192
+ uta = None
193
+ uta, params = self.handle_option_and_params(params, 'watchTickers', 'uta', False)
194
+ instType, params = self.get_inst_type(market, uta, params)
176
195
  topics = []
177
196
  messageHashes = []
178
197
  for i in range(0, len(symbols)):
@@ -180,9 +199,11 @@ class bitget(ccxt.async_support.bitget):
180
199
  marketInner = self.market(symbol)
181
200
  args: dict = {
182
201
  'instType': instType,
183
- 'channel': 'ticker',
184
- 'instId': marketInner['id'],
185
202
  }
203
+ topicOrChannel = 'topic' if uta else 'channel'
204
+ symbolOrInstId = 'symbol' if uta else 'instId'
205
+ args[topicOrChannel] = 'ticker'
206
+ args[symbolOrInstId] = marketInner['id']
186
207
  topics.append(args)
187
208
  messageHashes.append('ticker:' + symbol)
188
209
  tickers = await self.watch_public_multiple(messageHashes, topics, params)
@@ -193,6 +214,8 @@ class bitget(ccxt.async_support.bitget):
193
214
  return self.filter_by_array(self.tickers, 'symbol', symbols)
194
215
 
195
216
  def handle_ticker(self, client: Client, message):
217
+ #
218
+ # default
196
219
  #
197
220
  # {
198
221
  # "action": "snapshot",
@@ -223,6 +246,29 @@ class bitget(ccxt.async_support.bitget):
223
246
  # "ts": 1701842994341
224
247
  # }
225
248
  #
249
+ # uta
250
+ #
251
+ # {
252
+ # "action": "snapshot",
253
+ # "arg": {"instType": "spot", topic: "ticker", symbol: "BTCUSDT"},
254
+ # "data": [
255
+ # {
256
+ # "highPrice24h": "120255.61",
257
+ # "lowPrice24h": "116145.88",
258
+ # "openPrice24h": "118919.38",
259
+ # "lastPrice": "119818.83",
260
+ # "turnover24h": "215859996.272276",
261
+ # "volume24h": "1819.756798",
262
+ # "bid1Price": "119811.26",
263
+ # "ask1Price": "119831.18",
264
+ # "bid1Size": "0.008732",
265
+ # "ask1Size": "0.004297",
266
+ # "price24hPcnt": "0.02002"
267
+ # }
268
+ # ],
269
+ # "ts": 1753230479687
270
+ # }
271
+ #
226
272
  self.handle_bid_ask(client, message)
227
273
  ticker = self.parse_ws_ticker(message)
228
274
  symbol = ticker['symbol']
@@ -301,56 +347,85 @@ class bitget(ccxt.async_support.bitget):
301
347
  # "ts": 1701843962812
302
348
  # }
303
349
  #
350
+ # uta
351
+ #
352
+ # {
353
+ # "action": "snapshot",
354
+ # "arg": {"instType": "spot", topic: "ticker", symbol: "BTCUSDT"},
355
+ # "data": [
356
+ # {
357
+ # "highPrice24h": "120255.61",
358
+ # "lowPrice24h": "116145.88",
359
+ # "openPrice24h": "118919.38",
360
+ # "lastPrice": "119818.83",
361
+ # "turnover24h": "215859996.272276",
362
+ # "volume24h": "1819.756798",
363
+ # "bid1Price": "119811.26",
364
+ # "ask1Price": "119831.18",
365
+ # "bid1Size": "0.008732",
366
+ # "ask1Size": "0.004297",
367
+ # "price24hPcnt": "0.02002"
368
+ # }
369
+ # ],
370
+ # "ts": 1753230479687
371
+ # }
372
+ #
304
373
  arg = self.safe_value(message, 'arg', {})
305
374
  data = self.safe_value(message, 'data', [])
306
375
  ticker = self.safe_value(data, 0, {})
307
- timestamp = self.safe_integer(ticker, 'ts')
308
- instType = self.safe_string(arg, 'instType')
309
- marketType = 'spot' if (instType == 'SPOT') else 'contract'
310
- marketId = self.safe_string(ticker, 'instId')
376
+ utaTimestamp = self.safe_integer(message, 'ts')
377
+ timestamp = self.safe_integer(ticker, 'ts', utaTimestamp)
378
+ instType = self.safe_string_lower(arg, 'instType')
379
+ marketType = 'spot' if (instType == 'spot') else 'contract'
380
+ utaMarketId = self.safe_string(arg, 'symbol')
381
+ marketId = self.safe_string(ticker, 'instId', utaMarketId)
311
382
  market = self.safe_market(marketId, market, None, marketType)
312
- close = self.safe_string(ticker, 'lastPr')
313
- changeDecimal = self.safe_string(ticker, 'change24h')
314
- change = Precise.string_mul(changeDecimal, '100')
383
+ close = self.safe_string_2(ticker, 'lastPr', 'lastPrice')
384
+ changeDecimal = self.safe_string(ticker, 'change24h', '')
385
+ change = self.safe_string(ticker, 'price24hPcnt', Precise.string_mul(changeDecimal, '100'))
315
386
  return self.safe_ticker({
316
387
  'symbol': market['symbol'],
317
388
  'timestamp': timestamp,
318
389
  'datetime': self.iso8601(timestamp),
319
- 'high': self.safe_string(ticker, 'high24h'),
320
- 'low': self.safe_string(ticker, 'low24h'),
321
- 'bid': self.safe_string(ticker, 'bidPr'),
322
- 'bidVolume': self.safe_string(ticker, 'bidSz'),
323
- 'ask': self.safe_string(ticker, 'askPr'),
324
- 'askVolume': self.safe_string(ticker, 'askSz'),
390
+ 'high': self.safe_string_2(ticker, 'high24h', 'highPrice24h'),
391
+ 'low': self.safe_string_2(ticker, 'low24h', 'lowPrice24h'),
392
+ 'bid': self.safe_string_2(ticker, 'bidPr', 'bid1Price'),
393
+ 'bidVolume': self.safe_string_2(ticker, 'bidSz', 'bid1Size'),
394
+ 'ask': self.safe_string_2(ticker, 'askPr', 'ask1Price'),
395
+ 'askVolume': self.safe_string_2(ticker, 'askSz', 'ask1Size'),
325
396
  'vwap': None,
326
- 'open': self.safe_string(ticker, 'open24h'),
397
+ 'open': self.safe_string_2(ticker, 'open24h', 'openPrice24h'),
327
398
  'close': close,
328
399
  'last': close,
329
400
  'previousClose': None,
330
401
  'change': None,
331
402
  'percentage': change,
332
403
  'average': None,
333
- 'baseVolume': self.safe_string(ticker, 'baseVolume'),
334
- 'quoteVolume': self.safe_string(ticker, 'quoteVolume'),
404
+ 'baseVolume': self.safe_string_2(ticker, 'baseVolume', 'volume24h'),
405
+ 'quoteVolume': self.safe_string_2(ticker, 'quoteVolume', 'turnover24h'),
335
406
  'info': ticker,
336
407
  }, market)
337
408
 
338
409
  async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
339
410
  """
411
+ watches best bid & ask for symbols
340
412
 
341
413
  https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
342
414
  https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
415
+ https://www.bitget.com/api-doc/uta/websocket/public/Tickers-Channel
343
416
 
344
- watches best bid & ask for symbols
345
417
  :param str[] symbols: unified symbol of the market to fetch the ticker for
346
418
  :param dict [params]: extra parameters specific to the exchange API endpoint
419
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
347
420
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
348
421
  """
349
422
  await self.load_markets()
350
423
  symbols = self.market_symbols(symbols, None, False)
351
424
  market = self.market(symbols[0])
352
425
  instType = None
353
- instType, params = self.get_inst_type(market, params)
426
+ uta = None
427
+ uta, params = self.handle_option_and_params(params, 'watchBidsAsks', 'uta', False)
428
+ instType, params = self.get_inst_type(market, uta, params)
354
429
  topics = []
355
430
  messageHashes = []
356
431
  for i in range(0, len(symbols)):
@@ -358,9 +433,11 @@ class bitget(ccxt.async_support.bitget):
358
433
  marketInner = self.market(symbol)
359
434
  args: dict = {
360
435
  'instType': instType,
361
- 'channel': 'ticker',
362
- 'instId': marketInner['id'],
363
436
  }
437
+ topicOrChannel = 'topic' if uta else 'channel'
438
+ symbolOrInstId = 'symbol' if uta else 'instId'
439
+ args[topicOrChannel] = 'ticker'
440
+ args[symbolOrInstId] = marketInner['id']
364
441
  topics.append(args)
365
442
  messageHashes.append('bidask:' + symbol)
366
443
  tickers = await self.watch_public_multiple(messageHashes, topics, params)
@@ -381,19 +458,21 @@ class bitget(ccxt.async_support.bitget):
381
458
  arg = self.safe_value(message, 'arg', {})
382
459
  data = self.safe_value(message, 'data', [])
383
460
  ticker = self.safe_value(data, 0, {})
384
- timestamp = self.safe_integer(ticker, 'ts')
385
- instType = self.safe_string(arg, 'instType')
386
- marketType = 'spot' if (instType == 'SPOT') else 'contract'
387
- marketId = self.safe_string(ticker, 'instId')
461
+ utaTimestamp = self.safe_integer(message, 'ts')
462
+ timestamp = self.safe_integer(ticker, 'ts', utaTimestamp)
463
+ instType = self.safe_string_lower(arg, 'instType')
464
+ marketType = 'spot' if (instType == 'spot') else 'contract'
465
+ utaMarketId = self.safe_string(arg, 'symbol')
466
+ marketId = self.safe_string(ticker, 'instId', utaMarketId)
388
467
  market = self.safe_market(marketId, market, None, marketType)
389
468
  return self.safe_ticker({
390
469
  'symbol': market['symbol'],
391
470
  'timestamp': timestamp,
392
471
  'datetime': self.iso8601(timestamp),
393
- 'ask': self.safe_string(ticker, 'askPr'),
394
- 'askVolume': self.safe_string(ticker, 'askSz'),
395
- 'bid': self.safe_string(ticker, 'bidPr'),
396
- 'bidVolume': self.safe_string(ticker, 'bidSz'),
472
+ 'ask': self.safe_string_2(ticker, 'askPr', 'ask1Price'),
473
+ 'askVolume': self.safe_string_2(ticker, 'askSz', 'ask1Size'),
474
+ 'bid': self.safe_string_2(ticker, 'bidPr', 'bid1Price'),
475
+ 'bidVolume': self.safe_string_2(ticker, 'bidSz', 'bid1Size'),
397
476
  'info': ticker,
398
477
  }, market)
399
478
 
@@ -403,12 +482,14 @@ class bitget(ccxt.async_support.bitget):
403
482
 
404
483
  https://www.bitget.com/api-doc/spot/websocket/public/Candlesticks-Channel
405
484
  https://www.bitget.com/api-doc/contract/websocket/public/Candlesticks-Channel
485
+ https://www.bitget.com/api-doc/uta/websocket/public/Candlesticks-Channel
406
486
 
407
487
  :param str symbol: unified symbol of the market to fetch OHLCV data for
408
488
  :param str timeframe: the length of time each candle represents
409
489
  :param int [since]: timestamp in ms of the earliest candle to fetch
410
490
  :param int [limit]: the maximum amount of candles to fetch
411
491
  :param dict [params]: extra parameters specific to the exchange API endpoint
492
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
412
493
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
413
494
  """
414
495
  await self.load_markets()
@@ -416,14 +497,24 @@ class bitget(ccxt.async_support.bitget):
416
497
  symbol = market['symbol']
417
498
  timeframes = self.safe_value(self.options, 'timeframes')
418
499
  interval = self.safe_string(timeframes, timeframe)
419
- messageHash = 'candles:' + timeframe + ':' + symbol
500
+ messageHash = None
420
501
  instType = None
421
- instType, params = self.get_inst_type(market, params)
502
+ uta = None
503
+ uta, params = self.handle_option_and_params(params, 'watchOHLCV', 'uta', False)
504
+ instType, params = self.get_inst_type(market, uta, params)
422
505
  args: dict = {
423
506
  'instType': instType,
424
- 'channel': 'candle' + interval,
425
- 'instId': market['id'],
426
507
  }
508
+ if uta:
509
+ args['topic'] = 'kline'
510
+ args['symbol'] = market['id']
511
+ args['interval'] = interval
512
+ params['uta'] = True
513
+ messageHash = 'kline:' + symbol
514
+ else:
515
+ args['channel'] = 'candle' + interval
516
+ args['instId'] = market['id']
517
+ messageHash = 'candles:' + timeframe + ':' + symbol
427
518
  ohlcv = await self.watch_public(messageHash, args, params)
428
519
  if self.newUpdates:
429
520
  limit = ohlcv.getLimit(symbol, limit)
@@ -435,17 +526,43 @@ class bitget(ccxt.async_support.bitget):
435
526
 
436
527
  https://www.bitget.com/api-doc/spot/websocket/public/Candlesticks-Channel
437
528
  https://www.bitget.com/api-doc/contract/websocket/public/Candlesticks-Channel
529
+ https://www.bitget.com/api-doc/uta/websocket/public/Candlesticks-Channel
438
530
 
439
531
  :param str symbol: unified symbol of the market to unwatch the ohlcv for
440
532
  :param str [timeframe]: the period for the ratio, default is 1 minute
441
533
  :param dict [params]: extra parameters specific to the exchange API endpoint
534
+ :param boolean [params.uta]: set to True for the unified trading account(uta), defaults to False
442
535
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
443
536
  """
444
537
  await self.load_markets()
445
538
  timeframes = self.safe_dict(self.options, 'timeframes')
446
539
  interval = self.safe_string(timeframes, timeframe)
447
- channel = 'candle' + interval
448
- return await self.un_watch_channel(symbol, channel, 'candles:' + timeframe, params)
540
+ channel = None
541
+ market = None
542
+ if symbol is not None:
543
+ market = self.market(symbol)
544
+ instType = None
545
+ messageHash = None
546
+ uta = None
547
+ uta, params = self.handle_option_and_params(params, 'unWatchOHLCV', 'uta', False)
548
+ instType, params = self.get_inst_type(market, uta, params)
549
+ args: dict = {
550
+ 'instType': instType,
551
+ }
552
+ if uta:
553
+ channel = 'kline'
554
+ args['topic'] = channel
555
+ args['symbol'] = market['id']
556
+ args['interval'] = interval
557
+ params['uta'] = True
558
+ params['interval'] = interval
559
+ messageHash = channel + symbol
560
+ else:
561
+ channel = 'candle' + interval
562
+ args['channel'] = channel
563
+ args['instId'] = market['id']
564
+ messageHash = 'candles:' + interval
565
+ return await self.un_watch_channel(symbol, channel, messageHash, params)
449
566
 
450
567
  def handle_ohlcv(self, client: Client, message):
451
568
  #
@@ -481,15 +598,45 @@ class bitget(ccxt.async_support.bitget):
481
598
  # "ts": 1701901610417
482
599
  # }
483
600
  #
601
+ # uta
602
+ #
603
+ # {
604
+ # "action": "snapshot",
605
+ # "arg": {
606
+ # "instType": "usdt-futures",
607
+ # "topic": "kline",
608
+ # "symbol": "BTCUSDT",
609
+ # "interval": "1m"
610
+ # },
611
+ # "data": [
612
+ # {
613
+ # "start": "1755564480000",
614
+ # "open": "116286",
615
+ # "close": "116256.2",
616
+ # "high": "116310.2",
617
+ # "low": "116232.8",
618
+ # "volume": "39.7062",
619
+ # "turnover": "4616746.46654"
620
+ # },
621
+ # ],
622
+ # "ts": 1755594421877
623
+ # }
624
+ #
484
625
  arg = self.safe_value(message, 'arg', {})
485
- instType = self.safe_string(arg, 'instType')
486
- marketType = 'spot' if (instType == 'SPOT') else 'contract'
487
- marketId = self.safe_string(arg, 'instId')
626
+ instType = self.safe_string_lower(arg, 'instType')
627
+ marketType = 'spot' if (instType == 'spot') else 'contract'
628
+ marketId = self.safe_string_2(arg, 'instId', 'symbol')
488
629
  market = self.safe_market(marketId, None, None, marketType)
489
630
  symbol = market['symbol']
490
631
  self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
491
- channel = self.safe_string(arg, 'channel')
492
- interval = channel.replace('candle', '')
632
+ channel = self.safe_string_2(arg, 'channel', 'topic')
633
+ interval = self.safe_string(arg, 'interval')
634
+ isUta = None
635
+ if interval is None:
636
+ isUta = False
637
+ interval = channel.replace('candle', '')
638
+ else:
639
+ isUta = True
493
640
  timeframes = self.safe_value(self.options, 'timeframes')
494
641
  timeframe = self.find_timeframe(interval, timeframes)
495
642
  stored = self.safe_value(self.ohlcvs[symbol], timeframe)
@@ -501,7 +648,11 @@ class bitget(ccxt.async_support.bitget):
501
648
  for i in range(0, len(data)):
502
649
  parsed = self.parse_ws_ohlcv(data[i], market)
503
650
  stored.append(parsed)
504
- messageHash = 'candles:' + timeframe + ':' + symbol
651
+ messageHash = None
652
+ if isUta:
653
+ messageHash = 'kline:' + symbol
654
+ else:
655
+ messageHash = 'candles:' + timeframe + ':' + symbol
505
656
  client.resolve(stored, messageHash)
506
657
 
507
658
  def parse_ws_ohlcv(self, ohlcv, market=None) -> list:
@@ -517,14 +668,26 @@ class bitget(ccxt.async_support.bitget):
517
668
  # "437404.105512" # USDT volume
518
669
  # ]
519
670
  #
671
+ # uta
672
+ #
673
+ # {
674
+ # "start": "1755564480000",
675
+ # "open": "116286",
676
+ # "close": "116256.2",
677
+ # "high": "116310.2",
678
+ # "low": "116232.8",
679
+ # "volume": "39.7062",
680
+ # "turnover": "4616746.46654"
681
+ # }
682
+ #
520
683
  volumeIndex = 6 if (market['inverse']) else 5
521
684
  return [
522
- self.safe_integer(ohlcv, 0),
523
- self.safe_number(ohlcv, 1),
524
- self.safe_number(ohlcv, 2),
525
- self.safe_number(ohlcv, 3),
526
- self.safe_number(ohlcv, 4),
527
- self.safe_number(ohlcv, volumeIndex),
685
+ self.safe_integer_2(ohlcv, 'start', 0),
686
+ self.safe_number_2(ohlcv, 'open', 1),
687
+ self.safe_number_2(ohlcv, 'high', 2),
688
+ self.safe_number_2(ohlcv, 'low', 3),
689
+ self.safe_number_2(ohlcv, 'close', 4),
690
+ self.safe_number_2(ohlcv, 'volume', volumeIndex),
528
691
  ]
529
692
 
530
693
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
@@ -566,12 +729,21 @@ class bitget(ccxt.async_support.bitget):
566
729
  market = self.market(symbol)
567
730
  messageHash = 'unsubscribe:' + messageHashTopic + ':' + market['symbol']
568
731
  instType = None
569
- instType, params = self.get_inst_type(market, params)
732
+ uta = None
733
+ uta, params = self.handle_option_and_params(params, 'unWatchChannel', 'uta', False)
734
+ instType, params = self.get_inst_type(market, uta, params)
570
735
  args: dict = {
571
736
  'instType': instType,
572
- 'channel': channel,
573
- 'instId': market['id'],
574
737
  }
738
+ if uta:
739
+ args['topic'] = channel
740
+ args['symbol'] = market['id']
741
+ args['interval'] = self.safe_string(params, 'interval', '1m')
742
+ params['uta'] = True
743
+ params = self.omit(params, 'interval')
744
+ else:
745
+ args['channel'] = channel
746
+ args['instId'] = market['id']
575
747
  return await self.un_watch_public(messageHash, args, params)
576
748
 
577
749
  async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
@@ -599,7 +771,7 @@ class bitget(ccxt.async_support.bitget):
599
771
  symbol = symbols[i]
600
772
  market = self.market(symbol)
601
773
  instType = None
602
- instType, params = self.get_inst_type(market, params)
774
+ instType, params = self.get_inst_type(market, False, params)
603
775
  args: dict = {
604
776
  'instType': instType,
605
777
  'channel': channel,
@@ -757,7 +929,7 @@ class bitget(ccxt.async_support.bitget):
757
929
  symbol = symbols[i]
758
930
  market = self.market(symbol)
759
931
  instType = None
760
- instType, params = self.get_inst_type(market, params)
932
+ instType, params = self.get_inst_type(market, False, params)
761
933
  args: dict = {
762
934
  'instType': instType,
763
935
  'channel': 'trade',
@@ -941,7 +1113,7 @@ class bitget(ccxt.async_support.bitget):
941
1113
  symbols = self.market_symbols(symbols)
942
1114
  if not self.is_empty(symbols):
943
1115
  market = self.get_market_from_symbols(symbols)
944
- instType, params = self.get_inst_type(market, params)
1116
+ instType, params = self.get_inst_type(market, False, params)
945
1117
  messageHash = instType + ':positions' + messageHash
946
1118
  args: dict = {
947
1119
  'instType': instType,
@@ -1136,7 +1308,7 @@ class bitget(ccxt.async_support.bitget):
1136
1308
  if market is None and type == 'spot':
1137
1309
  instType = 'SPOT'
1138
1310
  else:
1139
- instType, params = self.get_inst_type(market, params)
1311
+ instType, params = self.get_inst_type(market, False, params)
1140
1312
  if type == 'spot' and (symbol is not None):
1141
1313
  subscriptionHash = subscriptionHash + ':' + symbol
1142
1314
  if isTrigger:
@@ -1487,7 +1659,7 @@ class bitget(ccxt.async_support.bitget):
1487
1659
  if market is None and type == 'spot':
1488
1660
  instType = 'spot'
1489
1661
  else:
1490
- instType, params = self.get_inst_type(market, params)
1662
+ instType, params = self.get_inst_type(market, False, params)
1491
1663
  subscriptionHash = 'fill:' + instType
1492
1664
  args: dict = {
1493
1665
  'instType': instType,
@@ -1708,12 +1880,21 @@ class bitget(ccxt.async_support.bitget):
1708
1880
  client.resolve(self.balance, messageHash)
1709
1881
 
1710
1882
  async def watch_public(self, messageHash, args, params={}):
1711
- url = self.urls['api']['ws']['public']
1883
+ uta = None
1884
+ url = None
1885
+ uta, params = self.handle_option_and_params(params, 'watchPublic', 'uta', False)
1886
+ if uta:
1887
+ url = self.urls['api']['ws']['utaPublic']
1888
+ else:
1889
+ url = self.urls['api']['ws']['public']
1712
1890
  sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1713
1891
  if sandboxMode:
1714
1892
  instType = self.safe_string(args, 'instType')
1715
1893
  if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1716
- url = self.urls['api']['demo']['public']
1894
+ if uta:
1895
+ url = self.urls['api']['demo']['utaPublic']
1896
+ else:
1897
+ url = self.urls['api']['demo']['public']
1717
1898
  request: dict = {
1718
1899
  'op': 'subscribe',
1719
1900
  'args': [args],
@@ -1722,12 +1903,21 @@ class bitget(ccxt.async_support.bitget):
1722
1903
  return await self.watch(url, messageHash, message, messageHash)
1723
1904
 
1724
1905
  async def un_watch_public(self, messageHash, args, params={}):
1725
- url = self.urls['api']['ws']['public']
1906
+ uta = None
1907
+ url = None
1908
+ uta, params = self.handle_option_and_params(params, 'unWatchPublic', 'uta', False)
1909
+ if uta:
1910
+ url = self.urls['api']['ws']['utaPublic']
1911
+ else:
1912
+ url = self.urls['api']['ws']['public']
1726
1913
  sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1727
1914
  if sandboxMode:
1728
1915
  instType = self.safe_string(args, 'instType')
1729
1916
  if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1730
- url = self.urls['api']['demo']['public']
1917
+ if uta:
1918
+ url = self.urls['api']['demo']['utaPublic']
1919
+ else:
1920
+ url = self.urls['api']['demo']['public']
1731
1921
  request: dict = {
1732
1922
  'op': 'unsubscribe',
1733
1923
  'args': [args],
@@ -1736,13 +1926,22 @@ class bitget(ccxt.async_support.bitget):
1736
1926
  return await self.watch(url, messageHash, message, messageHash)
1737
1927
 
1738
1928
  async def watch_public_multiple(self, messageHashes, argsArray, params={}):
1739
- url = self.urls['api']['ws']['public']
1929
+ uta = None
1930
+ url = None
1931
+ uta, params = self.handle_option_and_params(params, 'watchPublicMultiple', 'uta', False)
1932
+ if uta:
1933
+ url = self.urls['api']['ws']['utaPublic']
1934
+ else:
1935
+ url = self.urls['api']['ws']['public']
1740
1936
  sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1741
1937
  if sandboxMode:
1742
1938
  argsArrayFirst = self.safe_dict(argsArray, 0, {})
1743
1939
  instType = self.safe_string(argsArrayFirst, 'instType')
1744
1940
  if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1745
- url = self.urls['api']['demo']['public']
1941
+ if uta:
1942
+ url = self.urls['api']['demo']['utaPublic']
1943
+ else:
1944
+ url = self.urls['api']['demo']['public']
1746
1945
  request: dict = {
1747
1946
  'op': 'subscribe',
1748
1947
  'args': argsArray,
@@ -1871,6 +2070,41 @@ class bitget(ccxt.async_support.bitget):
1871
2070
  # ]
1872
2071
  # }
1873
2072
  #
2073
+ # uta
2074
+ #
2075
+ # {
2076
+ # "action": "snapshot",
2077
+ # "arg": {"instType": "spot", topic: "ticker", symbol: "BTCUSDT"},
2078
+ # "data": [
2079
+ # {
2080
+ # "highPrice24h": "120255.61",
2081
+ # "lowPrice24h": "116145.88",
2082
+ # "openPrice24h": "118919.38",
2083
+ # "lastPrice": "119818.83",
2084
+ # "turnover24h": "215859996.272276",
2085
+ # "volume24h": "1819.756798",
2086
+ # "bid1Price": "119811.26",
2087
+ # "ask1Price": "119831.18",
2088
+ # "bid1Size": "0.008732",
2089
+ # "ask1Size": "0.004297",
2090
+ # "price24hPcnt": "0.02002"
2091
+ # }
2092
+ # ],
2093
+ # "ts": 1753230479687
2094
+ # }
2095
+ #
2096
+ # unsubscribe
2097
+ #
2098
+ # {
2099
+ # "event": "unsubscribe",
2100
+ # "arg": {
2101
+ # "instType": "spot",
2102
+ # "topic": "kline",
2103
+ # "symbol": "BTCUSDT",
2104
+ # "interval": "1m"
2105
+ # }
2106
+ # }
2107
+ #
1874
2108
  if self.handle_error_message(client, message):
1875
2109
  return
1876
2110
  content = self.safe_string(message, 'message')
@@ -1903,9 +2137,10 @@ class bitget(ccxt.async_support.bitget):
1903
2137
  'positions': self.handle_positions,
1904
2138
  'account-isolated': self.handle_balance,
1905
2139
  'account-crossed': self.handle_balance,
2140
+ 'kline': self.handle_ohlcv,
1906
2141
  }
1907
2142
  arg = self.safe_value(message, 'arg', {})
1908
- topic = self.safe_value(arg, 'channel', '')
2143
+ topic = self.safe_value_2(arg, 'channel', 'topic', '')
1909
2144
  method = self.safe_value(methods, topic)
1910
2145
  if method is not None:
1911
2146
  method(client, message)
@@ -1981,7 +2216,7 @@ class bitget(ccxt.async_support.bitget):
1981
2216
  arg = self.safe_dict(message, 'arg', {})
1982
2217
  instType = self.safe_string_lower(arg, 'instType')
1983
2218
  type = 'spot' if (instType == 'spot') else 'contract'
1984
- instId = self.safe_string(arg, 'instId')
2219
+ instId = self.safe_string_2(arg, 'instId', 'symbol')
1985
2220
  market = self.safe_market(instId, None, None, type)
1986
2221
  symbol = market['symbol']
1987
2222
  messageHash = 'unsubscribe:ticker:' + market['symbol']
@@ -2000,18 +2235,34 @@ class bitget(ccxt.async_support.bitget):
2000
2235
  #
2001
2236
  # {"event":"unsubscribe","arg":{"instType":"SPOT","channel":"candle1m","instId":"BTCUSDT"}}
2002
2237
  #
2238
+ # UTA
2239
+ #
2240
+ # {"event":"unsubscribe","arg":{"instType":"spot","topic":"kline","symbol":"BTCUSDT","interval":"1m"}}
2241
+ #
2003
2242
  arg = self.safe_dict(message, 'arg', {})
2004
2243
  instType = self.safe_string_lower(arg, 'instType')
2005
2244
  type = 'spot' if (instType == 'spot') else 'contract'
2006
- instId = self.safe_string(arg, 'instId')
2007
- channel = self.safe_string(arg, 'channel')
2008
- interval = channel.replace('candle', '')
2245
+ instId = self.safe_string_2(arg, 'instId', 'symbol')
2246
+ channel = self.safe_string_2(arg, 'channel', 'topic')
2247
+ interval = self.safe_string(arg, 'interval')
2248
+ isUta = None
2249
+ if interval is None:
2250
+ isUta = False
2251
+ interval = channel.replace('candle', '')
2252
+ else:
2253
+ isUta = True
2009
2254
  timeframes = self.safe_value(self.options, 'timeframes')
2010
2255
  timeframe = self.find_timeframe(interval, timeframes)
2011
2256
  market = self.safe_market(instId, None, None, type)
2012
2257
  symbol = market['symbol']
2013
- messageHash = 'unsubscribe:candles:' + timeframe + ':' + market['symbol']
2014
- subMessageHash = 'candles:' + timeframe + ':' + symbol
2258
+ messageHash = None
2259
+ subMessageHash = None
2260
+ if isUta:
2261
+ messageHash = 'unsubscribe:kline:' + symbol
2262
+ subMessageHash = 'kline:' + symbol
2263
+ else:
2264
+ messageHash = 'unsubscribe:candles:' + timeframe + ':' + symbol
2265
+ subMessageHash = 'candles:' + timeframe + ':' + symbol
2015
2266
  if symbol in self.ohlcvs:
2016
2267
  if timeframe in self.ohlcvs[symbol]:
2017
2268
  del self.ohlcvs[symbol][timeframe]
@@ -2042,7 +2293,7 @@ class bitget(ccxt.async_support.bitget):
2042
2293
  argsList = [self.safe_dict(message, 'arg', {})]
2043
2294
  for i in range(0, len(argsList)):
2044
2295
  arg = argsList[i]
2045
- channel = self.safe_string(arg, 'channel')
2296
+ channel = self.safe_string_2(arg, 'channel', 'topic')
2046
2297
  if channel == 'books':
2047
2298
  # for now only unWatchOrderBook is supporteod
2048
2299
  self.handle_order_book_un_subscription(client, message)
@@ -2052,4 +2303,6 @@ class bitget(ccxt.async_support.bitget):
2052
2303
  self.handle_ticker_un_subscription(client, message)
2053
2304
  elif channel.startswith('candle'):
2054
2305
  self.handle_ohlcv_un_subscription(client, message)
2306
+ elif channel.startswith('kline'):
2307
+ self.handle_ohlcv_un_subscription(client, message)
2055
2308
  return message