ccxt 4.4.6__py2.py3-none-any.whl → 4.4.8__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/binance.py +1 -0
- ccxt/abstract/binancecoinm.py +1 -0
- ccxt/abstract/binanceus.py +1 -0
- ccxt/abstract/binanceusdm.py +1 -0
- ccxt/abstract/bybit.py +5 -0
- ccxt/abstract/okx.py +2 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +12 -3
- ccxt/async_support/binance.py +49 -12
- ccxt/async_support/bingx.py +3 -0
- ccxt/async_support/bitget.py +8 -4
- ccxt/async_support/bitmart.py +109 -1
- ccxt/async_support/bybit.py +364 -11
- ccxt/async_support/gate.py +3 -0
- ccxt/async_support/htx.py +20 -0
- ccxt/async_support/kucoin.py +2 -2
- ccxt/async_support/mexc.py +85 -13
- ccxt/async_support/okx.py +4 -0
- ccxt/base/exchange.py +16 -3
- ccxt/binance.py +49 -12
- ccxt/bingx.py +3 -0
- ccxt/bitget.py +8 -4
- ccxt/bitmart.py +109 -1
- ccxt/bybit.py +364 -11
- ccxt/gate.py +3 -0
- ccxt/htx.py +20 -0
- ccxt/kucoin.py +2 -2
- ccxt/mexc.py +85 -13
- ccxt/okx.py +4 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitget.py +62 -0
- ccxt/pro/bitmart.py +72 -0
- ccxt/pro/bitvavo.py +87 -2
- ccxt/pro/blofin.py +59 -0
- ccxt/pro/okx.py +11 -5
- {ccxt-4.4.6.dist-info → ccxt-4.4.8.dist-info}/METADATA +4 -4
- {ccxt-4.4.6.dist-info → ccxt-4.4.8.dist-info}/RECORD +41 -41
- {ccxt-4.4.6.dist-info → ccxt-4.4.8.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.6.dist-info → ccxt-4.4.8.dist-info}/WHEEL +0 -0
- {ccxt-4.4.6.dist-info → ccxt-4.4.8.dist-info}/top_level.txt +0 -0
ccxt/mexc.py
CHANGED
@@ -54,8 +54,8 @@ class mexc(Exchange, ImplicitAPI):
|
|
54
54
|
'closePosition': False,
|
55
55
|
'createDepositAddress': True,
|
56
56
|
'createMarketBuyOrderWithCost': True,
|
57
|
-
'createMarketOrderWithCost':
|
58
|
-
'createMarketSellOrderWithCost':
|
57
|
+
'createMarketOrderWithCost': True,
|
58
|
+
'createMarketSellOrderWithCost': True,
|
59
59
|
'createOrder': True,
|
60
60
|
'createOrders': True,
|
61
61
|
'createPostOnlyOrder': True,
|
@@ -144,7 +144,7 @@ class mexc(Exchange, ImplicitAPI):
|
|
144
144
|
'repayCrossMargin': False,
|
145
145
|
'repayIsolatedMargin': False,
|
146
146
|
'setLeverage': True,
|
147
|
-
'setMarginMode':
|
147
|
+
'setMarginMode': True,
|
148
148
|
'setPositionMode': True,
|
149
149
|
'signIn': None,
|
150
150
|
'transfer': None,
|
@@ -430,7 +430,6 @@ class mexc(Exchange, ImplicitAPI):
|
|
430
430
|
'options': {
|
431
431
|
'adjustForTimeDifference': False,
|
432
432
|
'timeDifference': 0,
|
433
|
-
'createMarketBuyOrderRequiresPrice': True,
|
434
433
|
'unavailableContracts': {
|
435
434
|
'BTC/USDT:USDT': True,
|
436
435
|
'LTC/USDT:USDT': True,
|
@@ -479,12 +478,14 @@ class mexc(Exchange, ImplicitAPI):
|
|
479
478
|
'LTC': 'LTC',
|
480
479
|
},
|
481
480
|
'networks': {
|
481
|
+
'ZKSYNC': 'ZKSYNCERA',
|
482
482
|
'TRC20': 'TRX',
|
483
483
|
'TON': 'TONCOIN',
|
484
484
|
'AVAXC': 'AVAX_CCHAIN',
|
485
485
|
'ERC20': 'ETH',
|
486
486
|
'ACA': 'ACALA',
|
487
487
|
'BEP20': 'BSC',
|
488
|
+
'OPTIMISM': 'OP',
|
488
489
|
# 'ADA': 'Cardano(ADA)',
|
489
490
|
# 'AE': 'AE',
|
490
491
|
# 'ALGO': 'Algorand(ALGO)',
|
@@ -2018,8 +2019,24 @@ class mexc(Exchange, ImplicitAPI):
|
|
2018
2019
|
market = self.market(symbol)
|
2019
2020
|
if not market['spot']:
|
2020
2021
|
raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
|
2021
|
-
params['
|
2022
|
-
return self.create_order(symbol, 'market', 'buy',
|
2022
|
+
params['cost'] = cost
|
2023
|
+
return self.create_order(symbol, 'market', 'buy', 0, None, params)
|
2024
|
+
|
2025
|
+
def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
|
2026
|
+
"""
|
2027
|
+
create a market sell order by providing the symbol and cost
|
2028
|
+
:see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#new-order
|
2029
|
+
:param str symbol: unified symbol of the market to create an order in
|
2030
|
+
:param float cost: how much you want to trade in units of the quote currency
|
2031
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2032
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
2033
|
+
"""
|
2034
|
+
self.load_markets()
|
2035
|
+
market = self.market(symbol)
|
2036
|
+
if not market['spot']:
|
2037
|
+
raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
|
2038
|
+
params['cost'] = cost
|
2039
|
+
return self.create_order(symbol, 'market', 'sell', 0, None, params)
|
2023
2040
|
|
2024
2041
|
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
2025
2042
|
"""
|
@@ -2043,6 +2060,7 @@ class mexc(Exchange, ImplicitAPI):
|
|
2043
2060
|
:param long [params.positionId]: *contract only* it is recommended to hasattr(self, fill) parameter when closing a position
|
2044
2061
|
:param str [params.externalOid]: *contract only* external order ID
|
2045
2062
|
:param int [params.positionMode]: *contract only* 1:hedge, 2:one-way, default: the user's current config
|
2063
|
+
:param boolean [params.test]: *spot only* whether to use the test endpoint or not, default is False
|
2046
2064
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
2047
2065
|
"""
|
2048
2066
|
self.load_markets()
|
@@ -2061,22 +2079,21 @@ class mexc(Exchange, ImplicitAPI):
|
|
2061
2079
|
'side': orderSide,
|
2062
2080
|
'type': type.upper(),
|
2063
2081
|
}
|
2064
|
-
if
|
2065
|
-
createMarketBuyOrderRequiresPrice = True
|
2066
|
-
createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
|
2082
|
+
if type == 'market':
|
2067
2083
|
cost = self.safe_number_2(params, 'cost', 'quoteOrderQty')
|
2068
2084
|
params = self.omit(params, 'cost')
|
2069
2085
|
if cost is not None:
|
2070
2086
|
amount = cost
|
2071
|
-
|
2087
|
+
request['quoteOrderQty'] = self.cost_to_precision(symbol, amount)
|
2088
|
+
else:
|
2072
2089
|
if price is None:
|
2073
|
-
|
2090
|
+
request['quantity'] = self.amount_to_precision(symbol, amount)
|
2074
2091
|
else:
|
2075
2092
|
amountString = self.number_to_string(amount)
|
2076
2093
|
priceString = self.number_to_string(price)
|
2077
2094
|
quoteAmount = Precise.string_mul(amountString, priceString)
|
2078
2095
|
amount = quoteAmount
|
2079
|
-
|
2096
|
+
request['quoteOrderQty'] = self.cost_to_precision(symbol, amount)
|
2080
2097
|
else:
|
2081
2098
|
request['quantity'] = self.amount_to_precision(symbol, amount)
|
2082
2099
|
if price is not None:
|
@@ -2111,8 +2128,14 @@ class mexc(Exchange, ImplicitAPI):
|
|
2111
2128
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
2112
2129
|
"""
|
2113
2130
|
self.load_markets()
|
2131
|
+
test = self.safe_bool(params, 'test', False)
|
2132
|
+
params = self.omit(params, 'test')
|
2114
2133
|
request = self.create_spot_order_request(market, type, side, amount, price, marginMode, params)
|
2115
|
-
response =
|
2134
|
+
response = None
|
2135
|
+
if test:
|
2136
|
+
response = self.spotPrivatePostOrderTest(request)
|
2137
|
+
else:
|
2138
|
+
response = self.spotPrivatePostOrder(request)
|
2116
2139
|
#
|
2117
2140
|
# spot
|
2118
2141
|
#
|
@@ -2426,6 +2449,9 @@ class mexc(Exchange, ImplicitAPI):
|
|
2426
2449
|
def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
2427
2450
|
"""
|
2428
2451
|
fetches information on multiple orders made by the user
|
2452
|
+
:see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
|
2453
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
|
2454
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
|
2429
2455
|
:param str symbol: unified market symbol of the market orders were made in
|
2430
2456
|
:param int [since]: the earliest time in ms to fetch orders for
|
2431
2457
|
:param int [limit]: the maximum number of order structures to retrieve
|
@@ -2639,6 +2665,9 @@ class mexc(Exchange, ImplicitAPI):
|
|
2639
2665
|
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
2640
2666
|
"""
|
2641
2667
|
fetch all unfilled currently open orders
|
2668
|
+
:see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#current-open-orders
|
2669
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
|
2670
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
|
2642
2671
|
:param str symbol: unified market symbol
|
2643
2672
|
:param int [since]: the earliest time in ms to fetch open orders for
|
2644
2673
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
@@ -2721,6 +2750,9 @@ class mexc(Exchange, ImplicitAPI):
|
|
2721
2750
|
def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
2722
2751
|
"""
|
2723
2752
|
fetches information on multiple closed orders made by the user
|
2753
|
+
:see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
|
2754
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
|
2755
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
|
2724
2756
|
:param str symbol: unified market symbol of the market orders were made in
|
2725
2757
|
:param int [since]: the earliest time in ms to fetch orders for
|
2726
2758
|
:param int [limit]: the maximum number of order structures to retrieve
|
@@ -2732,6 +2764,9 @@ class mexc(Exchange, ImplicitAPI):
|
|
2732
2764
|
def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
2733
2765
|
"""
|
2734
2766
|
fetches information on multiple canceled orders made by the user
|
2767
|
+
:see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#all-orders
|
2768
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-all-of-the-user-39-s-historical-orders
|
2769
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#gets-the-trigger-order-list
|
2735
2770
|
:param str symbol: unified market symbol of the market orders were made in
|
2736
2771
|
:param int [since]: timestamp in ms of the earliest order, default is None
|
2737
2772
|
:param int [limit]: max number of orders to return, default is None
|
@@ -5285,6 +5320,43 @@ class mexc(Exchange, ImplicitAPI):
|
|
5285
5320
|
positions = self.parse_positions(data, symbols, params)
|
5286
5321
|
return self.filter_by_since_limit(positions, since, limit)
|
5287
5322
|
|
5323
|
+
def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
5324
|
+
"""
|
5325
|
+
set margin mode to 'cross' or 'isolated'
|
5326
|
+
:see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#switch-leverage
|
5327
|
+
:param str marginMode: 'cross' or 'isolated'
|
5328
|
+
:param str [symbol]: required when there is no position, else provide params["positionId"]
|
5329
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
5330
|
+
:param str [params.positionId]: required when a position is set
|
5331
|
+
:param str [params.direction]: "long" or "short" required when there is no position
|
5332
|
+
:returns dict: response from the exchange
|
5333
|
+
"""
|
5334
|
+
self.load_markets()
|
5335
|
+
market = self.market(symbol)
|
5336
|
+
if market['spot']:
|
5337
|
+
raise BadSymbol(self.id + ' setMarginMode() supports contract markets only')
|
5338
|
+
marginMode = marginMode.lower()
|
5339
|
+
if marginMode != 'isolated' and marginMode != 'cross':
|
5340
|
+
raise BadRequest(self.id + ' setMarginMode() marginMode argument should be isolated or cross')
|
5341
|
+
leverage = self.safe_integer(params, 'leverage')
|
5342
|
+
if leverage is None:
|
5343
|
+
raise ArgumentsRequired(self.id + ' setMarginMode() requires a leverage parameter')
|
5344
|
+
direction = self.safe_string_lower_2(params, 'direction', 'positionId')
|
5345
|
+
request: dict = {
|
5346
|
+
'leverage': leverage,
|
5347
|
+
'openType': 1 if (marginMode == 'isolated') else 2,
|
5348
|
+
}
|
5349
|
+
if symbol is not None:
|
5350
|
+
request['symbol'] = market['id']
|
5351
|
+
if direction is not None:
|
5352
|
+
request['positionType'] = 2 if (direction == 'short') else 1
|
5353
|
+
params = self.omit(params, 'direction')
|
5354
|
+
response = self.contractPrivatePostPositionChangeLeverage(self.extend(request, params))
|
5355
|
+
#
|
5356
|
+
# {success: True, code: '0'}
|
5357
|
+
#
|
5358
|
+
return self.parse_leverage(response, market)
|
5359
|
+
|
5288
5360
|
def nonce(self):
|
5289
5361
|
return self.milliseconds() - self.safe_integer(self.options, 'timeDifference', 0)
|
5290
5362
|
|
ccxt/okx.py
CHANGED
@@ -290,6 +290,7 @@ class okx(Exchange, ImplicitAPI):
|
|
290
290
|
'copytrading/public-preference-currency': 4,
|
291
291
|
'copytrading/public-current-subpositions': 4,
|
292
292
|
'copytrading/public-subpositions-history': 4,
|
293
|
+
'support/announcements-types': 20,
|
293
294
|
},
|
294
295
|
},
|
295
296
|
'private': {
|
@@ -435,6 +436,7 @@ class okx(Exchange, ImplicitAPI):
|
|
435
436
|
# affiliate
|
436
437
|
'affiliate/invitee/detail': 1,
|
437
438
|
'users/partner/if-rebate': 1,
|
439
|
+
'support/announcements': 4,
|
438
440
|
},
|
439
441
|
'post': {
|
440
442
|
# rfq
|
@@ -814,6 +816,8 @@ class okx(Exchange, ImplicitAPI):
|
|
814
816
|
# SPOT/MARGIN error codes 54000-54999
|
815
817
|
'54000': ExchangeError, # Margin transactions unavailable
|
816
818
|
'54001': ExchangeError, # Only Multi-currency margin account can be set to borrow coins automatically
|
819
|
+
'54008': InvalidOrder, # This operation is disabled by the 'mass cancel order' endpoint. Please enable it using self endpoint.
|
820
|
+
'54009': InvalidOrder, # The range of {param0} should be [{param1}, {param2}].
|
817
821
|
'54011': InvalidOrder, # 200 Pre-market trading contracts are only allowed to reduce the number of positions within 1 hour before delivery. Please modify or cancel the order.
|
818
822
|
# Trading bot Error Code from 55100 to 55999
|
819
823
|
'55100': InvalidOrder, # Take profit % should be within the range of {parameter1}-{parameter2}
|
ccxt/pro/__init__.py
CHANGED
ccxt/pro/bitget.py
CHANGED
@@ -42,6 +42,7 @@ class bitget(ccxt.async_support.bitget):
|
|
42
42
|
'watchOrders': True,
|
43
43
|
'watchTicker': True,
|
44
44
|
'watchTickers': True,
|
45
|
+
'watchBidsAsks': True,
|
45
46
|
'watchTrades': True,
|
46
47
|
'watchTradesForSymbols': True,
|
47
48
|
'watchPositions': True,
|
@@ -209,6 +210,7 @@ class bitget(ccxt.async_support.bitget):
|
|
209
210
|
# "ts": 1701842994341
|
210
211
|
# }
|
211
212
|
#
|
213
|
+
self.handle_bid_ask(client, message)
|
212
214
|
ticker = self.parse_ws_ticker(message)
|
213
215
|
symbol = ticker['symbol']
|
214
216
|
self.tickers[symbol] = ticker
|
@@ -320,6 +322,66 @@ class bitget(ccxt.async_support.bitget):
|
|
320
322
|
'info': ticker,
|
321
323
|
}, market)
|
322
324
|
|
325
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
326
|
+
"""
|
327
|
+
:see: https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
|
328
|
+
:see: https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
|
329
|
+
watches best bid & ask for symbols
|
330
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
331
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
332
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
333
|
+
"""
|
334
|
+
await self.load_markets()
|
335
|
+
symbols = self.market_symbols(symbols, None, False)
|
336
|
+
market = self.market(symbols[0])
|
337
|
+
instType = None
|
338
|
+
instType, params = self.get_inst_type(market, params)
|
339
|
+
topics = []
|
340
|
+
messageHashes = []
|
341
|
+
for i in range(0, len(symbols)):
|
342
|
+
symbol = symbols[i]
|
343
|
+
marketInner = self.market(symbol)
|
344
|
+
args: dict = {
|
345
|
+
'instType': instType,
|
346
|
+
'channel': 'ticker',
|
347
|
+
'instId': marketInner['id'],
|
348
|
+
}
|
349
|
+
topics.append(args)
|
350
|
+
messageHashes.append('bidask:' + symbol)
|
351
|
+
tickers = await self.watch_public_multiple(messageHashes, topics, params)
|
352
|
+
if self.newUpdates:
|
353
|
+
result: dict = {}
|
354
|
+
result[tickers['symbol']] = tickers
|
355
|
+
return result
|
356
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
357
|
+
|
358
|
+
def handle_bid_ask(self, client: Client, message):
|
359
|
+
ticker = self.parse_ws_bid_ask(message)
|
360
|
+
symbol = ticker['symbol']
|
361
|
+
self.bidsasks[symbol] = ticker
|
362
|
+
messageHash = 'bidask:' + symbol
|
363
|
+
client.resolve(ticker, messageHash)
|
364
|
+
|
365
|
+
def parse_ws_bid_ask(self, message, market=None):
|
366
|
+
arg = self.safe_value(message, 'arg', {})
|
367
|
+
data = self.safe_value(message, 'data', [])
|
368
|
+
ticker = self.safe_value(data, 0, {})
|
369
|
+
timestamp = self.safe_integer(ticker, 'ts')
|
370
|
+
instType = self.safe_string(arg, 'instType')
|
371
|
+
marketType = 'spot' if (instType == 'SPOT') else 'contract'
|
372
|
+
marketId = self.safe_string(ticker, 'instId')
|
373
|
+
market = self.safe_market(marketId, market, None, marketType)
|
374
|
+
return self.safe_ticker({
|
375
|
+
'symbol': market['symbol'],
|
376
|
+
'timestamp': timestamp,
|
377
|
+
'datetime': self.iso8601(timestamp),
|
378
|
+
'ask': self.safe_string(ticker, 'askPr'),
|
379
|
+
'askVolume': self.safe_string(ticker, 'askSz'),
|
380
|
+
'bid': self.safe_string(ticker, 'bidPr'),
|
381
|
+
'bidVolume': self.safe_string(ticker, 'bidSz'),
|
382
|
+
'info': ticker,
|
383
|
+
}, market)
|
384
|
+
|
323
385
|
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
324
386
|
"""
|
325
387
|
watches historical candlestick data containing the open, high, low, close price, and the volume of a market
|
ccxt/pro/bitmart.py
CHANGED
@@ -31,6 +31,7 @@ class bitmart(ccxt.async_support.bitmart):
|
|
31
31
|
'watchBalance': True,
|
32
32
|
'watchTicker': True,
|
33
33
|
'watchTickers': True,
|
34
|
+
'watchBidsAsks': True,
|
34
35
|
'watchOrderBook': True,
|
35
36
|
'watchOrderBookForSymbols': True,
|
36
37
|
'watchOrders': True,
|
@@ -314,6 +315,7 @@ class bitmart(ccxt.async_support.bitmart):
|
|
314
315
|
|
315
316
|
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
316
317
|
"""
|
318
|
+
:see: https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
|
317
319
|
:see: https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
|
318
320
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
319
321
|
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
@@ -331,6 +333,75 @@ class bitmart(ccxt.async_support.bitmart):
|
|
331
333
|
return tickers
|
332
334
|
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
333
335
|
|
336
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
337
|
+
"""
|
338
|
+
:see: https://developer-pro.bitmart.com/en/spot/#public-ticker-channel
|
339
|
+
:see: https://developer-pro.bitmart.com/en/futuresv2/#public-ticker-channel
|
340
|
+
watches best bid & ask for symbols
|
341
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
342
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
343
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
344
|
+
"""
|
345
|
+
await self.load_markets()
|
346
|
+
symbols = self.market_symbols(symbols, None, False)
|
347
|
+
firstMarket = self.get_market_from_symbols(symbols)
|
348
|
+
marketType = None
|
349
|
+
marketType, params = self.handle_market_type_and_params('watchBidsAsks', firstMarket, params)
|
350
|
+
url = self.implode_hostname(self.urls['api']['ws'][marketType]['public'])
|
351
|
+
channelType = 'spot' if (marketType == 'spot') else 'futures'
|
352
|
+
actionType = 'op' if (marketType == 'spot') else 'action'
|
353
|
+
rawSubscriptions = []
|
354
|
+
messageHashes = []
|
355
|
+
for i in range(0, len(symbols)):
|
356
|
+
market = self.market(symbols[i])
|
357
|
+
rawSubscriptions.append(channelType + '/ticker:' + market['id'])
|
358
|
+
messageHashes.append('bidask:' + symbols[i])
|
359
|
+
if marketType != 'spot':
|
360
|
+
rawSubscriptions = [channelType + '/ticker']
|
361
|
+
request: dict = {
|
362
|
+
'args': rawSubscriptions,
|
363
|
+
}
|
364
|
+
request[actionType] = 'subscribe'
|
365
|
+
newTickers = await self.watch_multiple(url, messageHashes, request, rawSubscriptions)
|
366
|
+
if self.newUpdates:
|
367
|
+
tickers: dict = {}
|
368
|
+
tickers[newTickers['symbol']] = newTickers
|
369
|
+
return tickers
|
370
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
371
|
+
|
372
|
+
def handle_bid_ask(self, client: Client, message):
|
373
|
+
table = self.safe_string(message, 'table')
|
374
|
+
isSpot = (table is not None)
|
375
|
+
rawTickers = []
|
376
|
+
if isSpot:
|
377
|
+
rawTickers = self.safe_list(message, 'data', [])
|
378
|
+
else:
|
379
|
+
rawTickers = [self.safe_value(message, 'data', {})]
|
380
|
+
if not len(rawTickers):
|
381
|
+
return
|
382
|
+
for i in range(0, len(rawTickers)):
|
383
|
+
ticker = self.parse_ws_bid_ask(rawTickers[i])
|
384
|
+
symbol = ticker['symbol']
|
385
|
+
self.bidsasks[symbol] = ticker
|
386
|
+
messageHash = 'bidask:' + symbol
|
387
|
+
client.resolve(ticker, messageHash)
|
388
|
+
|
389
|
+
def parse_ws_bid_ask(self, ticker, market=None):
|
390
|
+
marketId = self.safe_string(ticker, 'symbol')
|
391
|
+
market = self.safe_market(marketId, market)
|
392
|
+
symbol = self.safe_string(market, 'symbol')
|
393
|
+
timestamp = self.safe_integer(ticker, 'ms_t')
|
394
|
+
return self.safe_ticker({
|
395
|
+
'symbol': symbol,
|
396
|
+
'timestamp': timestamp,
|
397
|
+
'datetime': self.iso8601(timestamp),
|
398
|
+
'ask': self.safe_string_2(ticker, 'ask_px', 'ask_price'),
|
399
|
+
'askVolume': self.safe_string_2(ticker, 'ask_sz', 'ask_vol'),
|
400
|
+
'bid': self.safe_string_2(ticker, 'bid_px', 'bid_price'),
|
401
|
+
'bidVolume': self.safe_string_2(ticker, 'bid_sz', 'bid_vol'),
|
402
|
+
'info': ticker,
|
403
|
+
}, market)
|
404
|
+
|
334
405
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
335
406
|
"""
|
336
407
|
watches information on multiple orders made by the user
|
@@ -878,6 +949,7 @@ class bitmart(ccxt.async_support.bitmart):
|
|
878
949
|
# }
|
879
950
|
# }
|
880
951
|
#
|
952
|
+
self.handle_bid_ask(client, message)
|
881
953
|
table = self.safe_string(message, 'table')
|
882
954
|
isSpot = (table is not None)
|
883
955
|
rawTickers = []
|
ccxt/pro/bitvavo.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, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, TradingFees
|
9
|
+
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
@@ -25,6 +25,8 @@ class bitvavo(ccxt.async_support.bitvavo):
|
|
25
25
|
'watchOrderBook': True,
|
26
26
|
'watchTrades': True,
|
27
27
|
'watchTicker': True,
|
28
|
+
'watchTickers': True,
|
29
|
+
'watchBidsAsks': True,
|
28
30
|
'watchOHLCV': True,
|
29
31
|
'watchOrders': True,
|
30
32
|
'watchMyTrades': True,
|
@@ -85,15 +87,51 @@ class bitvavo(ccxt.async_support.bitvavo):
|
|
85
87
|
message = self.extend(request, params)
|
86
88
|
return await self.watch(url, messageHash, message, messageHash)
|
87
89
|
|
90
|
+
async def watch_public_multiple(self, methodName, channelName: str, symbols, params={}):
|
91
|
+
await self.load_markets()
|
92
|
+
symbols = self.market_symbols(symbols)
|
93
|
+
messageHashes = [methodName]
|
94
|
+
args = []
|
95
|
+
for i in range(0, len(symbols)):
|
96
|
+
market = self.market(symbols[i])
|
97
|
+
args.append(market['id'])
|
98
|
+
url = self.urls['api']['ws']
|
99
|
+
request: dict = {
|
100
|
+
'action': 'subscribe',
|
101
|
+
'channels': [
|
102
|
+
{
|
103
|
+
'name': channelName,
|
104
|
+
'markets': args,
|
105
|
+
},
|
106
|
+
],
|
107
|
+
}
|
108
|
+
message = self.extend(request, params)
|
109
|
+
return await self.watch_multiple(url, messageHashes, message, messageHashes)
|
110
|
+
|
88
111
|
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
89
112
|
"""
|
90
113
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
114
|
+
:see: https://docs.bitvavo.com/#tag/Market-data-subscription-WebSocket/paths/~1subscribeTicker24h/post
|
91
115
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
92
116
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
93
117
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
94
118
|
"""
|
95
119
|
return await self.watch_public('ticker24h', symbol, params)
|
96
120
|
|
121
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
122
|
+
"""
|
123
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
124
|
+
:see: https://docs.bitvavo.com/#tag/Market-data-subscription-WebSocket/paths/~1subscribeTicker24h/post
|
125
|
+
:param str[] [symbols]: unified symbol of the market to fetch the ticker for
|
126
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
127
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
128
|
+
"""
|
129
|
+
await self.load_markets()
|
130
|
+
symbols = self.market_symbols(symbols, None, False)
|
131
|
+
channel = 'ticker24h'
|
132
|
+
tickers = await self.watch_public_multiple(channel, channel, symbols, params)
|
133
|
+
return self.filter_by_array(tickers, 'symbol', symbols)
|
134
|
+
|
97
135
|
def handle_ticker(self, client: Client, message):
|
98
136
|
#
|
99
137
|
# {
|
@@ -116,8 +154,10 @@ class bitvavo(ccxt.async_support.bitvavo):
|
|
116
154
|
# ]
|
117
155
|
# }
|
118
156
|
#
|
157
|
+
self.handle_bid_ask(client, message)
|
119
158
|
event = self.safe_string(message, 'event')
|
120
159
|
tickers = self.safe_value(message, 'data', [])
|
160
|
+
result = []
|
121
161
|
for i in range(0, len(tickers)):
|
122
162
|
data = tickers[i]
|
123
163
|
marketId = self.safe_string(data, 'market')
|
@@ -126,8 +166,53 @@ class bitvavo(ccxt.async_support.bitvavo):
|
|
126
166
|
ticker = self.parse_ticker(data, market)
|
127
167
|
symbol = ticker['symbol']
|
128
168
|
self.tickers[symbol] = ticker
|
169
|
+
result.append(ticker)
|
129
170
|
client.resolve(ticker, messageHash)
|
130
|
-
|
171
|
+
client.resolve(result, event)
|
172
|
+
|
173
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
174
|
+
"""
|
175
|
+
watches best bid & ask for symbols
|
176
|
+
:see: https://docs.bitvavo.com/#tag/Market-data-subscription-WebSocket/paths/~1subscribeTicker24h/post
|
177
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
178
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
179
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
180
|
+
"""
|
181
|
+
await self.load_markets()
|
182
|
+
symbols = self.market_symbols(symbols, None, False)
|
183
|
+
channel = 'ticker24h'
|
184
|
+
tickers = await self.watch_public_multiple('bidask', channel, symbols, params)
|
185
|
+
return self.filter_by_array(tickers, 'symbol', symbols)
|
186
|
+
|
187
|
+
def handle_bid_ask(self, client: Client, message):
|
188
|
+
event = 'bidask'
|
189
|
+
tickers = self.safe_value(message, 'data', [])
|
190
|
+
result = []
|
191
|
+
for i in range(0, len(tickers)):
|
192
|
+
data = tickers[i]
|
193
|
+
ticker = self.parse_ws_bid_ask(data)
|
194
|
+
symbol = ticker['symbol']
|
195
|
+
self.bidsasks[symbol] = ticker
|
196
|
+
result.append(ticker)
|
197
|
+
messageHash = event + ':' + symbol
|
198
|
+
client.resolve(ticker, messageHash)
|
199
|
+
client.resolve(result, event)
|
200
|
+
|
201
|
+
def parse_ws_bid_ask(self, ticker, market=None):
|
202
|
+
marketId = self.safe_string(ticker, 'market')
|
203
|
+
market = self.safe_market(marketId, None, '-')
|
204
|
+
symbol = self.safe_string(market, 'symbol')
|
205
|
+
timestamp = self.safe_integer(ticker, 'timestamp')
|
206
|
+
return self.safe_ticker({
|
207
|
+
'symbol': symbol,
|
208
|
+
'timestamp': timestamp,
|
209
|
+
'datetime': self.iso8601(timestamp),
|
210
|
+
'ask': self.safe_number(ticker, 'ask'),
|
211
|
+
'askVolume': self.safe_number(ticker, 'askSize'),
|
212
|
+
'bid': self.safe_number(ticker, 'bid'),
|
213
|
+
'bidVolume': self.safe_number(ticker, 'bidSize'),
|
214
|
+
'info': ticker,
|
215
|
+
}, market)
|
131
216
|
|
132
217
|
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
133
218
|
"""
|
ccxt/pro/blofin.py
CHANGED
@@ -26,6 +26,7 @@ class blofin(ccxt.async_support.blofin):
|
|
26
26
|
'watchOrderBookForSymbols': True,
|
27
27
|
'watchTicker': True,
|
28
28
|
'watchTickers': True,
|
29
|
+
'watchBidsAsks': True,
|
29
30
|
'watchOHLCV': True,
|
30
31
|
'watchOHLCVForSymbols': True,
|
31
32
|
'watchOrders': True,
|
@@ -256,6 +257,7 @@ class blofin(ccxt.async_support.blofin):
|
|
256
257
|
# ],
|
257
258
|
# }
|
258
259
|
#
|
260
|
+
self.handle_bid_ask(client, message)
|
259
261
|
arg = self.safe_dict(message, 'arg')
|
260
262
|
channelName = self.safe_string(arg, 'channel')
|
261
263
|
data = self.safe_list(message, 'data')
|
@@ -269,6 +271,63 @@ class blofin(ccxt.async_support.blofin):
|
|
269
271
|
def parse_ws_ticker(self, ticker, market: Market = None) -> Ticker:
|
270
272
|
return self.parse_ticker(ticker, market)
|
271
273
|
|
274
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
275
|
+
"""
|
276
|
+
watches best bid & ask for symbols
|
277
|
+
:see: https://docs.blofin.com/index.html#ws-tickers-channel
|
278
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
279
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
280
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
281
|
+
"""
|
282
|
+
await self.load_markets()
|
283
|
+
symbols = self.market_symbols(symbols, None, False)
|
284
|
+
firstMarket = self.market(symbols[0])
|
285
|
+
channel = 'tickers'
|
286
|
+
marketType = None
|
287
|
+
marketType, params = self.handle_market_type_and_params('watchBidsAsks', firstMarket, params)
|
288
|
+
url = self.implode_hostname(self.urls['api']['ws'][marketType]['public'])
|
289
|
+
messageHashes = []
|
290
|
+
args = []
|
291
|
+
for i in range(0, len(symbols)):
|
292
|
+
market = self.market(symbols[i])
|
293
|
+
messageHashes.append('bidask:' + market['symbol'])
|
294
|
+
args.append({
|
295
|
+
'channel': channel,
|
296
|
+
'instId': market['id'],
|
297
|
+
})
|
298
|
+
request = self.get_subscription_request(args)
|
299
|
+
ticker = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), messageHashes)
|
300
|
+
if self.newUpdates:
|
301
|
+
tickers = {}
|
302
|
+
tickers[ticker['symbol']] = ticker
|
303
|
+
return tickers
|
304
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
305
|
+
|
306
|
+
def handle_bid_ask(self, client: Client, message):
|
307
|
+
data = self.safe_list(message, 'data')
|
308
|
+
for i in range(0, len(data)):
|
309
|
+
ticker = self.parse_ws_bid_ask(data[i])
|
310
|
+
symbol = ticker['symbol']
|
311
|
+
messageHash = 'bidask:' + symbol
|
312
|
+
self.bidsasks[symbol] = ticker
|
313
|
+
client.resolve(ticker, messageHash)
|
314
|
+
|
315
|
+
def parse_ws_bid_ask(self, ticker, market=None):
|
316
|
+
marketId = self.safe_string(ticker, 'instId')
|
317
|
+
market = self.safe_market(marketId, market, '-')
|
318
|
+
symbol = self.safe_string(market, 'symbol')
|
319
|
+
timestamp = self.safe_integer(ticker, 'ts')
|
320
|
+
return self.safe_ticker({
|
321
|
+
'symbol': symbol,
|
322
|
+
'timestamp': timestamp,
|
323
|
+
'datetime': self.iso8601(timestamp),
|
324
|
+
'ask': self.safe_string(ticker, 'askPrice'),
|
325
|
+
'askVolume': self.safe_string(ticker, 'askSize'),
|
326
|
+
'bid': self.safe_string(ticker, 'bidPrice'),
|
327
|
+
'bidVolume': self.safe_string(ticker, 'bidSize'),
|
328
|
+
'info': ticker,
|
329
|
+
}, market)
|
330
|
+
|
272
331
|
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
273
332
|
"""
|
274
333
|
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|