ccxt 4.4.2__py2.py3-none-any.whl → 4.4.4__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/__init__.py +1 -1
- ccxt/abstract/bitmart.py +1 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +24 -13
- ccxt/async_support/base/ws/cache.py +1 -0
- ccxt/async_support/binance.py +50 -25
- ccxt/async_support/bingx.py +1 -0
- ccxt/async_support/bitfinex2.py +10 -9
- ccxt/async_support/bitget.py +13 -9
- ccxt/async_support/bitmart.py +3 -1
- ccxt/async_support/bitmex.py +14 -13
- ccxt/async_support/bitso.py +8 -7
- ccxt/async_support/bitstamp.py +36 -48
- ccxt/async_support/blofin.py +24 -26
- ccxt/async_support/bybit.py +26 -23
- ccxt/async_support/coinbase.py +31 -10
- ccxt/async_support/coinbaseexchange.py +14 -14
- ccxt/async_support/coinlist.py +9 -8
- ccxt/async_support/coinmetro.py +6 -6
- ccxt/async_support/cryptocom.py +12 -9
- ccxt/async_support/currencycom.py +9 -9
- ccxt/async_support/delta.py +8 -8
- ccxt/async_support/digifinex.py +11 -9
- ccxt/async_support/gate.py +9 -8
- ccxt/async_support/hashkey.py +12 -10
- ccxt/async_support/htx.py +16 -19
- ccxt/async_support/hyperliquid.py +70 -117
- ccxt/async_support/kraken.py +12 -10
- ccxt/async_support/kucoin.py +12 -11
- ccxt/async_support/luno.py +13 -12
- ccxt/async_support/mexc.py +49 -2
- ccxt/async_support/ndax.py +9 -8
- ccxt/async_support/okcoin.py +21 -30
- ccxt/async_support/okx.py +21 -29
- ccxt/async_support/woo.py +10 -9
- ccxt/async_support/woofipro.py +11 -9
- ccxt/async_support/xt.py +12 -7
- ccxt/async_support/zonda.py +9 -8
- ccxt/base/exchange.py +3 -1
- ccxt/binance.py +50 -25
- ccxt/bingx.py +1 -0
- ccxt/bitfinex2.py +10 -9
- ccxt/bitget.py +13 -9
- ccxt/bitmart.py +3 -1
- ccxt/bitmex.py +14 -13
- ccxt/bitso.py +8 -7
- ccxt/bitstamp.py +36 -48
- ccxt/blofin.py +24 -26
- ccxt/bybit.py +26 -23
- ccxt/coinbase.py +31 -10
- ccxt/coinbaseexchange.py +14 -14
- ccxt/coinlist.py +9 -8
- ccxt/coinmetro.py +6 -6
- ccxt/cryptocom.py +12 -9
- ccxt/currencycom.py +9 -9
- ccxt/delta.py +8 -8
- ccxt/digifinex.py +11 -9
- ccxt/gate.py +9 -8
- ccxt/hashkey.py +12 -10
- ccxt/htx.py +16 -19
- ccxt/hyperliquid.py +70 -117
- ccxt/kraken.py +12 -10
- ccxt/kucoin.py +12 -11
- ccxt/luno.py +13 -12
- ccxt/mexc.py +48 -2
- ccxt/ndax.py +9 -8
- ccxt/okcoin.py +21 -30
- ccxt/okx.py +21 -29
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bybit.py +51 -0
- ccxt/pro/cryptocom.py +181 -22
- ccxt/pro/mexc.py +154 -4
- ccxt/pro/okx.py +5 -3
- ccxt/pro/oxfun.py +70 -0
- ccxt/pro/phemex.py +41 -2
- ccxt/pro/woofipro.py +64 -0
- ccxt/test/tests_async.py +1 -1
- ccxt/test/tests_sync.py +1 -1
- ccxt/woo.py +10 -9
- ccxt/woofipro.py +11 -9
- ccxt/xt.py +12 -7
- ccxt/zonda.py +9 -8
- {ccxt-4.4.2.dist-info → ccxt-4.4.4.dist-info}/METADATA +5 -5
- {ccxt-4.4.2.dist-info → ccxt-4.4.4.dist-info}/RECORD +87 -87
- {ccxt-4.4.2.dist-info → ccxt-4.4.4.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.2.dist-info → ccxt-4.4.4.dist-info}/WHEEL +0 -0
- {ccxt-4.4.2.dist-info → ccxt-4.4.4.dist-info}/top_level.txt +0 -0
ccxt/pro/cryptocom.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
import ccxt.async_support
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
12
|
from typing import Any
|
@@ -24,7 +24,8 @@ class cryptocom(ccxt.async_support.cryptocom):
|
|
24
24
|
'ws': True,
|
25
25
|
'watchBalance': True,
|
26
26
|
'watchTicker': True,
|
27
|
-
'watchTickers':
|
27
|
+
'watchTickers': True,
|
28
|
+
'watchBidsAsks': True,
|
28
29
|
'watchMyTrades': True,
|
29
30
|
'watchTrades': True,
|
30
31
|
'watchTradesForSymbols': True,
|
@@ -443,40 +444,198 @@ class cryptocom(ccxt.async_support.cryptocom):
|
|
443
444
|
messageHash = 'unsubscribe:ticker:' + market['symbol']
|
444
445
|
return await self.un_watch_public_multiple('ticker', [market['symbol']], [messageHash], [subMessageHash], [subMessageHash], params)
|
445
446
|
|
447
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
448
|
+
"""
|
449
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
450
|
+
:see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
|
451
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
452
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
453
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
454
|
+
"""
|
455
|
+
await self.load_markets()
|
456
|
+
symbols = self.market_symbols(symbols, None, False)
|
457
|
+
messageHashes = []
|
458
|
+
marketIds = self.market_ids(symbols)
|
459
|
+
for i in range(0, len(marketIds)):
|
460
|
+
marketId = marketIds[i]
|
461
|
+
messageHashes.append('ticker.' + marketId)
|
462
|
+
url = self.urls['api']['ws']['public']
|
463
|
+
id = self.nonce()
|
464
|
+
request: dict = {
|
465
|
+
'method': 'subscribe',
|
466
|
+
'params': {
|
467
|
+
'channels': messageHashes,
|
468
|
+
},
|
469
|
+
'nonce': id,
|
470
|
+
}
|
471
|
+
ticker = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
|
472
|
+
if self.newUpdates:
|
473
|
+
result: dict = {}
|
474
|
+
result[ticker['symbol']] = ticker
|
475
|
+
return result
|
476
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
477
|
+
|
478
|
+
async def un_watch_tickers(self, symbols: Strings = None, params={}) -> Any:
|
479
|
+
"""
|
480
|
+
unWatches a price ticker
|
481
|
+
:see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
|
482
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
483
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
484
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
485
|
+
"""
|
486
|
+
await self.load_markets()
|
487
|
+
symbols = self.market_symbols(symbols, None, False)
|
488
|
+
messageHashes = []
|
489
|
+
subMessageHashes = []
|
490
|
+
marketIds = self.market_ids(symbols)
|
491
|
+
for i in range(0, len(marketIds)):
|
492
|
+
marketId = marketIds[i]
|
493
|
+
symbol = symbols[i]
|
494
|
+
subMessageHashes.append('ticker.' + marketId)
|
495
|
+
messageHashes.append('unsubscribe:ticker:' + symbol)
|
496
|
+
return await self.un_watch_public_multiple('ticker', symbols, messageHashes, subMessageHashes, subMessageHashes, params)
|
497
|
+
|
446
498
|
def handle_ticker(self, client: Client, message):
|
447
499
|
#
|
448
|
-
#
|
449
|
-
#
|
450
|
-
#
|
451
|
-
#
|
452
|
-
#
|
453
|
-
#
|
454
|
-
#
|
455
|
-
#
|
456
|
-
#
|
457
|
-
#
|
458
|
-
#
|
459
|
-
#
|
460
|
-
#
|
461
|
-
#
|
462
|
-
#
|
463
|
-
#
|
464
|
-
#
|
465
|
-
#
|
500
|
+
# {
|
501
|
+
# "instrument_name": "ETHUSD-PERP",
|
502
|
+
# "subscription": "ticker.ETHUSD-PERP",
|
503
|
+
# "channel": "ticker",
|
504
|
+
# "data": [
|
505
|
+
# {
|
506
|
+
# "h": "2400.20",
|
507
|
+
# "l": "2277.10",
|
508
|
+
# "a": "2335.25",
|
509
|
+
# "c": "-0.0022",
|
510
|
+
# "b": "2335.10",
|
511
|
+
# "bs": "5.4000",
|
512
|
+
# "k": "2335.16",
|
513
|
+
# "ks": "1.9970",
|
514
|
+
# "i": "ETHUSD-PERP",
|
515
|
+
# "v": "1305697.6462",
|
516
|
+
# "vv": "3058704939.17",
|
517
|
+
# "oi": "161646.3614",
|
518
|
+
# "t": 1726069647560
|
519
|
+
# }
|
520
|
+
# ]
|
466
521
|
# }
|
467
|
-
# }
|
468
522
|
#
|
523
|
+
self.handle_bid_ask(client, message)
|
469
524
|
messageHash = self.safe_string(message, 'subscription')
|
470
525
|
marketId = self.safe_string(message, 'instrument_name')
|
471
526
|
market = self.safe_market(marketId)
|
472
527
|
data = self.safe_value(message, 'data', [])
|
473
528
|
for i in range(0, len(data)):
|
474
529
|
ticker = data[i]
|
475
|
-
parsed = self.
|
530
|
+
parsed = self.parse_ws_ticker(ticker, market)
|
476
531
|
symbol = parsed['symbol']
|
477
532
|
self.tickers[symbol] = parsed
|
478
533
|
client.resolve(parsed, messageHash)
|
479
534
|
|
535
|
+
def parse_ws_ticker(self, ticker: dict, market: Market = None) -> Ticker:
|
536
|
+
#
|
537
|
+
# {
|
538
|
+
# "h": "2400.20",
|
539
|
+
# "l": "2277.10",
|
540
|
+
# "a": "2335.25",
|
541
|
+
# "c": "-0.0022",
|
542
|
+
# "b": "2335.10",
|
543
|
+
# "bs": "5.4000",
|
544
|
+
# "k": "2335.16",
|
545
|
+
# "ks": "1.9970",
|
546
|
+
# "i": "ETHUSD-PERP",
|
547
|
+
# "v": "1305697.6462",
|
548
|
+
# "vv": "3058704939.17",
|
549
|
+
# "oi": "161646.3614",
|
550
|
+
# "t": 1726069647560
|
551
|
+
# }
|
552
|
+
#
|
553
|
+
timestamp = self.safe_integer(ticker, 't')
|
554
|
+
marketId = self.safe_string(ticker, 'i')
|
555
|
+
market = self.safe_market(marketId, market, '_')
|
556
|
+
quote = self.safe_string(market, 'quote')
|
557
|
+
last = self.safe_string(ticker, 'a')
|
558
|
+
return self.safe_ticker({
|
559
|
+
'symbol': market['symbol'],
|
560
|
+
'timestamp': timestamp,
|
561
|
+
'datetime': self.iso8601(timestamp),
|
562
|
+
'high': self.safe_number(ticker, 'h'),
|
563
|
+
'low': self.safe_number(ticker, 'l'),
|
564
|
+
'bid': self.safe_number(ticker, 'b'),
|
565
|
+
'bidVolume': self.safe_number(ticker, 'bs'),
|
566
|
+
'ask': self.safe_number(ticker, 'k'),
|
567
|
+
'askVolume': self.safe_number(ticker, 'ks'),
|
568
|
+
'vwap': None,
|
569
|
+
'open': None,
|
570
|
+
'close': last,
|
571
|
+
'last': last,
|
572
|
+
'previousClose': None,
|
573
|
+
'change': None,
|
574
|
+
'percentage': self.safe_string(ticker, 'c'),
|
575
|
+
'average': None,
|
576
|
+
'baseVolume': self.safe_string(ticker, 'v'),
|
577
|
+
'quoteVolume': self.safe_string(ticker, 'vv') if (quote == 'USD') else None,
|
578
|
+
'info': ticker,
|
579
|
+
}, market)
|
580
|
+
|
581
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
582
|
+
"""
|
583
|
+
:see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
|
584
|
+
watches best bid & ask for symbols
|
585
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
586
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
587
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
588
|
+
"""
|
589
|
+
await self.load_markets()
|
590
|
+
symbols = self.market_symbols(symbols, None, False)
|
591
|
+
messageHashes = []
|
592
|
+
topics = []
|
593
|
+
marketIds = self.market_ids(symbols)
|
594
|
+
for i in range(0, len(marketIds)):
|
595
|
+
marketId = marketIds[i]
|
596
|
+
messageHashes.append('bidask.' + symbols[i])
|
597
|
+
topics.append('ticker.' + marketId)
|
598
|
+
url = self.urls['api']['ws']['public']
|
599
|
+
id = self.nonce()
|
600
|
+
request: dict = {
|
601
|
+
'method': 'subscribe',
|
602
|
+
'params': {
|
603
|
+
'channels': topics,
|
604
|
+
},
|
605
|
+
'nonce': id,
|
606
|
+
}
|
607
|
+
newTickers = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
|
608
|
+
if self.newUpdates:
|
609
|
+
tickers: dict = {}
|
610
|
+
tickers[newTickers['symbol']] = newTickers
|
611
|
+
return tickers
|
612
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
613
|
+
|
614
|
+
def handle_bid_ask(self, client: Client, message):
|
615
|
+
data = self.safe_list(message, 'data', [])
|
616
|
+
ticker = self.safe_dict(data, 0, {})
|
617
|
+
parsedTicker = self.parse_ws_bid_ask(ticker)
|
618
|
+
symbol = parsedTicker['symbol']
|
619
|
+
self.bidsasks[symbol] = parsedTicker
|
620
|
+
messageHash = 'bidask.' + symbol
|
621
|
+
client.resolve(parsedTicker, messageHash)
|
622
|
+
|
623
|
+
def parse_ws_bid_ask(self, ticker, market=None):
|
624
|
+
marketId = self.safe_string(ticker, 'i')
|
625
|
+
market = self.safe_market(marketId, market)
|
626
|
+
symbol = self.safe_string(market, 'symbol')
|
627
|
+
timestamp = self.safe_integer(ticker, 't')
|
628
|
+
return self.safe_ticker({
|
629
|
+
'symbol': symbol,
|
630
|
+
'timestamp': timestamp,
|
631
|
+
'datetime': self.iso8601(timestamp),
|
632
|
+
'ask': self.safe_string(ticker, 'k'),
|
633
|
+
'askVolume': self.safe_string(ticker, 'ks'),
|
634
|
+
'bid': self.safe_string(ticker, 'b'),
|
635
|
+
'bidVolume': self.safe_string(ticker, 'bs'),
|
636
|
+
'info': ticker,
|
637
|
+
}, market)
|
638
|
+
|
480
639
|
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
481
640
|
"""
|
482
641
|
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
ccxt/pro/mexc.py
CHANGED
@@ -6,10 +6,12 @@
|
|
6
6
|
import ccxt.async_support
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Ticker, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Strings, Ticker, Tickers, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import AuthenticationError
|
13
|
+
from ccxt.base.errors import ArgumentsRequired
|
14
|
+
from ccxt.base.errors import NotSupported
|
13
15
|
|
14
16
|
|
15
17
|
class mexc(ccxt.async_support.mexc):
|
@@ -33,7 +35,8 @@ class mexc(ccxt.async_support.mexc):
|
|
33
35
|
'watchOrderBook': True,
|
34
36
|
'watchOrders': True,
|
35
37
|
'watchTicker': True,
|
36
|
-
'watchTickers':
|
38
|
+
'watchTickers': True,
|
39
|
+
'watchBidsAsks': True,
|
37
40
|
'watchTrades': True,
|
38
41
|
'watchTradesForSymbols': False,
|
39
42
|
},
|
@@ -110,6 +113,7 @@ class mexc(ccxt.async_support.mexc):
|
|
110
113
|
# "t": 1678643605721
|
111
114
|
# }
|
112
115
|
#
|
116
|
+
self.handle_bid_ask(client, message)
|
113
117
|
rawTicker = self.safe_value_2(message, 'd', 'data')
|
114
118
|
marketId = self.safe_string_2(message, 's', 'symbol')
|
115
119
|
timestamp = self.safe_integer(message, 't')
|
@@ -126,6 +130,77 @@ class mexc(ccxt.async_support.mexc):
|
|
126
130
|
messageHash = 'ticker:' + symbol
|
127
131
|
client.resolve(ticker, messageHash)
|
128
132
|
|
133
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
134
|
+
"""
|
135
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
136
|
+
:see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#individual-symbol-book-ticker-streams
|
137
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
|
138
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
139
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
140
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
141
|
+
"""
|
142
|
+
await self.load_markets()
|
143
|
+
symbols = self.market_symbols(symbols, None, False)
|
144
|
+
messageHashes = []
|
145
|
+
marketIds = self.market_ids(symbols)
|
146
|
+
firstMarket = self.market(symbols[0])
|
147
|
+
isSpot = firstMarket['spot']
|
148
|
+
url = self.urls['api']['ws']['spot'] if (isSpot) else self.urls['api']['ws']['swap']
|
149
|
+
request: dict = {}
|
150
|
+
if isSpot:
|
151
|
+
topics = []
|
152
|
+
for i in range(0, len(marketIds)):
|
153
|
+
marketId = marketIds[i]
|
154
|
+
messageHashes.append('ticker:' + symbols[i])
|
155
|
+
topics.append('spot@public.bookTicker.v3.api@' + marketId)
|
156
|
+
request['method'] = 'SUBSCRIPTION'
|
157
|
+
request['params'] = topics
|
158
|
+
else:
|
159
|
+
request['method'] = 'sub.tickers'
|
160
|
+
request['params'] = {}
|
161
|
+
messageHashes.append('ticker')
|
162
|
+
ticker = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
|
163
|
+
if isSpot and self.newUpdates:
|
164
|
+
result: dict = {}
|
165
|
+
result[ticker['symbol']] = ticker
|
166
|
+
return result
|
167
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
168
|
+
|
169
|
+
def handle_tickers(self, client: Client, message):
|
170
|
+
#
|
171
|
+
# {
|
172
|
+
# "channel": "push.tickers",
|
173
|
+
# "data": [
|
174
|
+
# {
|
175
|
+
# "symbol": "ETH_USDT",
|
176
|
+
# "lastPrice": 2324.5,
|
177
|
+
# "riseFallRate": 0.0356,
|
178
|
+
# "fairPrice": 2324.32,
|
179
|
+
# "indexPrice": 2325.44,
|
180
|
+
# "volume24": 25868309,
|
181
|
+
# "amount24": 591752573.9792,
|
182
|
+
# "maxBidPrice": 2557.98,
|
183
|
+
# "minAskPrice": 2092.89,
|
184
|
+
# "lower24Price": 2239.39,
|
185
|
+
# "high24Price": 2332.59,
|
186
|
+
# "timestamp": 1725872514111
|
187
|
+
# }
|
188
|
+
# ],
|
189
|
+
# "ts": 1725872514111
|
190
|
+
# }
|
191
|
+
#
|
192
|
+
data = self.safe_list(message, 'data')
|
193
|
+
topic = 'ticker'
|
194
|
+
result = []
|
195
|
+
for i in range(0, len(data)):
|
196
|
+
ticker = self.parse_ticker(data[i])
|
197
|
+
symbol = ticker['symbol']
|
198
|
+
self.tickers[symbol] = ticker
|
199
|
+
result.append(ticker)
|
200
|
+
messageHash = topic + ':' + symbol
|
201
|
+
client.resolve(ticker, messageHash)
|
202
|
+
client.resolve(result, topic)
|
203
|
+
|
129
204
|
def parse_ws_ticker(self, ticker, market=None):
|
130
205
|
#
|
131
206
|
# spot
|
@@ -158,6 +233,80 @@ class mexc(ccxt.async_support.mexc):
|
|
158
233
|
'info': ticker,
|
159
234
|
}, market)
|
160
235
|
|
236
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
237
|
+
"""
|
238
|
+
:see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#individual-symbol-book-ticker-streams
|
239
|
+
watches best bid & ask for symbols
|
240
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
241
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
242
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
243
|
+
"""
|
244
|
+
await self.load_markets()
|
245
|
+
symbols = self.market_symbols(symbols, None, True, False, True)
|
246
|
+
marketType = None
|
247
|
+
if symbols is None:
|
248
|
+
raise ArgumentsRequired(self.id + 'watchBidsAsks required symbols argument')
|
249
|
+
markets = self.markets_for_symbols(symbols)
|
250
|
+
marketType, params = self.handle_market_type_and_params('watchBidsAsks', markets[0], params)
|
251
|
+
isSpot = marketType == 'spot'
|
252
|
+
if not isSpot:
|
253
|
+
raise NotSupported(self.id + 'watchBidsAsks only support spot market')
|
254
|
+
messageHashes = []
|
255
|
+
topics = []
|
256
|
+
for i in range(0, len(symbols)):
|
257
|
+
if isSpot:
|
258
|
+
market = self.market(symbols[i])
|
259
|
+
topics.append('spot@public.bookTicker.v3.api@' + market['id'])
|
260
|
+
messageHashes.append('bidask:' + symbols[i])
|
261
|
+
url = self.urls['api']['ws']['spot']
|
262
|
+
request: dict = {
|
263
|
+
'method': 'SUBSCRIPTION',
|
264
|
+
'params': topics,
|
265
|
+
}
|
266
|
+
ticker = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
|
267
|
+
if self.newUpdates:
|
268
|
+
tickers: dict = {}
|
269
|
+
tickers[ticker['symbol']] = ticker
|
270
|
+
return tickers
|
271
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
272
|
+
|
273
|
+
def handle_bid_ask(self, client: Client, message):
|
274
|
+
#
|
275
|
+
# {
|
276
|
+
# "c": "spot@public.bookTicker.v3.api@BTCUSDT",
|
277
|
+
# "d": {
|
278
|
+
# "A": "4.70432",
|
279
|
+
# "B": "6.714863",
|
280
|
+
# "a": "20744.54",
|
281
|
+
# "b": "20744.17"
|
282
|
+
# },
|
283
|
+
# "s": "BTCUSDT",
|
284
|
+
# "t": 1678643605721
|
285
|
+
# }
|
286
|
+
#
|
287
|
+
parsedTicker = self.parse_ws_bid_ask(message)
|
288
|
+
symbol = parsedTicker['symbol']
|
289
|
+
self.bidsasks[symbol] = parsedTicker
|
290
|
+
messageHash = 'bidask:' + symbol
|
291
|
+
client.resolve(parsedTicker, messageHash)
|
292
|
+
|
293
|
+
def parse_ws_bid_ask(self, ticker, market=None):
|
294
|
+
data = self.safe_dict(ticker, 'd')
|
295
|
+
marketId = self.safe_string(ticker, 's')
|
296
|
+
market = self.safe_market(marketId, market)
|
297
|
+
symbol = self.safe_string(market, 'symbol')
|
298
|
+
timestamp = self.safe_integer(ticker, 't')
|
299
|
+
return self.safe_ticker({
|
300
|
+
'symbol': symbol,
|
301
|
+
'timestamp': timestamp,
|
302
|
+
'datetime': self.iso8601(timestamp),
|
303
|
+
'ask': self.safe_number(data, 'a'),
|
304
|
+
'askVolume': self.safe_number(data, 'A'),
|
305
|
+
'bid': self.safe_number(data, 'b'),
|
306
|
+
'bidVolume': self.safe_number(data, 'B'),
|
307
|
+
'info': ticker,
|
308
|
+
}, market)
|
309
|
+
|
161
310
|
async def watch_spot_public(self, channel, messageHash, params={}):
|
162
311
|
url = self.urls['api']['ws']['spot']
|
163
312
|
request: dict = {
|
@@ -1073,8 +1222,8 @@ class mexc(ccxt.async_support.mexc):
|
|
1073
1222
|
# "code": 0,
|
1074
1223
|
# "msg": "spot@public.increase.depth.v3.api@BTCUSDT"
|
1075
1224
|
# }
|
1076
|
-
#
|
1077
|
-
msg = self.safe_string(message, 'msg')
|
1225
|
+
# Set the default to an empty string if the message is empty during the test.
|
1226
|
+
msg = self.safe_string(message, 'msg', '')
|
1078
1227
|
if msg == 'PONG':
|
1079
1228
|
self.handle_pong(client, message)
|
1080
1229
|
elif msg.find('@') > -1:
|
@@ -1110,6 +1259,7 @@ class mexc(ccxt.async_support.mexc):
|
|
1110
1259
|
'push.kline': self.handle_ohlcv,
|
1111
1260
|
'public.bookTicker.v3.api': self.handle_ticker,
|
1112
1261
|
'push.ticker': self.handle_ticker,
|
1262
|
+
'push.tickers': self.handle_tickers,
|
1113
1263
|
'public.increase.depth.v3.api': self.handle_order_book,
|
1114
1264
|
'push.depth': self.handle_order_book,
|
1115
1265
|
'private.orders.v3.api': self.handle_order,
|
ccxt/pro/okx.py
CHANGED
@@ -1340,8 +1340,10 @@ class okx(ccxt.async_support.okx):
|
|
1340
1340
|
},
|
1341
1341
|
],
|
1342
1342
|
}
|
1343
|
-
|
1344
|
-
|
1343
|
+
# Only add params['access'] to prevent sending custom parameters, such.
|
1344
|
+
if 'access' in params:
|
1345
|
+
request['access'] = params['access']
|
1346
|
+
self.watch(url, messageHash, request, messageHash)
|
1345
1347
|
return await future
|
1346
1348
|
|
1347
1349
|
async def watch_balance(self, params={}) -> Balances:
|
@@ -1499,7 +1501,7 @@ class okx(ccxt.async_support.okx):
|
|
1499
1501
|
'channel': 'positions',
|
1500
1502
|
'instType': 'ANY',
|
1501
1503
|
}
|
1502
|
-
args = [arg]
|
1504
|
+
args = [self.extend(arg, params)]
|
1503
1505
|
nonSymbolRequest: dict = {
|
1504
1506
|
'op': 'subscribe',
|
1505
1507
|
'args': args,
|
ccxt/pro/oxfun.py
CHANGED
@@ -30,6 +30,7 @@ class oxfun(ccxt.async_support.oxfun):
|
|
30
30
|
'watchMyTrades': False,
|
31
31
|
'watchTicker': True,
|
32
32
|
'watchTickers': True,
|
33
|
+
'watchBidsAsks': True,
|
33
34
|
'watchBalance': True,
|
34
35
|
'createOrderWs': True,
|
35
36
|
'editOrderWs': True,
|
@@ -466,6 +467,73 @@ class oxfun(ccxt.async_support.oxfun):
|
|
466
467
|
self.tickers[symbol] = ticker
|
467
468
|
client.resolve(ticker, messageHash)
|
468
469
|
|
470
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
471
|
+
"""
|
472
|
+
:see: https://docs.ox.fun/?json#best-bid-ask
|
473
|
+
watches best bid & ask for symbols
|
474
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
475
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
476
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
477
|
+
"""
|
478
|
+
await self.load_markets()
|
479
|
+
symbols = self.market_symbols(symbols, None, False)
|
480
|
+
messageHashes = []
|
481
|
+
args = []
|
482
|
+
for i in range(0, len(symbols)):
|
483
|
+
market = self.market(symbols[i])
|
484
|
+
args.append('bestBidAsk:' + market['id'])
|
485
|
+
messageHashes.append('bidask:' + market['symbol'])
|
486
|
+
newTickers = await self.subscribe_multiple(messageHashes, args, params)
|
487
|
+
if self.newUpdates:
|
488
|
+
tickers: dict = {}
|
489
|
+
tickers[newTickers['symbol']] = newTickers
|
490
|
+
return tickers
|
491
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
492
|
+
|
493
|
+
def handle_bid_ask(self, client: Client, message):
|
494
|
+
#
|
495
|
+
# {
|
496
|
+
# "table": "bestBidAsk",
|
497
|
+
# "data": {
|
498
|
+
# "ask": [
|
499
|
+
# 19045.0,
|
500
|
+
# 1.0
|
501
|
+
# ],
|
502
|
+
# "checksum": 3790706311,
|
503
|
+
# "marketCode": "BTC-USD-SWAP-LIN",
|
504
|
+
# "bid": [
|
505
|
+
# 19015.0,
|
506
|
+
# 1.0
|
507
|
+
# ],
|
508
|
+
# "timestamp": "1665456882928"
|
509
|
+
# }
|
510
|
+
# }
|
511
|
+
#
|
512
|
+
data = self.safe_dict(message, 'data', {})
|
513
|
+
parsedTicker = self.parse_ws_bid_ask(data)
|
514
|
+
symbol = parsedTicker['symbol']
|
515
|
+
self.bidsasks[symbol] = parsedTicker
|
516
|
+
messageHash = 'bidask:' + symbol
|
517
|
+
client.resolve(parsedTicker, messageHash)
|
518
|
+
|
519
|
+
def parse_ws_bid_ask(self, ticker, market=None):
|
520
|
+
marketId = self.safe_string(ticker, 'marketCode')
|
521
|
+
market = self.safe_market(marketId, market)
|
522
|
+
symbol = self.safe_string(market, 'symbol')
|
523
|
+
timestamp = self.safe_integer(ticker, 'timestamp')
|
524
|
+
ask = self.safe_list(ticker, 'ask', [])
|
525
|
+
bid = self.safe_list(ticker, 'bid', [])
|
526
|
+
return self.safe_ticker({
|
527
|
+
'symbol': symbol,
|
528
|
+
'timestamp': timestamp,
|
529
|
+
'datetime': self.iso8601(timestamp),
|
530
|
+
'ask': self.safe_number(ask, 0),
|
531
|
+
'askVolume': self.safe_number(ask, 1),
|
532
|
+
'bid': self.safe_number(bid, 0),
|
533
|
+
'bidVolume': self.safe_number(bid, 1),
|
534
|
+
'info': ticker,
|
535
|
+
}, market)
|
536
|
+
|
469
537
|
async def watch_balance(self, params={}) -> Balances:
|
470
538
|
"""
|
471
539
|
:see: https://docs.ox.fun/?json#balance-channel
|
@@ -943,6 +1011,8 @@ class oxfun(ccxt.async_support.oxfun):
|
|
943
1011
|
self.handle_positions(client, message)
|
944
1012
|
if table.find('order') > -1:
|
945
1013
|
self.handle_orders(client, message)
|
1014
|
+
if table == 'bestBidAsk':
|
1015
|
+
self.handle_bid_ask(client, message)
|
946
1016
|
else:
|
947
1017
|
if event == 'login':
|
948
1018
|
self.handle_authentication_message(client, message)
|
ccxt/pro/phemex.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
import ccxt.async_support
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Ticker, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Strings, Ticker, Tickers, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import AuthenticationError
|
@@ -20,7 +20,7 @@ class phemex(ccxt.async_support.phemex):
|
|
20
20
|
'has': {
|
21
21
|
'ws': True,
|
22
22
|
'watchTicker': True,
|
23
|
-
'watchTickers':
|
23
|
+
'watchTickers': True,
|
24
24
|
'watchTrades': True,
|
25
25
|
'watchMyTrades': True,
|
26
26
|
'watchOrders': True,
|
@@ -504,6 +504,45 @@ class phemex(ccxt.async_support.phemex):
|
|
504
504
|
request = self.deep_extend(subscribe, params)
|
505
505
|
return await self.watch(url, messageHash, request, subscriptionHash)
|
506
506
|
|
507
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
508
|
+
"""
|
509
|
+
:see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#subscribe-24-hours-ticker
|
510
|
+
:see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#subscribe-24-hours-ticker
|
511
|
+
:see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#subscribe-24-hours-ticker
|
512
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
513
|
+
:param str[] [symbols]: unified symbol of the market to fetch the ticker for
|
514
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
515
|
+
:param str [params.channel]: the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
|
516
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
517
|
+
"""
|
518
|
+
await self.load_markets()
|
519
|
+
symbols = self.market_symbols(symbols, None, False)
|
520
|
+
first = symbols[0]
|
521
|
+
market = self.market(first)
|
522
|
+
isSwap = market['swap']
|
523
|
+
settleIsUSDT = market['settle'] == 'USDT'
|
524
|
+
name = 'spot_market24h'
|
525
|
+
if isSwap:
|
526
|
+
name = 'perp_market24h_pack_p' if settleIsUSDT else 'market24h'
|
527
|
+
url = self.urls['api']['ws']
|
528
|
+
requestId = self.request_id()
|
529
|
+
subscriptionHash = name + '.subscribe'
|
530
|
+
messageHashes = []
|
531
|
+
for i in range(0, len(symbols)):
|
532
|
+
messageHashes.append('ticker:' + symbols[i])
|
533
|
+
subscribe: dict = {
|
534
|
+
'method': subscriptionHash,
|
535
|
+
'id': requestId,
|
536
|
+
'params': [],
|
537
|
+
}
|
538
|
+
request = self.deep_extend(subscribe, params)
|
539
|
+
ticker = await self.watch_multiple(url, messageHashes, request, messageHashes)
|
540
|
+
if self.newUpdates:
|
541
|
+
result: dict = {}
|
542
|
+
result[ticker['symbol']] = ticker
|
543
|
+
return result
|
544
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
545
|
+
|
507
546
|
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
508
547
|
"""
|
509
548
|
:see: https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#subscribe-trade
|