ccxt 4.3.95__py2.py3-none-any.whl → 4.3.96__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.
ccxt/pro/okx.py CHANGED
@@ -27,6 +27,7 @@ class okx(ccxt.async_support.okx):
27
27
  'ws': True,
28
28
  'watchTicker': True,
29
29
  'watchTickers': True,
30
+ 'watchBidsAsks': True,
30
31
  'watchOrderBook': True,
31
32
  'watchTrades': True,
32
33
  'watchTradesForSymbols': True,
@@ -135,9 +136,8 @@ class okx(ccxt.async_support.okx):
135
136
  symbols = self.symbols
136
137
  symbols = self.market_symbols(symbols)
137
138
  url = self.get_url(channel, access)
138
- messageHash = channel
139
+ messageHashes = []
139
140
  args = []
140
- messageHash += '::' + ','.join(symbols)
141
141
  for i in range(0, len(symbols)):
142
142
  marketId = self.market_id(symbols[i])
143
143
  arg: dict = {
@@ -145,11 +145,12 @@ class okx(ccxt.async_support.okx):
145
145
  'instId': marketId,
146
146
  }
147
147
  args.append(self.extend(arg, params))
148
+ messageHashes.append(channel + '::' + symbols[i])
148
149
  request: dict = {
149
150
  'op': 'subscribe',
150
151
  'args': args,
151
152
  }
152
- return await self.watch(url, messageHash, request, messageHash)
153
+ return await self.watch_multiple(url, messageHashes, request, messageHashes)
153
154
 
154
155
  async def subscribe(self, access, messageHash, channel, symbol, params={}):
155
156
  await self.load_markets()
@@ -379,6 +380,17 @@ class okx(ccxt.async_support.okx):
379
380
  ticker = await self.watch_tickers([symbol], params)
380
381
  return self.safe_value(ticker, symbol)
381
382
 
383
+ async def un_watch_ticker(self, symbol: str, params={}) -> Any:
384
+ """
385
+ :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
386
+ unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
387
+ :param str symbol: unified symbol of the market to fetch the ticker for
388
+ :param dict [params]: extra parameters specific to the exchange API endpoint
389
+ :param str [params.channel]: the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
390
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
391
+ """
392
+ return await self.un_watch_tickers([symbol], params)
393
+
382
394
  async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
383
395
  """
384
396
  :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
@@ -397,6 +409,37 @@ class okx(ccxt.async_support.okx):
397
409
  return newTickers
398
410
  return self.filter_by_array(self.tickers, 'symbol', symbols)
399
411
 
412
+ async def un_watch_tickers(self, symbols: Strings = None, params={}) -> Any:
413
+ """
414
+ :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
415
+ unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
416
+ :param str[] [symbols]: unified symbol of the market to fetch the ticker for
417
+ :param dict [params]: extra parameters specific to the exchange API endpoint
418
+ :param str [params.channel]: the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
419
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
420
+ """
421
+ await self.load_markets()
422
+ symbols = self.market_symbols(symbols, None, False)
423
+ channel = None
424
+ channel, params = self.handle_option_and_params(params, 'watchTickers', 'channel', 'tickers')
425
+ topics = []
426
+ messageHashes = []
427
+ for i in range(0, len(symbols)):
428
+ symbol = symbols[i]
429
+ messageHashes.append('unsubscribe:ticker:' + symbol)
430
+ marketId = self.market_id(symbol)
431
+ topic: dict = {
432
+ 'channel': channel,
433
+ 'instId': marketId,
434
+ }
435
+ topics.append(topic)
436
+ request: dict = {
437
+ 'op': 'unsubscribe',
438
+ 'args': topics,
439
+ }
440
+ url = self.get_url(channel, 'public')
441
+ return await self.watch_multiple(url, messageHashes, request, messageHashes)
442
+
400
443
  def handle_ticker(self, client: Client, message):
401
444
  #
402
445
  # {
@@ -423,27 +466,104 @@ class okx(ccxt.async_support.okx):
423
466
  # ]
424
467
  # }
425
468
  #
469
+ self.handle_bid_ask(client, message)
426
470
  arg = self.safe_value(message, 'arg', {})
471
+ marketId = self.safe_string(arg, 'instId')
472
+ market = self.safe_market(marketId, None, '-')
473
+ symbol = market['symbol']
427
474
  channel = self.safe_string(arg, 'channel')
428
475
  data = self.safe_value(message, 'data', [])
429
- newTickers = []
476
+ newTickers: dict = {}
430
477
  for i in range(0, len(data)):
431
478
  ticker = self.parse_ticker(data[i])
432
- symbol = ticker['symbol']
433
479
  self.tickers[symbol] = ticker
434
- newTickers.append(ticker)
435
- messageHashes = self.find_message_hashes(client, channel + '::')
436
- for i in range(0, len(messageHashes)):
437
- messageHash = messageHashes[i]
438
- parts = messageHash.split('::')
439
- symbolsString = parts[1]
440
- symbols = symbolsString.split(',')
441
- tickers = self.filter_by_array(newTickers, 'symbol', symbols)
442
- tickersSymbols = list(tickers.keys())
443
- numTickers = len(tickersSymbols)
444
- if numTickers > 0:
445
- client.resolve(tickers, messageHash)
446
- return message
480
+ newTickers[symbol] = ticker
481
+ messageHash = channel + '::' + symbol
482
+ client.resolve(newTickers, messageHash)
483
+
484
+ async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
485
+ """
486
+ :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
487
+ watches best bid & ask for symbols
488
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
489
+ :param dict [params]: extra parameters specific to the exchange API endpoint
490
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
491
+ """
492
+ await self.load_markets()
493
+ symbols = self.market_symbols(symbols, None, False)
494
+ channel = None
495
+ channel, params = self.handle_option_and_params(params, 'watchBidsAsks', 'channel', 'tickers')
496
+ url = self.get_url(channel, 'public')
497
+ messageHashes = []
498
+ args = []
499
+ for i in range(0, len(symbols)):
500
+ marketId = self.market_id(symbols[i])
501
+ arg: dict = {
502
+ 'channel': channel,
503
+ 'instId': marketId,
504
+ }
505
+ args.append(self.extend(arg, params))
506
+ messageHashes.append('bidask::' + symbols[i])
507
+ request: dict = {
508
+ 'op': 'subscribe',
509
+ 'args': args,
510
+ }
511
+ newTickers = await self.watch_multiple(url, messageHashes, request, messageHashes)
512
+ if self.newUpdates:
513
+ tickers: dict = {}
514
+ tickers[newTickers['symbol']] = newTickers
515
+ return tickers
516
+ return self.filter_by_array(self.bidsasks, 'symbol', symbols)
517
+
518
+ def handle_bid_ask(self, client: Client, message):
519
+ #
520
+ # {
521
+ # "arg": {channel: "tickers", instId: "BTC-USDT"},
522
+ # "data": [
523
+ # {
524
+ # "instType": "SPOT",
525
+ # "instId": "BTC-USDT",
526
+ # "last": "31500.1",
527
+ # "lastSz": "0.00001754",
528
+ # "askPx": "31500.1",
529
+ # "askSz": "0.00998144",
530
+ # "bidPx": "31500",
531
+ # "bidSz": "3.05652439",
532
+ # "open24h": "31697",
533
+ # "high24h": "32248",
534
+ # "low24h": "31165.6",
535
+ # "sodUtc0": "31385.5",
536
+ # "sodUtc8": "32134.9",
537
+ # "volCcy24h": "503403597.38138519",
538
+ # "vol24h": "15937.10781721",
539
+ # "ts": "1626526618762"
540
+ # }
541
+ # ]
542
+ # }
543
+ #
544
+ data = self.safe_list(message, 'data', [])
545
+ ticker = self.safe_dict(data, 0, {})
546
+ parsedTicker = self.parse_ws_bid_ask(ticker)
547
+ symbol = parsedTicker['symbol']
548
+ self.bidsasks[symbol] = parsedTicker
549
+ messageHash = 'bidask::' + symbol
550
+ client.resolve(parsedTicker, messageHash)
551
+
552
+ def parse_ws_bid_ask(self, ticker, market=None):
553
+ marketId = self.safe_string(ticker, 'instId')
554
+ market = self.safe_market(marketId, market)
555
+ symbol = self.safe_string(market, 'symbol')
556
+ timestamp = self.safe_integer(ticker, 'ts')
557
+ return self.safe_ticker({
558
+ 'symbol': symbol,
559
+ 'timestamp': timestamp,
560
+ 'datetime': self.iso8601(timestamp),
561
+ 'ask': self.safe_string(ticker, 'askPx'),
562
+ 'askVolume': self.safe_string(ticker, 'askSz'),
563
+ 'bid': self.safe_string(ticker, 'bidPx'),
564
+ 'bidVolume': self.safe_string(ticker, 'bidSz'),
565
+ 'info': ticker,
566
+ }, market)
447
567
 
448
568
  async def watch_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
449
569
  """
@@ -547,10 +667,24 @@ class okx(ccxt.async_support.okx):
547
667
  await self.authenticate({'access': 'business' if isStop else 'private'})
548
668
  symbols = self.market_symbols(symbols, None, True, True)
549
669
  messageHash = 'myLiquidations'
670
+ messageHashes = []
550
671
  if symbols is not None:
551
- messageHash += '::' + ','.join(symbols)
672
+ for i in range(0, len(symbols)):
673
+ symbol = symbols[i]
674
+ messageHashes.append(messageHash + '::' + symbol)
675
+ else:
676
+ messageHashes.append(messageHash)
552
677
  channel = 'balance_and_position'
553
- newLiquidations = await self.subscribe('private', messageHash, channel, None, params)
678
+ request: dict = {
679
+ 'op': 'subscribe',
680
+ 'args': [
681
+ {
682
+ 'channel': channel,
683
+ },
684
+ ],
685
+ }
686
+ url = self.get_url(channel, 'private')
687
+ newLiquidations = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), messageHashes)
554
688
  if self.newUpdates:
555
689
  return newLiquidations
556
690
  return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
@@ -710,6 +844,17 @@ class okx(ccxt.async_support.okx):
710
844
  limit = ohlcv.getLimit(symbol, limit)
711
845
  return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
712
846
 
847
+ async def un_watch_ohlcv(self, symbol: str, timeframe='1m', params={}) -> Any:
848
+ """
849
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
850
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
851
+ :param str timeframe: the length of time each candle represents
852
+ :param dict [params]: extra parameters specific to the exchange API endpoint
853
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
854
+ """
855
+ await self.load_markets()
856
+ return await self.un_watch_ohlcv_for_symbols([[symbol, timeframe]], params)
857
+
713
858
  async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
714
859
  """
715
860
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
@@ -749,6 +894,39 @@ class okx(ccxt.async_support.okx):
749
894
  filtered = self.filter_by_since_limit(candles, since, limit, 0, True)
750
895
  return self.create_ohlcv_object(symbol, timeframe, filtered)
751
896
 
897
+ async def un_watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], params={}):
898
+ """
899
+ unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
900
+ :param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
901
+ :param dict [params]: extra parameters specific to the exchange API endpoint
902
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
903
+ """
904
+ symbolsLength = len(symbolsAndTimeframes)
905
+ if symbolsLength == 0 or not isinstance(symbolsAndTimeframes[0], list):
906
+ raise ArgumentsRequired(self.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]")
907
+ await self.load_markets()
908
+ topics = []
909
+ messageHashes = []
910
+ for i in range(0, len(symbolsAndTimeframes)):
911
+ symbolAndTimeframe = symbolsAndTimeframes[i]
912
+ sym = symbolAndTimeframe[0]
913
+ tf = symbolAndTimeframe[1]
914
+ marketId = self.market_id(sym)
915
+ interval = self.safe_string(self.timeframes, tf, tf)
916
+ channel = 'candle' + interval
917
+ topic: dict = {
918
+ 'channel': channel,
919
+ 'instId': marketId,
920
+ }
921
+ topics.append(topic)
922
+ messageHashes.append('unsubscribe:multi:' + channel + ':' + sym)
923
+ request: dict = {
924
+ 'op': 'unsubscribe',
925
+ 'args': topics,
926
+ }
927
+ url = self.get_url('candle', 'public')
928
+ return await self.watch_multiple(url, messageHashes, request, messageHashes)
929
+
752
930
  def handle_ohlcv(self, client: Client, message):
753
931
  #
754
932
  # {
@@ -1403,6 +1581,9 @@ class okx(ccxt.async_support.okx):
1403
1581
  # }
1404
1582
  #
1405
1583
  arg = self.safe_value(message, 'arg', {})
1584
+ marketId = self.safe_string(arg, 'instId')
1585
+ market = self.safe_market(marketId, None, '-')
1586
+ symbol = market['symbol']
1406
1587
  channel = self.safe_string(arg, 'channel', '')
1407
1588
  data = self.safe_value(message, 'data', [])
1408
1589
  if self.positions is None:
@@ -1420,16 +1601,10 @@ class okx(ccxt.async_support.okx):
1420
1601
  newPositions.append(shortPosition)
1421
1602
  newPositions.append(position)
1422
1603
  cache.append(position)
1423
- messageHashes = self.find_message_hashes(client, channel + '::')
1424
- for i in range(0, len(messageHashes)):
1425
- messageHash = messageHashes[i]
1426
- parts = messageHash.split('::')
1427
- symbolsString = parts[1]
1428
- symbols = symbolsString.split(',')
1429
- positions = self.filter_by_array(newPositions, 'symbol', symbols, False)
1430
- if not self.is_empty(positions):
1431
- client.resolve(positions, messageHash)
1432
- client.resolve(newPositions, channel)
1604
+ messageHash = channel
1605
+ if symbol is not None:
1606
+ messageHash = channel + '::' + symbol
1607
+ client.resolve(newPositions, messageHash)
1433
1608
 
1434
1609
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1435
1610
  """
@@ -2008,6 +2183,34 @@ class okx(ccxt.async_support.okx):
2008
2183
  client.reject(error, subMessageHash)
2009
2184
  client.resolve(True, messageHash)
2010
2185
 
2186
+ def handle_unsubscription_ohlcv(self, client: Client, symbol: str, channel: str):
2187
+ tf = channel.replace('candle', '')
2188
+ timeframe = self.find_timeframe(tf)
2189
+ subMessageHash = 'multi:' + channel + ':' + symbol
2190
+ messageHash = 'unsubscribe:' + subMessageHash
2191
+ if subMessageHash in client.subscriptions:
2192
+ del client.subscriptions[subMessageHash]
2193
+ if messageHash in client.subscriptions:
2194
+ del client.subscriptions[messageHash]
2195
+ if timeframe in self.ohlcvs[symbol]:
2196
+ del self.ohlcvs[symbol][timeframe]
2197
+ error = UnsubscribeError(self.id + ' ' + subMessageHash)
2198
+ client.reject(error, subMessageHash)
2199
+ client.resolve(True, messageHash)
2200
+
2201
+ def handle_unsubscription_ticker(self, client: Client, symbol: str, channel):
2202
+ subMessageHash = channel + '::' + symbol
2203
+ messageHash = 'unsubscribe:ticker:' + symbol
2204
+ if subMessageHash in client.subscriptions:
2205
+ del client.subscriptions[subMessageHash]
2206
+ if messageHash in client.subscriptions:
2207
+ del client.subscriptions[messageHash]
2208
+ if symbol in self.tickers:
2209
+ del self.tickers[symbol]
2210
+ error = UnsubscribeError(self.id + ' ' + subMessageHash)
2211
+ client.reject(error, subMessageHash)
2212
+ client.resolve(True, messageHash)
2213
+
2011
2214
  def handle_unsubscription(self, client: Client, message):
2012
2215
  #
2013
2216
  # {
@@ -2020,10 +2223,14 @@ class okx(ccxt.async_support.okx):
2020
2223
  # }
2021
2224
  # arg might be an array or list
2022
2225
  arg = self.safe_dict(message, 'arg', {})
2023
- channel = self.safe_string(arg, 'channel')
2226
+ channel = self.safe_string(arg, 'channel', '')
2024
2227
  marketId = self.safe_string(arg, 'instId')
2025
2228
  symbol = self.safe_symbol(marketId)
2026
2229
  if channel == 'trades':
2027
2230
  self.handle_un_subscription_trades(client, symbol)
2028
2231
  elif channel.startswith('bbo') or channel.startswith('book'):
2029
2232
  self.handle_unsubscription_order_book(client, symbol, channel)
2233
+ elif channel.find('tickers') > -1:
2234
+ self.handle_unsubscription_ticker(client, symbol, channel)
2235
+ elif channel.startswith('candle'):
2236
+ self.handle_unsubscription_ohlcv(client, symbol, channel)
ccxt/tradeogre.py CHANGED
@@ -83,7 +83,6 @@ class tradeogre(Exchange, ImplicitAPI):
83
83
  'fetchOrderBooks': False,
84
84
  'fetchOrders': False,
85
85
  'fetchOrderTrades': False,
86
- 'fetchPermissions': False,
87
86
  'fetchPosition': False,
88
87
  'fetchPositionHistory': False,
89
88
  'fetchPositionMode': False,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.3.95
3
+ Version: 4.3.96
4
4
  Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
5
5
  Home-page: https://ccxt.com
6
6
  Author: Igor Kroitor
@@ -50,7 +50,7 @@ Requires-Dist: mypy (==1.6.1) ; extra == 'type'
50
50
 
51
51
  # CCXT – CryptoCurrency eXchange Trading Library
52
52
 
53
- [![Build Status](https://img.shields.io/travis/com/ccxt/ccxt)](https://travis-ci.com/ccxt/ccxt) [![npm](https://img.shields.io/npm/v/ccxt.svg)](https://npmjs.com/package/ccxt) [![PyPI](https://img.shields.io/pypi/v/ccxt.svg)](https://pypi.python.org/pypi/ccxt) [![NPM Downloads](https://img.shields.io/npm/dy/ccxt.svg)](https://www.npmjs.com/package/ccxt) [![Discord](https://img.shields.io/discord/690203284119617602?logo=discord&logoColor=white)](https://discord.gg/ccxt) [![Supported Exchanges](https://img.shields.io/badge/exchanges-110-blue.svg)](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [![Twitter Follow](https://img.shields.io/twitter/follow/ccxt_official.svg?style=social&label=CCXT)](https://twitter.com/ccxt_official)
53
+ [![Build Status](https://img.shields.io/travis/com/ccxt/ccxt)](https://travis-ci.com/ccxt/ccxt) [![npm](https://img.shields.io/npm/v/ccxt.svg)](https://npmjs.com/package/ccxt) [![PyPI](https://img.shields.io/pypi/v/ccxt.svg)](https://pypi.python.org/pypi/ccxt) [![NPM Downloads](https://img.shields.io/npm/dy/ccxt.svg)](https://www.npmjs.com/package/ccxt) [![Discord](https://img.shields.io/discord/690203284119617602?logo=discord&logoColor=white)](https://discord.gg/ccxt) [![Supported Exchanges](https://img.shields.io/badge/exchanges-108-blue.svg)](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [![Twitter Follow](https://img.shields.io/twitter/follow/ccxt_official.svg?style=social&label=CCXT)](https://twitter.com/ccxt_official)
54
54
 
55
55
  A JavaScript / Python / PHP / C# library for cryptocurrency trading and e-commerce with support for many bitcoin/ether/altcoin exchange markets and merchant APIs.
56
56
 
@@ -272,13 +272,13 @@ console.log(version, Object.keys(exchanges));
272
272
 
273
273
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
274
274
 
275
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.95/dist/ccxt.browser.min.js
276
- * unpkg: https://unpkg.com/ccxt@4.3.95/dist/ccxt.browser.min.js
275
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.96/dist/ccxt.browser.min.js
276
+ * unpkg: https://unpkg.com/ccxt@4.3.96/dist/ccxt.browser.min.js
277
277
 
278
278
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
279
279
 
280
280
  ```HTML
281
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.95/dist/ccxt.browser.min.js"></script>
281
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.96/dist/ccxt.browser.min.js"></script>
282
282
  ```
283
283
 
284
284
  Creates a global `ccxt` object: