ccxt 4.3.88__py2.py3-none-any.whl → 4.3.90__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 (105) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/ace.py +1 -0
  3. ccxt/alpaca.py +3 -2
  4. ccxt/ascendex.py +102 -116
  5. ccxt/async_support/__init__.py +1 -1
  6. ccxt/async_support/ace.py +1 -0
  7. ccxt/async_support/alpaca.py +3 -2
  8. ccxt/async_support/ascendex.py +102 -116
  9. ccxt/async_support/base/exchange.py +1 -1
  10. ccxt/async_support/bigone.py +1 -0
  11. ccxt/async_support/bingx.py +30 -17
  12. ccxt/async_support/bit2c.py +1 -0
  13. ccxt/async_support/bitbank.py +1 -0
  14. ccxt/async_support/bitfinex.py +1 -0
  15. ccxt/async_support/bitfinex2.py +21 -22
  16. ccxt/async_support/bitflyer.py +1 -0
  17. ccxt/async_support/bitget.py +3 -2
  18. ccxt/async_support/bitmart.py +4 -8
  19. ccxt/async_support/bitmex.py +1 -0
  20. ccxt/async_support/bitopro.py +1 -0
  21. ccxt/async_support/bitrue.py +62 -71
  22. ccxt/async_support/bitso.py +1 -0
  23. ccxt/async_support/bitstamp.py +1 -0
  24. ccxt/async_support/bitvavo.py +1 -0
  25. ccxt/async_support/blockchaincom.py +1 -0
  26. ccxt/async_support/btcalpha.py +1 -0
  27. ccxt/async_support/btcbox.py +1 -0
  28. ccxt/async_support/btcmarkets.py +1 -0
  29. ccxt/async_support/bybit.py +2 -0
  30. ccxt/async_support/cex.py +1 -0
  31. ccxt/async_support/coinbaseexchange.py +1 -0
  32. ccxt/async_support/coinbaseinternational.py +2 -1
  33. ccxt/async_support/coinex.py +1 -16
  34. ccxt/async_support/cryptocom.py +0 -12
  35. ccxt/async_support/hitbtc.py +1 -0
  36. ccxt/async_support/huobijp.py +0 -8
  37. ccxt/async_support/kraken.py +48 -48
  38. ccxt/async_support/latoken.py +1 -0
  39. ccxt/async_support/mexc.py +1 -61
  40. ccxt/async_support/okcoin.py +4 -9
  41. ccxt/async_support/okx.py +1 -8
  42. ccxt/async_support/onetrading.py +1 -0
  43. ccxt/async_support/phemex.py +1 -0
  44. ccxt/async_support/poloniexfutures.py +1 -0
  45. ccxt/async_support/probit.py +1 -0
  46. ccxt/async_support/vertex.py +1 -0
  47. ccxt/async_support/whitebit.py +5 -3
  48. ccxt/async_support/woo.py +1 -0
  49. ccxt/async_support/woofipro.py +1 -0
  50. ccxt/base/exchange.py +6 -4
  51. ccxt/bigone.py +1 -0
  52. ccxt/bingx.py +30 -17
  53. ccxt/bit2c.py +1 -0
  54. ccxt/bitbank.py +1 -0
  55. ccxt/bitfinex.py +1 -0
  56. ccxt/bitfinex2.py +21 -22
  57. ccxt/bitflyer.py +1 -0
  58. ccxt/bitget.py +3 -2
  59. ccxt/bitmart.py +4 -8
  60. ccxt/bitmex.py +1 -0
  61. ccxt/bitopro.py +1 -0
  62. ccxt/bitrue.py +62 -71
  63. ccxt/bitso.py +1 -0
  64. ccxt/bitstamp.py +1 -0
  65. ccxt/bitvavo.py +1 -0
  66. ccxt/blockchaincom.py +1 -0
  67. ccxt/btcalpha.py +1 -0
  68. ccxt/btcbox.py +1 -0
  69. ccxt/btcmarkets.py +1 -0
  70. ccxt/bybit.py +2 -0
  71. ccxt/cex.py +1 -0
  72. ccxt/coinbaseexchange.py +1 -0
  73. ccxt/coinbaseinternational.py +2 -1
  74. ccxt/coinex.py +1 -16
  75. ccxt/cryptocom.py +0 -12
  76. ccxt/hitbtc.py +1 -0
  77. ccxt/huobijp.py +0 -8
  78. ccxt/kraken.py +48 -48
  79. ccxt/latoken.py +1 -0
  80. ccxt/mexc.py +1 -61
  81. ccxt/okcoin.py +4 -9
  82. ccxt/okx.py +1 -8
  83. ccxt/onetrading.py +1 -0
  84. ccxt/phemex.py +1 -0
  85. ccxt/poloniexfutures.py +1 -0
  86. ccxt/pro/__init__.py +1 -1
  87. ccxt/pro/binance.py +280 -0
  88. ccxt/pro/bingx.py +235 -85
  89. ccxt/pro/bithumb.py +4 -0
  90. ccxt/pro/bitvavo.py +1 -0
  91. ccxt/pro/bybit.py +253 -2
  92. ccxt/pro/cex.py +1 -0
  93. ccxt/pro/coinex.py +941 -662
  94. ccxt/pro/lbank.py +1 -2
  95. ccxt/pro/okx.py +142 -2
  96. ccxt/probit.py +1 -0
  97. ccxt/vertex.py +1 -0
  98. ccxt/whitebit.py +5 -3
  99. ccxt/woo.py +1 -0
  100. ccxt/woofipro.py +1 -0
  101. {ccxt-4.3.88.dist-info → ccxt-4.3.90.dist-info}/METADATA +4 -4
  102. {ccxt-4.3.88.dist-info → ccxt-4.3.90.dist-info}/RECORD +105 -105
  103. {ccxt-4.3.88.dist-info → ccxt-4.3.90.dist-info}/LICENSE.txt +0 -0
  104. {ccxt-4.3.88.dist-info → ccxt-4.3.90.dist-info}/WHEEL +0 -0
  105. {ccxt-4.3.88.dist-info → ccxt-4.3.90.dist-info}/top_level.txt +0 -0
ccxt/pro/bingx.py CHANGED
@@ -37,7 +37,8 @@ class bingx(ccxt.async_support.bingx):
37
37
  'api': {
38
38
  'ws': {
39
39
  'spot': 'wss://open-api-ws.bingx.com/market',
40
- 'swap': 'wss://open-api-swap.bingx.com/swap-market',
40
+ 'linear': 'wss://open-api-swap.bingx.com/swap-market',
41
+ 'inverse': 'wss://open-api-cswap-ws.bingx.com/market',
41
42
  },
42
43
  },
43
44
  },
@@ -95,17 +96,24 @@ class bingx(ccxt.async_support.bingx):
95
96
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
96
97
  """
97
98
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
99
+ :see: https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#Subscribe%20to%2024-hour%20Price%20Change
98
100
  :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20to%2024-hour%20price%20changes
101
+ :see: https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscribe%20to%2024-Hour%20Price%20Change
99
102
  :param str symbol: unified symbol of the market to fetch the ticker for
100
103
  :param dict [params]: extra parameters specific to the exchange API endpoint
101
104
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
102
105
  """
103
106
  await self.load_markets()
104
107
  market = self.market(symbol)
105
- marketType, query = self.handle_market_type_and_params('watchTicker', market, params)
106
- url = self.safe_value(self.urls['api']['ws'], marketType)
107
- if url is None:
108
- raise BadRequest(self.id + ' watchTicker is not supported for ' + marketType + ' markets.')
108
+ marketType = None
109
+ subType = None
110
+ url = None
111
+ marketType, params = self.handle_market_type_and_params('watchTicker', market, params)
112
+ subType, params = self.handle_sub_type_and_params('watchTicker', market, params, 'linear')
113
+ if marketType == 'swap':
114
+ url = self.safe_string(self.urls['api']['ws'], subType)
115
+ else:
116
+ url = self.safe_string(self.urls['api']['ws'], marketType)
109
117
  subscriptionHash = market['id'] + '@ticker'
110
118
  messageHash = self.get_message_hash('ticker', market['symbol'])
111
119
  uuid = self.uuid()
@@ -115,7 +123,7 @@ class bingx(ccxt.async_support.bingx):
115
123
  }
116
124
  if marketType == 'swap':
117
125
  request['reqType'] = 'sub'
118
- return await self.watch(url, messageHash, self.extend(request, query), subscriptionHash)
126
+ return await self.watch(url, messageHash, self.extend(request, params), subscriptionHash)
119
127
 
120
128
  def handle_ticker(self, client: Client, message):
121
129
  #
@@ -247,12 +255,16 @@ class bingx(ccxt.async_support.bingx):
247
255
  symbols = self.market_symbols(symbols, None, True, True, False)
248
256
  firstMarket = None
249
257
  marketType = None
258
+ subType = None
250
259
  symbolsDefined = (symbols is not None)
251
260
  if symbolsDefined:
252
261
  firstMarket = self.market(symbols[0])
253
262
  marketType, params = self.handle_market_type_and_params('watchTickers', firstMarket, params)
263
+ subType, params = self.handle_sub_type_and_params('watchTickers', firstMarket, params, 'linear')
254
264
  if marketType == 'spot':
255
265
  raise NotSupported(self.id + ' watchTickers is not supported for spot markets yet')
266
+ if subType == 'inverse':
267
+ raise NotSupported(self.id + ' watchTickers is not supported for inverse markets yet')
256
268
  messageHashes = []
257
269
  subscriptionHashes = ['all@ticker']
258
270
  if symbolsDefined:
@@ -262,7 +274,7 @@ class bingx(ccxt.async_support.bingx):
262
274
  messageHashes.append(self.get_message_hash('ticker', market['symbol']))
263
275
  else:
264
276
  messageHashes.append(self.get_message_hash('ticker'))
265
- url = self.safe_string(self.urls['api']['ws'], marketType)
277
+ url = self.safe_string(self.urls['api']['ws'], subType)
266
278
  uuid = self.uuid()
267
279
  request: dict = {
268
280
  'id': uuid,
@@ -289,12 +301,16 @@ class bingx(ccxt.async_support.bingx):
289
301
  symbols = self.market_symbols(symbols, None, True, True, False)
290
302
  firstMarket = None
291
303
  marketType = None
304
+ subType = None
292
305
  symbolsDefined = (symbols is not None)
293
306
  if symbolsDefined:
294
307
  firstMarket = self.market(symbols[0])
295
308
  marketType, params = self.handle_market_type_and_params('watchOrderBookForSymbols', firstMarket, params)
309
+ subType, params = self.handle_sub_type_and_params('watchOrderBookForSymbols', firstMarket, params, 'linear')
296
310
  if marketType == 'spot':
297
311
  raise NotSupported(self.id + ' watchOrderBookForSymbols is not supported for spot markets yet')
312
+ if subType == 'inverse':
313
+ raise NotSupported(self.id + ' watchOrderBookForSymbols is not supported for inverse markets yet')
298
314
  limit = self.get_order_book_limit_by_market_type(marketType, limit)
299
315
  interval = None
300
316
  interval, params = self.handle_option_and_params(params, 'watchOrderBookForSymbols', 'interval', 500)
@@ -309,7 +325,7 @@ class bingx(ccxt.async_support.bingx):
309
325
  messageHashes.append(self.get_message_hash('orderbook', market['symbol']))
310
326
  else:
311
327
  messageHashes.append(self.get_message_hash('orderbook'))
312
- url = self.safe_string(self.urls['api']['ws'], marketType)
328
+ url = self.safe_string(self.urls['api']['ws'], subType)
313
329
  uuid = self.uuid()
314
330
  request: dict = {
315
331
  'id': uuid,
@@ -329,6 +345,7 @@ class bingx(ccxt.async_support.bingx):
329
345
  async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
330
346
  """
331
347
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
348
+ :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20K-Line%20Data%20of%20all%20trading%20pairs
332
349
  :param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
333
350
  :param int [since]: timestamp in ms of the earliest candle to fetch
334
351
  :param int [limit]: the maximum amount of candles to fetch
@@ -341,14 +358,19 @@ class bingx(ccxt.async_support.bingx):
341
358
  await self.load_markets()
342
359
  messageHashes = []
343
360
  marketType = None
361
+ subType = None
344
362
  chosenTimeframe = None
363
+ firstMarket = None
345
364
  if symbolsLength != 0:
346
365
  symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
347
366
  symbols = self.market_symbols(symbols, None, True, True, False)
348
367
  firstMarket = self.market(symbols[0])
349
- marketType, params = self.handle_market_type_and_params('watchOrderBookForSymbols', firstMarket, params)
350
- if marketType == 'spot':
351
- raise NotSupported(self.id + ' watchOrderBookForSymbols is not supported for spot markets yet')
368
+ marketType, params = self.handle_market_type_and_params('watchOHLCVForSymbols', firstMarket, params)
369
+ subType, params = self.handle_sub_type_and_params('watchOHLCVForSymbols', firstMarket, params, 'linear')
370
+ if marketType == 'spot':
371
+ raise NotSupported(self.id + ' watchOHLCVForSymbols is not supported for spot markets yet')
372
+ if subType == 'inverse':
373
+ raise NotSupported(self.id + ' watchOHLCVForSymbols is not supported for inverse markets yet')
352
374
  marketOptions = self.safe_dict(self.options, marketType)
353
375
  timeframes = self.safe_dict(marketOptions, 'timeframes', {})
354
376
  for i in range(0, len(symbolsAndTimeframes)):
@@ -363,7 +385,7 @@ class bingx(ccxt.async_support.bingx):
363
385
  raise BadRequest(self.id + ' watchOHLCVForSymbols requires all timeframes to be the same')
364
386
  messageHashes.append(self.get_message_hash('ohlcv', market['symbol'], chosenTimeframe))
365
387
  subscriptionHash = 'all@kline_' + chosenTimeframe
366
- url = self.safe_string(self.urls['api']['ws'], marketType)
388
+ url = self.safe_string(self.urls['api']['ws'], subType)
367
389
  uuid = self.uuid()
368
390
  request: dict = {
369
391
  'id': uuid,
@@ -404,8 +426,9 @@ class bingx(ccxt.async_support.bingx):
404
426
  async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
405
427
  """
406
428
  watches information on multiple trades made in a market
407
- :see: https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#Subscription%20transaction%20by%20transaction
408
- :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20the%20Latest%20Trade%20Detail
429
+ :see: https://bingx-api.github.io/docs/#/spot/socket/market.html#Subscribe%20to%20tick-by-tick
430
+ :see: https://bingx-api.github.io/docs/#/swapV2/socket/market.html#Subscribe%20the%20Latest%20Trade%20Detail
431
+ :see: https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscription%20transaction%20by%20transaction
409
432
  :param str symbol: unified market symbol of the market orders were made in
410
433
  :param int [since]: the earliest time in ms to fetch orders for
411
434
  :param int [limit]: the maximum number of order structures to retrieve
@@ -414,11 +437,16 @@ class bingx(ccxt.async_support.bingx):
414
437
  """
415
438
  await self.load_markets()
416
439
  market = self.market(symbol)
440
+ symbol = market['symbol']
417
441
  marketType = None
442
+ subType = None
443
+ url = None
418
444
  marketType, params = self.handle_market_type_and_params('watchTrades', market, params)
419
- url = self.safe_value(self.urls['api']['ws'], marketType)
420
- if url is None:
421
- raise BadRequest(self.id + ' watchTrades is not supported for ' + marketType + ' markets.')
445
+ subType, params = self.handle_sub_type_and_params('watchTrades', market, params, 'linear')
446
+ if marketType == 'swap':
447
+ url = self.safe_string(self.urls['api']['ws'], subType)
448
+ else:
449
+ url = self.safe_string(self.urls['api']['ws'], marketType)
422
450
  rawHash = market['id'] + '@trade'
423
451
  messageHash = 'trade::' + symbol
424
452
  uuid = self.uuid()
@@ -435,8 +463,7 @@ class bingx(ccxt.async_support.bingx):
435
463
 
436
464
  def handle_trades(self, client: Client, message):
437
465
  #
438
- # spot
439
- # first snapshot
466
+ # spot: first snapshot
440
467
  #
441
468
  # {
442
469
  # "id": "d83b78ce-98be-4dc2-b847-12fe471b5bc5",
@@ -445,7 +472,7 @@ class bingx(ccxt.async_support.bingx):
445
472
  # "timestamp": 1690214699854
446
473
  # }
447
474
  #
448
- # subsequent updates
475
+ # spot: subsequent updates
449
476
  #
450
477
  # {
451
478
  # "code": 0,
@@ -463,9 +490,7 @@ class bingx(ccxt.async_support.bingx):
463
490
  # "success": True
464
491
  # }
465
492
  #
466
- #
467
- # swap
468
- # first snapshot
493
+ # linear swap: first snapshot
469
494
  #
470
495
  # {
471
496
  # "id": "2aed93b1-6e1e-4038-aeba-f5eeaec2ca48",
@@ -475,8 +500,7 @@ class bingx(ccxt.async_support.bingx):
475
500
  # "data": null
476
501
  # }
477
502
  #
478
- # subsequent updates
479
- #
503
+ # linear swap: subsequent updates
480
504
  #
481
505
  # {
482
506
  # "code": 0,
@@ -493,6 +517,32 @@ class bingx(ccxt.async_support.bingx):
493
517
  # ]
494
518
  # }
495
519
  #
520
+ # inverse swap: first snapshot
521
+ #
522
+ # {
523
+ # "code": 0,
524
+ # "id": "a2e482ca-f71b-42f8-a83a-8ff85a713e64",
525
+ # "msg": "SUCCESS",
526
+ # "timestamp": 1722920589426
527
+ # }
528
+ #
529
+ # inverse swap: subsequent updates
530
+ #
531
+ # {
532
+ # "code": 0,
533
+ # "dataType": "BTC-USD@trade",
534
+ # "data": {
535
+ # "e": "trade",
536
+ # "E": 1722920589665,
537
+ # "s": "BTC-USD",
538
+ # "t": "39125001",
539
+ # "p": "55360.0",
540
+ # "q": "1",
541
+ # "T": 1722920589582,
542
+ # "m": False
543
+ # }
544
+ # }
545
+ #
496
546
  data = self.safe_value(message, 'data', [])
497
547
  rawHash = self.safe_string(message, 'dataType')
498
548
  marketId = rawHash.split('@')[0]
@@ -520,6 +570,7 @@ class bingx(ccxt.async_support.bingx):
520
570
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
521
571
  :see: https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#Subscribe%20Market%20Depth%20Data
522
572
  :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20Market%20Depth%20Data
573
+ :see: https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscribe%20to%20Limited%20Depth
523
574
  :param str symbol: unified symbol of the market to fetch the order book for
524
575
  :param int [limit]: the maximum amount of order book entries to return
525
576
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -527,17 +578,23 @@ class bingx(ccxt.async_support.bingx):
527
578
  """
528
579
  await self.load_markets()
529
580
  market = self.market(symbol)
530
- marketType, query = self.handle_market_type_and_params('watchOrderBook', market, params)
581
+ marketType = None
582
+ subType = None
583
+ url = None
584
+ marketType, params = self.handle_market_type_and_params('watchOrderBook', market, params)
585
+ subType, params = self.handle_sub_type_and_params('watchOrderBook', market, params, 'linear')
586
+ if marketType == 'swap':
587
+ url = self.safe_string(self.urls['api']['ws'], subType)
588
+ else:
589
+ url = self.safe_string(self.urls['api']['ws'], marketType)
531
590
  limit = self.get_order_book_limit_by_market_type(marketType, limit)
532
591
  channelName = 'depth' + str(limit)
533
- url = self.safe_value(self.urls['api']['ws'], marketType)
534
- if url is None:
535
- raise BadRequest(self.id + ' watchOrderBook is not supported for ' + marketType + ' markets.')
536
592
  interval = None
537
593
  if marketType != 'spot':
538
- interval, params = self.handle_option_and_params(params, 'watchOrderBook', 'interval', 500)
539
- self.check_required_argument('watchOrderBook', interval, 'interval', [100, 200, 500, 1000])
540
- channelName = channelName + '@' + str(interval) + 'ms'
594
+ if not market['inverse']:
595
+ interval, params = self.handle_option_and_params(params, 'watchOrderBook', 'interval', 500)
596
+ self.check_required_argument('watchOrderBook', interval, 'interval', [100, 200, 500, 1000])
597
+ channelName = channelName + '@' + str(interval) + 'ms'
541
598
  subscriptionHash = market['id'] + '@' + channelName
542
599
  messageHash = self.get_message_hash('orderbook', market['symbol'])
543
600
  uuid = self.uuid()
@@ -547,24 +604,30 @@ class bingx(ccxt.async_support.bingx):
547
604
  }
548
605
  if marketType == 'swap':
549
606
  request['reqType'] = 'sub'
550
- subscriptionArgs: dict = {
551
- 'limit': limit,
552
- 'interval': interval,
553
- 'params': params,
554
- }
555
- orderbook = await self.watch(url, messageHash, self.deep_extend(request, query), subscriptionHash, subscriptionArgs)
607
+ subscriptionArgs: dict = {}
608
+ if market['inverse']:
609
+ subscriptionArgs = {
610
+ 'count': limit,
611
+ 'params': params,
612
+ }
613
+ else:
614
+ subscriptionArgs = {
615
+ 'level': limit,
616
+ 'interval': interval,
617
+ 'params': params,
618
+ }
619
+ orderbook = await self.watch(url, messageHash, self.deep_extend(request, params), subscriptionHash, subscriptionArgs)
556
620
  return orderbook.limit()
557
621
 
558
622
  def handle_delta(self, bookside, delta):
559
- price = self.safe_float(delta, 0)
560
- amount = self.safe_float(delta, 1)
623
+ price = self.safe_float_2(delta, 0, 'p')
624
+ amount = self.safe_float_2(delta, 1, 'a')
561
625
  bookside.store(price, amount)
562
626
 
563
627
  def handle_order_book(self, client: Client, message):
564
628
  #
565
629
  # spot
566
630
  #
567
- #
568
631
  # {
569
632
  # "code": 0,
570
633
  # "dataType": "BTC-USDT@depth20",
@@ -582,8 +645,7 @@ class bingx(ccxt.async_support.bingx):
582
645
  # "success": True
583
646
  # }
584
647
  #
585
- # swap
586
- #
648
+ # linear swap
587
649
  #
588
650
  # {
589
651
  # "code": 0,
@@ -601,6 +663,28 @@ class bingx(ccxt.async_support.bingx):
601
663
  # }
602
664
  # }
603
665
  #
666
+ # inverse swap
667
+ #
668
+ # {
669
+ # "code": 0,
670
+ # "dataType": "BTC-USD@depth100",
671
+ # "data": {
672
+ # {
673
+ # "symbol": "BTC-USD",
674
+ # "bids": [
675
+ # {"p": "58074.2", "a": "1.422318", "v": "826.0"},
676
+ # ...
677
+ # ],
678
+ # "asks": [
679
+ # {"p": "62878.0", "a": "0.001590", "v": "1.0"},
680
+ # ...
681
+ # ],
682
+ # "aggPrecision": "0.1",
683
+ # "timestamp": 1723705093529
684
+ # }
685
+ # }
686
+ # }
687
+ #
604
688
  data = self.safe_dict(message, 'data', {})
605
689
  dataType = self.safe_string(message, 'dataType')
606
690
  parts = dataType.split('@')
@@ -618,7 +702,11 @@ class bingx(ccxt.async_support.bingx):
618
702
  limit = self.safe_integer(subscription, 'limit')
619
703
  self.orderbooks[symbol] = self.order_book({}, limit)
620
704
  orderbook = self.orderbooks[symbol]
621
- snapshot = self.parse_order_book(data, symbol, None, 'bids', 'asks', 0, 1)
705
+ snapshot = None
706
+ if market['inverse']:
707
+ snapshot = self.parse_order_book(data, symbol, None, 'bids', 'asks', 'p', 'a')
708
+ else:
709
+ snapshot = self.parse_order_book(data, symbol, None, 'bids', 'asks', 0, 1)
622
710
  orderbook.reset(snapshot)
623
711
  self.orderbooks[symbol] = orderbook
624
712
  messageHash = self.get_message_hash('orderbook', symbol)
@@ -641,8 +729,10 @@ class bingx(ccxt.async_support.bingx):
641
729
  # }
642
730
  #
643
731
  # for spot, opening-time(t) is used instead of closing-time(T), to be compatible with fetchOHLCV
644
- # for swap,(T) is the opening time
732
+ # for linear swap,(T) is the opening time
645
733
  timestamp = 't' if (market['spot']) else 'T'
734
+ if market['swap']:
735
+ timestamp = 't' if (market['inverse']) else 'T'
646
736
  return [
647
737
  self.safe_integer(ohlcv, timestamp),
648
738
  self.safe_number(ohlcv, 'o'),
@@ -654,7 +744,7 @@ class bingx(ccxt.async_support.bingx):
654
744
 
655
745
  def handle_ohlcv(self, client: Client, message):
656
746
  #
657
- # spot
747
+ # spot:
658
748
  #
659
749
  # {
660
750
  # "code": 0,
@@ -680,7 +770,8 @@ class bingx(ccxt.async_support.bingx):
680
770
  # "success": True
681
771
  # }
682
772
  #
683
- # swap
773
+ # linear swap:
774
+ #
684
775
  # {
685
776
  # "code": 0,
686
777
  # "dataType": "BTC-USDT@kline_1m",
@@ -697,13 +788,26 @@ class bingx(ccxt.async_support.bingx):
697
788
  # ]
698
789
  # }
699
790
  #
791
+ # inverse swap:
792
+ #
793
+ # {
794
+ # "code": 0,
795
+ # "timestamp": 1723769354547,
796
+ # "dataType": "BTC-USD@kline_1m",
797
+ # "data": {
798
+ # "t": 1723769340000,
799
+ # "o": 57485.1,
800
+ # "c": 57468,
801
+ # "l": 57464.9,
802
+ # "h": 57485.1,
803
+ # "a": 0.189663,
804
+ # "v": 109,
805
+ # "u": 92,
806
+ # "s": "BTC-USD"
807
+ # }
808
+ # }
809
+ #
700
810
  isSwap = client.url.find('swap') >= 0
701
- candles = None
702
- if isSwap:
703
- candles = self.safe_list(message, 'data', [])
704
- else:
705
- data = self.safe_dict(message, 'data', {})
706
- candles = [self.safe_dict(data, 'K', {})]
707
811
  dataType = self.safe_string(message, 'dataType')
708
812
  parts = dataType.split('@')
709
813
  firstPart = parts[0]
@@ -711,6 +815,15 @@ class bingx(ccxt.async_support.bingx):
711
815
  marketId = self.safe_string(message, 's', firstPart)
712
816
  marketType = 'swap' if isSwap else 'spot'
713
817
  market = self.safe_market(marketId, None, None, marketType)
818
+ candles = None
819
+ if isSwap:
820
+ if market['inverse']:
821
+ candles = [self.safe_dict(message, 'data', {})]
822
+ else:
823
+ candles = self.safe_list(message, 'data', [])
824
+ else:
825
+ data = self.safe_dict(message, 'data', {})
826
+ candles = [self.safe_dict(data, 'K', {})]
714
827
  symbol = market['symbol']
715
828
  self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
716
829
  rawTimeframe = dataType.split('_')[1]
@@ -740,6 +853,7 @@ class bingx(ccxt.async_support.bingx):
740
853
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
741
854
  :see: https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#K-line%20Streams
742
855
  :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20K-Line%20Data
856
+ :see: https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscribe%20to%20Latest%20Trading%20Pair%20K-Line
743
857
  :param str symbol: unified symbol of the market to fetch OHLCV data for
744
858
  :param str timeframe: the length of time each candle represents
745
859
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -749,8 +863,15 @@ class bingx(ccxt.async_support.bingx):
749
863
  """
750
864
  await self.load_markets()
751
865
  market = self.market(symbol)
752
- marketType, query = self.handle_market_type_and_params('watchOHLCV', market, params)
753
- url = self.safe_value(self.urls['api']['ws'], marketType)
866
+ marketType = None
867
+ subType = None
868
+ url = None
869
+ marketType, params = self.handle_market_type_and_params('watchOHLCV', market, params)
870
+ subType, params = self.handle_sub_type_and_params('watchOHLCV', market, params, 'linear')
871
+ if marketType == 'swap':
872
+ url = self.safe_string(self.urls['api']['ws'], subType)
873
+ else:
874
+ url = self.safe_string(self.urls['api']['ws'], marketType)
754
875
  if url is None:
755
876
  raise BadRequest(self.id + ' watchOHLCV is not supported for ' + marketType + ' markets.')
756
877
  options = self.safe_value(self.options, marketType, {})
@@ -766,10 +887,10 @@ class bingx(ccxt.async_support.bingx):
766
887
  if marketType == 'swap':
767
888
  request['reqType'] = 'sub'
768
889
  subscriptionArgs: dict = {
769
- 'limit': limit,
890
+ 'interval': rawTimeframe,
770
891
  'params': params,
771
892
  }
772
- result = await self.watch(url, messageHash, self.extend(request, query), subscriptionHash, subscriptionArgs)
893
+ result = await self.watch(url, messageHash, self.extend(request, params), subscriptionHash, subscriptionArgs)
773
894
  ohlcv = result[2]
774
895
  if self.newUpdates:
775
896
  limit = ohlcv.getLimit(symbol, limit)
@@ -777,11 +898,12 @@ class bingx(ccxt.async_support.bingx):
777
898
 
778
899
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
779
900
  """
780
- :see: https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
781
- :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
782
901
  watches information on multiple orders made by the user
783
- :param str symbol: unified market symbol of the market orders were made in
784
- :param int [since]: the earliest time in ms to fetch orders for
902
+ :see: https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
903
+ :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Order%20update%20push
904
+ :see: https://bingx-api.github.io/docs/#/en-us/cswap/socket/account.html#Order%20update%20push
905
+ :param str [symbol]: unified market symbol of the market orders are made in
906
+ :param int [since]: the earliest time in ms to watch orders for
785
907
  :param int [limit]: the maximum number of order structures to retrieve
786
908
  :param dict [params]: extra parameters specific to the exchange API endpoint
787
909
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
@@ -789,11 +911,13 @@ class bingx(ccxt.async_support.bingx):
789
911
  await self.load_markets()
790
912
  await self.authenticate()
791
913
  type = None
914
+ subType = None
792
915
  market = None
793
916
  if symbol is not None:
794
917
  market = self.market(symbol)
795
918
  symbol = market['symbol']
796
919
  type, params = self.handle_market_type_and_params('watchOrders', market, params)
920
+ subType, params = self.handle_sub_type_and_params('watchOrders', market, params, 'linear')
797
921
  isSpot = (type == 'spot')
798
922
  spotHash = 'spot:private'
799
923
  swapHash = 'swap:private'
@@ -803,14 +927,21 @@ class bingx(ccxt.async_support.bingx):
803
927
  messageHash = spotMessageHash if isSpot else swapMessageHash
804
928
  if market is not None:
805
929
  messageHash += ':' + symbol
806
- url = self.urls['api']['ws'][type] + '?listenKey=' + self.options['listenKey']
807
- request = None
808
930
  uuid = self.uuid()
809
- if isSpot:
931
+ baseUrl = None
932
+ request = None
933
+ if type == 'swap':
934
+ if subType == 'inverse':
935
+ raise NotSupported(self.id + ' watchOrders is not supported for inverse swap markets yet')
936
+ baseUrl = self.safe_string(self.urls['api']['ws'], subType)
937
+ else:
938
+ baseUrl = self.safe_string(self.urls['api']['ws'], type)
810
939
  request = {
811
940
  'id': uuid,
941
+ 'reqType': 'sub',
812
942
  'dataType': 'spot.executionReport',
813
943
  }
944
+ url = baseUrl + '?listenKey=' + self.options['listenKey']
814
945
  orders = await self.watch(url, messageHash, request, subscriptionHash)
815
946
  if self.newUpdates:
816
947
  limit = orders.getLimit(symbol, limit)
@@ -818,40 +949,50 @@ class bingx(ccxt.async_support.bingx):
818
949
 
819
950
  async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
820
951
  """
821
- :see: https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
822
- :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
823
952
  watches information on multiple trades made by the user
824
- :param str symbol: unified market symbol of the market trades were made in
825
- :param int [since]: the earliest time in ms to trades orders for
826
- :param int [limit]: the maximum number of trades structures to retrieve
953
+ :see: https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
954
+ :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Order%20update%20push
955
+ :see: https://bingx-api.github.io/docs/#/en-us/cswap/socket/account.html#Order%20update%20push
956
+ :param str [symbol]: unified market symbol of the market the trades are made in
957
+ :param int [since]: the earliest time in ms to watch trades for
958
+ :param int [limit]: the maximum number of trade structures to retrieve
827
959
  :param dict [params]: extra parameters specific to the exchange API endpoint
828
960
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
829
961
  """
830
962
  await self.load_markets()
831
963
  await self.authenticate()
832
964
  type = None
965
+ subType = None
833
966
  market = None
834
967
  if symbol is not None:
835
968
  market = self.market(symbol)
836
969
  symbol = market['symbol']
837
- type, params = self.handle_market_type_and_params('watchOrders', market, params)
970
+ type, params = self.handle_market_type_and_params('watchMyTrades', market, params)
971
+ subType, params = self.handle_sub_type_and_params('watchMyTrades', market, params, 'linear')
838
972
  isSpot = (type == 'spot')
839
- spotSubHash = 'spot:private'
840
- swapSubHash = 'swap:private'
841
- subscriptionHash = spotSubHash if isSpot else swapSubHash
973
+ spotHash = 'spot:private'
974
+ swapHash = 'swap:private'
975
+ subscriptionHash = spotHash if isSpot else swapHash
842
976
  spotMessageHash = 'spot:mytrades'
843
977
  swapMessageHash = 'swap:mytrades'
844
978
  messageHash = spotMessageHash if isSpot else swapMessageHash
845
979
  if market is not None:
846
980
  messageHash += ':' + symbol
847
- url = self.urls['api']['ws'][type] + '?listenKey=' + self.options['listenKey']
848
- request = None
849
981
  uuid = self.uuid()
850
- if isSpot:
982
+ baseUrl = None
983
+ request = None
984
+ if type == 'swap':
985
+ if subType == 'inverse':
986
+ raise NotSupported(self.id + ' watchMyTrades is not supported for inverse swap markets yet')
987
+ baseUrl = self.safe_string(self.urls['api']['ws'], subType)
988
+ else:
989
+ baseUrl = self.safe_string(self.urls['api']['ws'], type)
851
990
  request = {
852
991
  'id': uuid,
992
+ 'reqType': 'sub',
853
993
  'dataType': 'spot.executionReport',
854
994
  }
995
+ url = baseUrl + '?listenKey=' + self.options['listenKey']
855
996
  trades = await self.watch(url, messageHash, request, subscriptionHash)
856
997
  if self.newUpdates:
857
998
  limit = trades.getLimit(symbol, limit)
@@ -859,16 +1000,19 @@ class bingx(ccxt.async_support.bingx):
859
1000
 
860
1001
  async def watch_balance(self, params={}) -> Balances:
861
1002
  """
1003
+ query for balance and get the amount of funds available for trading or funds locked in orders
862
1004
  :see: https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20account%20balance%20push
863
1005
  :see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
864
- query for balance and get the amount of funds available for trading or funds locked in orders
1006
+ :see: https://bingx-api.github.io/docs/#/en-us/cswap/socket/account.html#Account%20balance%20and%20position%20update%20push
865
1007
  :param dict [params]: extra parameters specific to the exchange API endpoint
866
1008
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
867
1009
  """
868
1010
  await self.load_markets()
869
1011
  await self.authenticate()
870
1012
  type = None
1013
+ subType = None
871
1014
  type, params = self.handle_market_type_and_params('watchBalance', None, params)
1015
+ subType, params = self.handle_sub_type_and_params('watchBalance', None, params, 'linear')
872
1016
  isSpot = (type == 'spot')
873
1017
  spotSubHash = 'spot:balance'
874
1018
  swapSubHash = 'swap:private'
@@ -876,16 +1020,22 @@ class bingx(ccxt.async_support.bingx):
876
1020
  swapMessageHash = 'swap:balance'
877
1021
  messageHash = spotMessageHash if isSpot else swapMessageHash
878
1022
  subscriptionHash = spotSubHash if isSpot else swapSubHash
879
- url = self.urls['api']['ws'][type] + '?listenKey=' + self.options['listenKey']
880
1023
  request = None
1024
+ baseUrl = None
881
1025
  uuid = self.uuid()
882
- if type == 'spot':
1026
+ if type == 'swap':
1027
+ if subType == 'inverse':
1028
+ raise NotSupported(self.id + ' watchBalance is not supported for inverse swap markets yet')
1029
+ baseUrl = self.safe_string(self.urls['api']['ws'], subType)
1030
+ else:
1031
+ baseUrl = self.safe_string(self.urls['api']['ws'], type)
883
1032
  request = {
884
1033
  'id': uuid,
885
1034
  'dataType': 'ACCOUNT_UPDATE',
886
1035
  }
1036
+ url = baseUrl + '?listenKey=' + self.options['listenKey']
887
1037
  client = self.client(url)
888
- self.set_balance_cache(client, type, subscriptionHash, params)
1038
+ self.set_balance_cache(client, type, subType, subscriptionHash, params)
889
1039
  fetchBalanceSnapshot = None
890
1040
  awaitBalanceSnapshot = None
891
1041
  fetchBalanceSnapshot, params = self.handle_option_and_params(params, 'watchBalance', 'fetchBalanceSnapshot', True)
@@ -894,7 +1044,7 @@ class bingx(ccxt.async_support.bingx):
894
1044
  await client.future(type + ':fetchBalanceSnapshot')
895
1045
  return await self.watch(url, messageHash, request, subscriptionHash)
896
1046
 
897
- def set_balance_cache(self, client: Client, type, subscriptionHash, params):
1047
+ def set_balance_cache(self, client: Client, type, subType, subscriptionHash, params):
898
1048
  if subscriptionHash in client.subscriptions:
899
1049
  return
900
1050
  fetchBalanceSnapshot = self.handle_option_and_params(params, 'watchBalance', 'fetchBalanceSnapshot', True)
@@ -902,12 +1052,12 @@ class bingx(ccxt.async_support.bingx):
902
1052
  messageHash = type + ':fetchBalanceSnapshot'
903
1053
  if not (messageHash in client.futures):
904
1054
  client.future(messageHash)
905
- self.spawn(self.load_balance_snapshot, client, messageHash, type)
1055
+ self.spawn(self.load_balance_snapshot, client, messageHash, type, subType)
906
1056
  else:
907
1057
  self.balance[type] = {}
908
1058
 
909
- async def load_balance_snapshot(self, client, messageHash, type):
910
- response = await self.fetch_balance({'type': type})
1059
+ async def load_balance_snapshot(self, client, messageHash, type, subType):
1060
+ response = await self.fetch_balance({'type': type, 'subType': subType})
911
1061
  self.balance[type] = self.extend(response, self.safe_value(self.balance, type, {}))
912
1062
  # don't remove the future from the .futures cache
913
1063
  future = client.futures[messageHash]
@@ -941,7 +1091,7 @@ class bingx(ccxt.async_support.bingx):
941
1091
  try:
942
1092
  await self.userAuthPrivatePutUserDataStream({'listenKey': listenKey}) # self.extend the expiry
943
1093
  except Exception as error:
944
- types = ['spot', 'swap']
1094
+ types = ['spot', 'linear', 'inverse']
945
1095
  for i in range(0, len(types)):
946
1096
  type = types[i]
947
1097
  url = self.urls['api']['ws'][type] + '?listenKey=' + listenKey