ccxt 4.4.1__py2.py3-none-any.whl → 4.4.3__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 +1 -1
- ccxt/async_support/binance.py +81 -18
- ccxt/async_support/bitmart.py +3 -1
- ccxt/async_support/bitstamp.py +24 -36
- ccxt/async_support/bybit.py +2 -0
- ccxt/async_support/cryptocom.py +3 -2
- ccxt/async_support/currencycom.py +1 -2
- ccxt/async_support/htx.py +1 -1
- ccxt/async_support/mexc.py +76 -1
- ccxt/async_support/xt.py +6 -2
- ccxt/base/exchange.py +53 -1
- ccxt/base/types.py +2 -2
- ccxt/binance.py +81 -18
- ccxt/bitmart.py +3 -1
- ccxt/bitstamp.py +24 -36
- ccxt/bybit.py +2 -0
- ccxt/cryptocom.py +3 -2
- ccxt/currencycom.py +1 -2
- ccxt/htx.py +1 -1
- ccxt/mexc.py +76 -1
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +3 -47
- ccxt/pro/bitget.py +1 -7
- ccxt/pro/bitmex.py +11 -1
- ccxt/pro/bybit.py +2 -41
- ccxt/pro/cryptocom.py +183 -53
- ccxt/pro/gate.py +1 -8
- ccxt/pro/hyperliquid.py +4 -29
- ccxt/pro/kucoin.py +2 -43
- ccxt/pro/kucoinfutures.py +122 -0
- ccxt/pro/mexc.py +76 -4
- ccxt/pro/okx.py +13 -34
- ccxt/pro/oxfun.py +70 -0
- ccxt/pro/phemex.py +41 -2
- ccxt/pro/woofipro.py +64 -0
- ccxt/xt.py +6 -2
- {ccxt-4.4.1.dist-info → ccxt-4.4.3.dist-info}/METADATA +5 -5
- {ccxt-4.4.1.dist-info → ccxt-4.4.3.dist-info}/RECORD +44 -44
- {ccxt-4.4.1.dist-info → ccxt-4.4.3.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.1.dist-info → ccxt-4.4.3.dist-info}/WHEEL +0 -0
- {ccxt-4.4.1.dist-info → ccxt-4.4.3.dist-info}/top_level.txt +0 -0
ccxt/pro/kucoin.py
CHANGED
@@ -11,7 +11,6 @@ from typing import List
|
|
11
11
|
from typing import Any
|
12
12
|
from ccxt.base.errors import ExchangeError
|
13
13
|
from ccxt.base.errors import ArgumentsRequired
|
14
|
-
from ccxt.base.errors import UnsubscribeError
|
15
14
|
|
16
15
|
|
17
16
|
class kucoin(ccxt.async_support.kucoin):
|
@@ -502,8 +501,6 @@ class kucoin(ccxt.async_support.kucoin):
|
|
502
501
|
unWatches trades stream
|
503
502
|
:see: https://www.kucoin.com/docs/websocket/spot-trading/public-channels/match-execution-data
|
504
503
|
:param str symbol: unified symbol of the market to fetch trades for
|
505
|
-
:param int [since]: timestamp in ms of the earliest trade to fetch
|
506
|
-
:param int [limit]: the maximum amount of trades to fetch
|
507
504
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
508
505
|
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
509
506
|
"""
|
@@ -851,46 +848,8 @@ class kucoin(ccxt.async_support.kucoin):
|
|
851
848
|
for i in range(0, len(messageHashes)):
|
852
849
|
messageHash = messageHashes[i]
|
853
850
|
subHash = subMessageHashes[i]
|
854
|
-
|
855
|
-
|
856
|
-
if subHash in client.subscriptions:
|
857
|
-
del client.subscriptions[subHash]
|
858
|
-
error = UnsubscribeError(self.id + ' ' + subHash)
|
859
|
-
client.reject(error, subHash)
|
860
|
-
client.resolve(True, messageHash)
|
861
|
-
self.clean_cache(subscription)
|
862
|
-
|
863
|
-
def clean_cache(self, subscription: dict):
|
864
|
-
topic = self.safe_string(subscription, 'topic')
|
865
|
-
symbols = self.safe_list(subscription, 'symbols', [])
|
866
|
-
symbolsLength = len(symbols)
|
867
|
-
if symbolsLength > 0:
|
868
|
-
for i in range(0, len(symbols)):
|
869
|
-
symbol = symbols[i]
|
870
|
-
if topic == 'trades':
|
871
|
-
if symbol in self.trades:
|
872
|
-
del self.trades[symbol]
|
873
|
-
elif topic == 'orderbook':
|
874
|
-
if symbol in self.orderbooks:
|
875
|
-
del self.orderbooks[symbol]
|
876
|
-
elif topic == 'ticker':
|
877
|
-
if symbol in self.tickers:
|
878
|
-
del self.tickers[symbol]
|
879
|
-
else:
|
880
|
-
if topic == 'myTrades':
|
881
|
-
# don't reset self.myTrades directly here
|
882
|
-
# because in c# we need to use a different object
|
883
|
-
keys = list(self.myTrades.keys())
|
884
|
-
for i in range(0, len(keys)):
|
885
|
-
del self.myTrades[keys[i]]
|
886
|
-
elif topic == 'orders':
|
887
|
-
orderSymbols = list(self.orders.keys())
|
888
|
-
for i in range(0, len(orderSymbols)):
|
889
|
-
del self.orders[orderSymbols[i]]
|
890
|
-
elif topic == 'ticker':
|
891
|
-
tickerSymbols = list(self.tickers.keys())
|
892
|
-
for i in range(0, len(tickerSymbols)):
|
893
|
-
del self.tickers[tickerSymbols[i]]
|
851
|
+
self.clean_unsubscription(client, subHash, messageHash)
|
852
|
+
self.clean_cache(subscription)
|
894
853
|
|
895
854
|
def handle_system_status(self, client: Client, message):
|
896
855
|
#
|
ccxt/pro/kucoinfutures.py
CHANGED
@@ -8,6 +8,7 @@ from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById,
|
|
8
8
|
from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
|
9
9
|
from ccxt.async_support.base.ws.client import Client
|
10
10
|
from typing import List
|
11
|
+
from typing import Any
|
11
12
|
from ccxt.base.errors import ExchangeError
|
12
13
|
from ccxt.base.errors import ArgumentsRequired
|
13
14
|
|
@@ -175,6 +176,24 @@ class kucoinfutures(ccxt.async_support.kucoinfutures):
|
|
175
176
|
}
|
176
177
|
return await self.watch_multiple(url, messageHashes, self.extend(request, params), subscriptionHashes, subscriptionArgs)
|
177
178
|
|
179
|
+
async def un_subscribe_multiple(self, url, messageHashes, topic, subscriptionHashes, params={}, subscription: dict = None):
|
180
|
+
requestId = str(self.request_id())
|
181
|
+
request: dict = {
|
182
|
+
'id': requestId,
|
183
|
+
'type': 'unsubscribe',
|
184
|
+
'topic': topic,
|
185
|
+
'response': True,
|
186
|
+
}
|
187
|
+
message = self.extend(request, params)
|
188
|
+
if subscription is not None:
|
189
|
+
subscription[requestId] = requestId
|
190
|
+
client = self.client(url)
|
191
|
+
for i in range(0, len(subscriptionHashes)):
|
192
|
+
subscriptionHash = subscriptionHashes[i]
|
193
|
+
if not (subscriptionHash in client.subscriptions):
|
194
|
+
client.subscriptions[requestId] = subscriptionHash
|
195
|
+
return await self.watch_multiple(url, messageHashes, message, subscriptionHashes, subscription)
|
196
|
+
|
178
197
|
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
179
198
|
"""
|
180
199
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
@@ -526,6 +545,44 @@ class kucoinfutures(ccxt.async_support.kucoinfutures):
|
|
526
545
|
limit = trades.getLimit(tradeSymbol, limit)
|
527
546
|
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
528
547
|
|
548
|
+
async def un_watch_trades(self, symbol: str, params={}) -> Any:
|
549
|
+
"""
|
550
|
+
unWatches trades stream
|
551
|
+
:see: https://docs.kucoin.com/futures/#execution-data
|
552
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
553
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
554
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
555
|
+
"""
|
556
|
+
return await self.un_watch_trades_for_symbols([symbol], params)
|
557
|
+
|
558
|
+
async def un_watch_trades_for_symbols(self, symbols: List[str], params={}) -> Any:
|
559
|
+
"""
|
560
|
+
get the list of most recent trades for a particular symbol
|
561
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
562
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
563
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
564
|
+
"""
|
565
|
+
await self.load_markets()
|
566
|
+
symbols = self.market_symbols(symbols, None, False)
|
567
|
+
url = await self.negotiate(False)
|
568
|
+
symbols = self.market_symbols(symbols)
|
569
|
+
marketIds = self.market_ids(symbols)
|
570
|
+
topic = '/contractMarket/execution:' + ','.join(marketIds)
|
571
|
+
subscriptionHashes = []
|
572
|
+
messageHashes = []
|
573
|
+
for i in range(0, len(symbols)):
|
574
|
+
symbol = symbols[i]
|
575
|
+
messageHashes.append('unsubscribe:trades:' + symbol)
|
576
|
+
subscriptionHashes.append('trades:' + symbol)
|
577
|
+
subscription = {
|
578
|
+
'messageHashes': messageHashes,
|
579
|
+
'subMessageHashes': subscriptionHashes,
|
580
|
+
'topic': 'trades',
|
581
|
+
'unsubscribe': True,
|
582
|
+
'symbols': symbols,
|
583
|
+
}
|
584
|
+
return await self.un_subscribe_multiple(url, messageHashes, topic, messageHashes, params, subscription)
|
585
|
+
|
529
586
|
def handle_trade(self, client: Client, message):
|
530
587
|
#
|
531
588
|
# {
|
@@ -651,6 +708,7 @@ class kucoinfutures(ccxt.async_support.kucoinfutures):
|
|
651
708
|
async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
|
652
709
|
"""
|
653
710
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
711
|
+
:see: https://docs.kucoin.com/futures/#level-2-market-data
|
654
712
|
:param str[] symbols: unified array of symbols
|
655
713
|
:param int [limit]: the maximum amount of order book entries to return
|
656
714
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -680,6 +738,43 @@ class kucoinfutures(ccxt.async_support.kucoinfutures):
|
|
680
738
|
orderbook = await self.subscribe_multiple(url, messageHashes, topic, subscriptionHashes, subscriptionArgs, params)
|
681
739
|
return orderbook.limit()
|
682
740
|
|
741
|
+
async def un_watch_order_book(self, symbol: str, params={}) -> Any:
|
742
|
+
"""
|
743
|
+
unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
744
|
+
:see: https://docs.kucoin.com/futures/#level-2-market-data
|
745
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
746
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
747
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
748
|
+
"""
|
749
|
+
return await self.un_watch_order_book_for_symbols([symbol], params)
|
750
|
+
|
751
|
+
async def un_watch_order_book_for_symbols(self, symbols: List[str], params={}) -> Any:
|
752
|
+
"""
|
753
|
+
unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
754
|
+
:param str[] symbols: unified array of symbols
|
755
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
756
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
757
|
+
"""
|
758
|
+
await self.load_markets()
|
759
|
+
symbols = self.market_symbols(symbols)
|
760
|
+
marketIds = self.market_ids(symbols)
|
761
|
+
url = await self.negotiate(False)
|
762
|
+
topic = '/contractMarket/level2:' + ','.join(marketIds)
|
763
|
+
subscriptionHashes = []
|
764
|
+
messageHashes = []
|
765
|
+
for i in range(0, len(symbols)):
|
766
|
+
symbol = symbols[i]
|
767
|
+
messageHashes.append('unsubscribe:orderbook:' + symbol)
|
768
|
+
subscriptionHashes.append('orderbook:' + symbol)
|
769
|
+
subscription = {
|
770
|
+
'messageHashes': messageHashes,
|
771
|
+
'symbols': symbols,
|
772
|
+
'unsubscribe': True,
|
773
|
+
'topic': 'orderbook',
|
774
|
+
'subMessageHashes': subscriptionHashes,
|
775
|
+
}
|
776
|
+
return await self.un_subscribe_multiple(url, messageHashes, topic, messageHashes, params, subscription)
|
777
|
+
|
683
778
|
def handle_delta(self, orderbook, delta):
|
684
779
|
orderbook['nonce'] = self.safe_integer(delta, 'sequence')
|
685
780
|
timestamp = self.safe_integer(delta, 'timestamp')
|
@@ -1067,6 +1162,32 @@ class kucoinfutures(ccxt.async_support.kucoinfutures):
|
|
1067
1162
|
self.options['urls'][type] = None
|
1068
1163
|
self.handle_errors(None, None, client.url, None, None, data, message, None, None)
|
1069
1164
|
|
1165
|
+
def handle_subscription_status(self, client: Client, message):
|
1166
|
+
#
|
1167
|
+
# {
|
1168
|
+
# "id": "1578090438322",
|
1169
|
+
# "type": "ack"
|
1170
|
+
# }
|
1171
|
+
#
|
1172
|
+
id = self.safe_string(message, 'id')
|
1173
|
+
if not (id in client.subscriptions):
|
1174
|
+
return
|
1175
|
+
subscriptionHash = self.safe_string(client.subscriptions, id)
|
1176
|
+
subscription = self.safe_value(client.subscriptions, subscriptionHash)
|
1177
|
+
del client.subscriptions[id]
|
1178
|
+
method = self.safe_value(subscription, 'method')
|
1179
|
+
if method is not None:
|
1180
|
+
method(client, message, subscription)
|
1181
|
+
isUnSub = self.safe_bool(subscription, 'unsubscribe', False)
|
1182
|
+
if isUnSub:
|
1183
|
+
messageHashes = self.safe_list(subscription, 'messageHashes', [])
|
1184
|
+
subMessageHashes = self.safe_list(subscription, 'subMessageHashes', [])
|
1185
|
+
for i in range(0, len(messageHashes)):
|
1186
|
+
messageHash = messageHashes[i]
|
1187
|
+
subHash = subMessageHashes[i]
|
1188
|
+
self.clean_unsubscription(client, subHash, messageHash)
|
1189
|
+
self.clean_cache(subscription)
|
1190
|
+
|
1070
1191
|
def handle_message(self, client: Client, message):
|
1071
1192
|
type = self.safe_string(message, 'type')
|
1072
1193
|
methods: dict = {
|
@@ -1075,6 +1196,7 @@ class kucoinfutures(ccxt.async_support.kucoinfutures):
|
|
1075
1196
|
'message': self.handle_subject,
|
1076
1197
|
'pong': self.handle_pong,
|
1077
1198
|
'error': self.handle_error_message,
|
1199
|
+
'ack': self.handle_subscription_status,
|
1078
1200
|
}
|
1079
1201
|
method = self.safe_value(methods, type)
|
1080
1202
|
if method is not None:
|
ccxt/pro/mexc.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
|
@@ -33,7 +33,7 @@ class mexc(ccxt.async_support.mexc):
|
|
33
33
|
'watchOrderBook': True,
|
34
34
|
'watchOrders': True,
|
35
35
|
'watchTicker': True,
|
36
|
-
'watchTickers':
|
36
|
+
'watchTickers': True,
|
37
37
|
'watchTrades': True,
|
38
38
|
'watchTradesForSymbols': False,
|
39
39
|
},
|
@@ -126,6 +126,77 @@ class mexc(ccxt.async_support.mexc):
|
|
126
126
|
messageHash = 'ticker:' + symbol
|
127
127
|
client.resolve(ticker, messageHash)
|
128
128
|
|
129
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
130
|
+
"""
|
131
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
132
|
+
:see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#individual-symbol-book-ticker-streams
|
133
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
|
134
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
135
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
136
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
137
|
+
"""
|
138
|
+
await self.load_markets()
|
139
|
+
symbols = self.market_symbols(symbols, None, False)
|
140
|
+
messageHashes = []
|
141
|
+
marketIds = self.market_ids(symbols)
|
142
|
+
firstMarket = self.market(symbols[0])
|
143
|
+
isSpot = firstMarket['spot']
|
144
|
+
url = self.urls['api']['ws']['spot'] if (isSpot) else self.urls['api']['ws']['swap']
|
145
|
+
request: dict = {}
|
146
|
+
if isSpot:
|
147
|
+
topics = []
|
148
|
+
for i in range(0, len(marketIds)):
|
149
|
+
marketId = marketIds[i]
|
150
|
+
messageHashes.append('ticker:' + symbols[i])
|
151
|
+
topics.append('spot@public.bookTicker.v3.api@' + marketId)
|
152
|
+
request['method'] = 'SUBSCRIPTION'
|
153
|
+
request['params'] = topics
|
154
|
+
else:
|
155
|
+
request['method'] = 'sub.tickers'
|
156
|
+
request['params'] = {}
|
157
|
+
messageHashes.append('ticker')
|
158
|
+
ticker = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
|
159
|
+
if isSpot and self.newUpdates:
|
160
|
+
result: dict = {}
|
161
|
+
result[ticker['symbol']] = ticker
|
162
|
+
return result
|
163
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
164
|
+
|
165
|
+
def handle_tickers(self, client: Client, message):
|
166
|
+
#
|
167
|
+
# {
|
168
|
+
# "channel": "push.tickers",
|
169
|
+
# "data": [
|
170
|
+
# {
|
171
|
+
# "symbol": "ETH_USDT",
|
172
|
+
# "lastPrice": 2324.5,
|
173
|
+
# "riseFallRate": 0.0356,
|
174
|
+
# "fairPrice": 2324.32,
|
175
|
+
# "indexPrice": 2325.44,
|
176
|
+
# "volume24": 25868309,
|
177
|
+
# "amount24": 591752573.9792,
|
178
|
+
# "maxBidPrice": 2557.98,
|
179
|
+
# "minAskPrice": 2092.89,
|
180
|
+
# "lower24Price": 2239.39,
|
181
|
+
# "high24Price": 2332.59,
|
182
|
+
# "timestamp": 1725872514111
|
183
|
+
# }
|
184
|
+
# ],
|
185
|
+
# "ts": 1725872514111
|
186
|
+
# }
|
187
|
+
#
|
188
|
+
data = self.safe_list(message, 'data')
|
189
|
+
topic = 'ticker'
|
190
|
+
result = []
|
191
|
+
for i in range(0, len(data)):
|
192
|
+
ticker = self.parse_ticker(data[i])
|
193
|
+
symbol = ticker['symbol']
|
194
|
+
self.tickers[symbol] = ticker
|
195
|
+
result.append(ticker)
|
196
|
+
messageHash = topic + ':' + symbol
|
197
|
+
client.resolve(ticker, messageHash)
|
198
|
+
client.resolve(result, topic)
|
199
|
+
|
129
200
|
def parse_ws_ticker(self, ticker, market=None):
|
130
201
|
#
|
131
202
|
# spot
|
@@ -1073,8 +1144,8 @@ class mexc(ccxt.async_support.mexc):
|
|
1073
1144
|
# "code": 0,
|
1074
1145
|
# "msg": "spot@public.increase.depth.v3.api@BTCUSDT"
|
1075
1146
|
# }
|
1076
|
-
#
|
1077
|
-
msg = self.safe_string(message, 'msg')
|
1147
|
+
# Set the default to an empty string if the message is empty during the test.
|
1148
|
+
msg = self.safe_string(message, 'msg', '')
|
1078
1149
|
if msg == 'PONG':
|
1079
1150
|
self.handle_pong(client, message)
|
1080
1151
|
elif msg.find('@') > -1:
|
@@ -1110,6 +1181,7 @@ class mexc(ccxt.async_support.mexc):
|
|
1110
1181
|
'push.kline': self.handle_ohlcv,
|
1111
1182
|
'public.bookTicker.v3.api': self.handle_ticker,
|
1112
1183
|
'push.ticker': self.handle_ticker,
|
1184
|
+
'push.tickers': self.handle_tickers,
|
1113
1185
|
'public.increase.depth.v3.api': self.handle_order_book,
|
1114
1186
|
'push.depth': self.handle_order_book,
|
1115
1187
|
'private.orders.v3.api': self.handle_order,
|
ccxt/pro/okx.py
CHANGED
@@ -16,7 +16,6 @@ from ccxt.base.errors import ArgumentsRequired
|
|
16
16
|
from ccxt.base.errors import BadRequest
|
17
17
|
from ccxt.base.errors import InvalidNonce
|
18
18
|
from ccxt.base.errors import ChecksumError
|
19
|
-
from ccxt.base.errors import UnsubscribeError
|
20
19
|
|
21
20
|
|
22
21
|
class okx(ccxt.async_support.okx):
|
@@ -1341,8 +1340,10 @@ class okx(ccxt.async_support.okx):
|
|
1341
1340
|
},
|
1342
1341
|
],
|
1343
1342
|
}
|
1344
|
-
|
1345
|
-
|
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)
|
1346
1347
|
return await future
|
1347
1348
|
|
1348
1349
|
async def watch_balance(self, params={}) -> Balances:
|
@@ -1500,7 +1501,7 @@ class okx(ccxt.async_support.okx):
|
|
1500
1501
|
'channel': 'positions',
|
1501
1502
|
'instType': 'ANY',
|
1502
1503
|
}
|
1503
|
-
args = [arg]
|
1504
|
+
args = [self.extend(arg, params)]
|
1504
1505
|
nonSymbolRequest: dict = {
|
1505
1506
|
'op': 'subscribe',
|
1506
1507
|
'args': args,
|
@@ -2162,54 +2163,32 @@ class okx(ccxt.async_support.okx):
|
|
2162
2163
|
def handle_un_subscription_trades(self, client: Client, symbol: str):
|
2163
2164
|
subMessageHash = 'trades:' + symbol
|
2164
2165
|
messageHash = 'unsubscribe:trades:' + symbol
|
2165
|
-
|
2166
|
-
|
2167
|
-
|
2168
|
-
del client.subscriptions[messageHash]
|
2169
|
-
del self.trades[symbol]
|
2170
|
-
error = UnsubscribeError(self.id + ' ' + subMessageHash)
|
2171
|
-
client.reject(error, subMessageHash)
|
2172
|
-
client.resolve(True, messageHash)
|
2166
|
+
self.clean_unsubscription(client, subMessageHash, messageHash)
|
2167
|
+
if symbol in self.trades:
|
2168
|
+
del self.trades[symbol]
|
2173
2169
|
|
2174
2170
|
def handle_unsubscription_order_book(self, client: Client, symbol: str, channel: str):
|
2175
2171
|
subMessageHash = channel + ':' + symbol
|
2176
2172
|
messageHash = 'unsubscribe:orderbook:' + symbol
|
2177
|
-
|
2178
|
-
|
2179
|
-
|
2180
|
-
del client.subscriptions[messageHash]
|
2181
|
-
del self.orderbooks[symbol]
|
2182
|
-
error = UnsubscribeError(self.id + ' ' + subMessageHash)
|
2183
|
-
client.reject(error, subMessageHash)
|
2184
|
-
client.resolve(True, messageHash)
|
2173
|
+
self.clean_unsubscription(client, subMessageHash, messageHash)
|
2174
|
+
if symbol in self.orderbooks:
|
2175
|
+
del self.orderbooks[symbol]
|
2185
2176
|
|
2186
2177
|
def handle_unsubscription_ohlcv(self, client: Client, symbol: str, channel: str):
|
2187
2178
|
tf = channel.replace('candle', '')
|
2188
2179
|
timeframe = self.find_timeframe(tf)
|
2189
2180
|
subMessageHash = 'multi:' + channel + ':' + symbol
|
2190
2181
|
messageHash = 'unsubscribe:' + subMessageHash
|
2191
|
-
|
2192
|
-
del client.subscriptions[subMessageHash]
|
2193
|
-
if messageHash in client.subscriptions:
|
2194
|
-
del client.subscriptions[messageHash]
|
2182
|
+
self.clean_unsubscription(client, subMessageHash, messageHash)
|
2195
2183
|
if timeframe in self.ohlcvs[symbol]:
|
2196
2184
|
del self.ohlcvs[symbol][timeframe]
|
2197
|
-
error = UnsubscribeError(self.id + ' ' + subMessageHash)
|
2198
|
-
client.reject(error, subMessageHash)
|
2199
|
-
client.resolve(True, messageHash)
|
2200
2185
|
|
2201
2186
|
def handle_unsubscription_ticker(self, client: Client, symbol: str, channel):
|
2202
2187
|
subMessageHash = channel + '::' + symbol
|
2203
2188
|
messageHash = 'unsubscribe:ticker:' + symbol
|
2204
|
-
|
2205
|
-
del client.subscriptions[subMessageHash]
|
2206
|
-
if messageHash in client.subscriptions:
|
2207
|
-
del client.subscriptions[messageHash]
|
2189
|
+
self.clean_unsubscription(client, subMessageHash, messageHash)
|
2208
2190
|
if symbol in self.tickers:
|
2209
2191
|
del self.tickers[symbol]
|
2210
|
-
error = UnsubscribeError(self.id + ' ' + subMessageHash)
|
2211
|
-
client.reject(error, subMessageHash)
|
2212
|
-
client.resolve(True, messageHash)
|
2213
2192
|
|
2214
2193
|
def handle_unsubscription(self, client: Client, message):
|
2215
2194
|
#
|
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
|