ccxt 4.4.7__py2.py3-none-any.whl → 4.4.9__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/bigone.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/kucoinfutures.py +5 -0
- ccxt/abstract/okx.py +2 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/bigone.py +35 -86
- ccxt/async_support/binance.py +49 -12
- ccxt/async_support/bingx.py +7 -2
- ccxt/async_support/bitget.py +3 -0
- ccxt/async_support/bybit.py +354 -2
- ccxt/async_support/gate.py +30 -1
- ccxt/async_support/htx.py +22 -0
- ccxt/async_support/kucoin.py +1 -0
- ccxt/async_support/kucoinfutures.py +152 -3
- ccxt/async_support/okx.py +4 -0
- ccxt/base/exchange.py +1 -1
- ccxt/bigone.py +35 -86
- ccxt/binance.py +49 -12
- ccxt/bingx.py +7 -2
- ccxt/bitget.py +3 -0
- ccxt/bybit.py +354 -2
- ccxt/gate.py +30 -1
- ccxt/htx.py +22 -0
- ccxt/kucoin.py +1 -0
- ccxt/kucoinfutures.py +152 -3
- ccxt/okx.py +4 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +3 -3
- ccxt/pro/bitmart.py +72 -0
- ccxt/pro/bitvavo.py +87 -2
- ccxt/pro/blofin.py +59 -0
- ccxt/pro/hitbtc.py +112 -44
- ccxt/pro/hollaex.py +5 -0
- ccxt/pro/okx.py +12 -1
- ccxt/pro/p2b.py +33 -2
- ccxt/pro/whitebit.py +29 -1
- {ccxt-4.4.7.dist-info → ccxt-4.4.9.dist-info}/METADATA +4 -4
- {ccxt-4.4.7.dist-info → ccxt-4.4.9.dist-info}/RECORD +47 -47
- {ccxt-4.4.7.dist-info → ccxt-4.4.9.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.7.dist-info → ccxt-4.4.9.dist-info}/WHEEL +0 -0
- {ccxt-4.4.7.dist-info → ccxt-4.4.9.dist-info}/top_level.txt +0 -0
ccxt/kucoinfutures.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
from ccxt.kucoin import kucoin
|
7
7
|
from ccxt.abstract.kucoinfutures import ImplicitAPI
|
8
|
-
from ccxt.base.types import Balances, Currency, Int, LeverageTier, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
|
8
|
+
from ccxt.base.types import Balances, Currency, Int, Leverage, LeverageTier, MarginMode, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
|
9
9
|
from typing import List
|
10
10
|
from ccxt.base.errors import AuthenticationError
|
11
11
|
from ccxt.base.errors import PermissionDenied
|
@@ -80,9 +80,10 @@ class kucoinfutures(kucoin, ImplicitAPI):
|
|
80
80
|
'fetchIsolatedBorrowRates': False,
|
81
81
|
'fetchL3OrderBook': True,
|
82
82
|
'fetchLedger': True,
|
83
|
+
'fetchLeverage': True,
|
83
84
|
'fetchLeverageTiers': False,
|
84
85
|
'fetchMarginAdjustmentHistory': False,
|
85
|
-
'fetchMarginMode':
|
86
|
+
'fetchMarginMode': True,
|
86
87
|
'fetchMarketLeverageTiers': True,
|
87
88
|
'fetchMarkets': True,
|
88
89
|
'fetchMarkOHLCV': False,
|
@@ -106,7 +107,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
|
|
106
107
|
'fetchTransactionFee': False,
|
107
108
|
'fetchWithdrawals': True,
|
108
109
|
'setLeverage': False,
|
109
|
-
'setMarginMode':
|
110
|
+
'setMarginMode': True,
|
110
111
|
'transfer': True,
|
111
112
|
'withdraw': None,
|
112
113
|
},
|
@@ -183,12 +184,15 @@ class kucoinfutures(kucoin, ImplicitAPI):
|
|
183
184
|
'trade-fees': 1,
|
184
185
|
'history-positions': 1,
|
185
186
|
'getMaxOpenSize': 1,
|
187
|
+
'getCrossUserLeverage': 1,
|
188
|
+
'position/getMarginMode': 1,
|
186
189
|
},
|
187
190
|
'post': {
|
188
191
|
'withdrawals': 1,
|
189
192
|
'transfer-out': 1, # v2
|
190
193
|
'transfer-in': 1,
|
191
194
|
'orders': 1.33,
|
195
|
+
'st-orders': 1.33,
|
192
196
|
'orders/test': 1.33,
|
193
197
|
'position/margin/auto-deposit-status': 1,
|
194
198
|
'position/margin/deposit-margin': 1,
|
@@ -196,6 +200,8 @@ class kucoinfutures(kucoin, ImplicitAPI):
|
|
196
200
|
'bullet-private': 1,
|
197
201
|
'sub/api-key': 1,
|
198
202
|
'sub/api-key/update': 1,
|
203
|
+
'changeCrossUserLeverage': 1,
|
204
|
+
'position/changeMarginMode': 1,
|
199
205
|
},
|
200
206
|
'delete': {
|
201
207
|
'withdrawals/{withdrawalId}': 1,
|
@@ -330,9 +336,13 @@ class kucoinfutures(kucoin, ImplicitAPI):
|
|
330
336
|
'futuresPrivate': {
|
331
337
|
'GET': {
|
332
338
|
'getMaxOpenSize': 'v2',
|
339
|
+
'getCrossUserLeverage': 'v2',
|
340
|
+
'position/getMarginMode': 'v2',
|
333
341
|
},
|
334
342
|
'POST': {
|
335
343
|
'transfer-out': 'v2',
|
344
|
+
'changeCrossUserLeverage': 'v2',
|
345
|
+
'position/changeMarginMode': 'v2',
|
336
346
|
},
|
337
347
|
},
|
338
348
|
'futuresPublic': {
|
@@ -2721,3 +2731,142 @@ class kucoinfutures(kucoin, ImplicitAPI):
|
|
2721
2731
|
'percentage': True,
|
2722
2732
|
'tierBased': True,
|
2723
2733
|
}
|
2734
|
+
|
2735
|
+
def fetch_margin_mode(self, symbol: str, params={}) -> MarginMode:
|
2736
|
+
"""
|
2737
|
+
fetches the margin mode of a trading pair
|
2738
|
+
:see: https://www.kucoin.com/docs/rest/futures-trading/positions/get-margin-mode
|
2739
|
+
:param str symbol: unified symbol of the market to fetch the margin mode for
|
2740
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2741
|
+
:returns dict: a `margin mode structure <https://docs.ccxt.com/#/?id=margin-mode-structure>`
|
2742
|
+
"""
|
2743
|
+
self.load_markets()
|
2744
|
+
market = self.market(symbol)
|
2745
|
+
request: dict = {
|
2746
|
+
'symbol': market['id'],
|
2747
|
+
}
|
2748
|
+
response = self.futuresPrivateGetPositionGetMarginMode(self.extend(request, params))
|
2749
|
+
#
|
2750
|
+
# {
|
2751
|
+
# "code": "200000",
|
2752
|
+
# "data": {
|
2753
|
+
# "symbol": "XBTUSDTM",
|
2754
|
+
# "marginMode": "ISOLATED"
|
2755
|
+
# }
|
2756
|
+
# }
|
2757
|
+
#
|
2758
|
+
data = self.safe_dict(response, 'data', {})
|
2759
|
+
return self.parse_margin_mode(data, market)
|
2760
|
+
|
2761
|
+
def parse_margin_mode(self, marginMode: dict, market=None) -> MarginMode:
|
2762
|
+
marginType = self.safe_string(marginMode, 'marginMode')
|
2763
|
+
marginType = 'isolated' if (marginType == 'ISOLATED') else 'cross'
|
2764
|
+
return {
|
2765
|
+
'info': marginMode,
|
2766
|
+
'symbol': market['symbol'],
|
2767
|
+
'marginMode': marginType,
|
2768
|
+
}
|
2769
|
+
|
2770
|
+
def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
2771
|
+
"""
|
2772
|
+
set margin mode to 'cross' or 'isolated'
|
2773
|
+
:see: https://www.kucoin.com/docs/rest/futures-trading/positions/modify-margin-mode
|
2774
|
+
:param str marginMode: 'cross' or 'isolated'
|
2775
|
+
:param str symbol: unified market symbol
|
2776
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2777
|
+
:returns dict: response from the exchange
|
2778
|
+
"""
|
2779
|
+
if symbol is None:
|
2780
|
+
raise ArgumentsRequired(self.id + ' setMarginMode() requires a symbol argument')
|
2781
|
+
self.check_required_argument('setMarginMode', marginMode, 'marginMode', ['cross', 'isolated'])
|
2782
|
+
self.load_markets()
|
2783
|
+
market = self.market(symbol)
|
2784
|
+
request: dict = {
|
2785
|
+
'symbol': market['id'],
|
2786
|
+
'marginMode': marginMode.upper(),
|
2787
|
+
}
|
2788
|
+
response = self.futuresPrivatePostPositionChangeMarginMode(self.extend(request, params))
|
2789
|
+
#
|
2790
|
+
# {
|
2791
|
+
# "code": "200000",
|
2792
|
+
# "data": {
|
2793
|
+
# "symbol": "XBTUSDTM",
|
2794
|
+
# "marginMode": "ISOLATED"
|
2795
|
+
# }
|
2796
|
+
# }
|
2797
|
+
#
|
2798
|
+
data = self.safe_dict(response, 'data', {})
|
2799
|
+
return self.parse_margin_mode(data, market)
|
2800
|
+
|
2801
|
+
def fetch_leverage(self, symbol: str, params={}) -> Leverage:
|
2802
|
+
"""
|
2803
|
+
fetch the set leverage for a market
|
2804
|
+
:see: https://www.kucoin.com/docs/rest/futures-trading/positions/get-cross-margin-leverage
|
2805
|
+
:param str symbol: unified market symbol
|
2806
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2807
|
+
:returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
|
2808
|
+
"""
|
2809
|
+
marginMode = None
|
2810
|
+
marginMode, params = self.handle_margin_mode_and_params(symbol, params)
|
2811
|
+
if marginMode != 'cross':
|
2812
|
+
raise NotSupported(self.id + ' fetchLeverage() currently supports only params["marginMode"] = "cross"')
|
2813
|
+
self.load_markets()
|
2814
|
+
market = self.market(symbol)
|
2815
|
+
request: dict = {
|
2816
|
+
'symbol': market['id'],
|
2817
|
+
}
|
2818
|
+
response = self.futuresPrivateGetGetCrossUserLeverage(self.extend(request, params))
|
2819
|
+
#
|
2820
|
+
# {
|
2821
|
+
# "code": "200000",
|
2822
|
+
# "data": {
|
2823
|
+
# "symbol": "XBTUSDTM",
|
2824
|
+
# "leverage": "3"
|
2825
|
+
# }
|
2826
|
+
# }
|
2827
|
+
#
|
2828
|
+
data = self.safe_dict(response, 'data', {})
|
2829
|
+
parsed = self.parse_leverage(data, market)
|
2830
|
+
return self.extend(parsed, {
|
2831
|
+
'marginMode': marginMode,
|
2832
|
+
})
|
2833
|
+
|
2834
|
+
def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
|
2835
|
+
"""
|
2836
|
+
set the level of leverage for a market
|
2837
|
+
:see: https://www.kucoin.com/docs/rest/futures-trading/positions/modify-cross-margin-leverage
|
2838
|
+
:param float leverage: the rate of leverage
|
2839
|
+
:param str symbol: unified market symbol
|
2840
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2841
|
+
:returns dict: response from the exchange
|
2842
|
+
"""
|
2843
|
+
marginMode = None
|
2844
|
+
marginMode, params = self.handle_margin_mode_and_params(symbol, params)
|
2845
|
+
if marginMode != 'cross':
|
2846
|
+
raise NotSupported(self.id + ' setLeverage() currently supports only params["marginMode"] = "cross"')
|
2847
|
+
self.load_markets()
|
2848
|
+
market = self.market(symbol)
|
2849
|
+
request: dict = {
|
2850
|
+
'symbol': market['id'],
|
2851
|
+
'leverage': str(leverage),
|
2852
|
+
}
|
2853
|
+
response = self.futuresPrivatePostChangeCrossUserLeverage(self.extend(request, params))
|
2854
|
+
#
|
2855
|
+
# {
|
2856
|
+
# "code": "200000",
|
2857
|
+
# "data": True
|
2858
|
+
# }
|
2859
|
+
#
|
2860
|
+
return self.parse_leverage(response, market)
|
2861
|
+
|
2862
|
+
def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
|
2863
|
+
marketId = self.safe_string(leverage, 'symbol')
|
2864
|
+
market = self.safe_market(marketId, market)
|
2865
|
+
leverageNum = self.safe_integer(leverage, 'leverage')
|
2866
|
+
return {
|
2867
|
+
'info': leverage,
|
2868
|
+
'symbol': market['symbol'],
|
2869
|
+
'marginMode': None,
|
2870
|
+
'longLeverage': leverageNum,
|
2871
|
+
'shortLeverage': leverageNum,
|
2872
|
+
}
|
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/binance.py
CHANGED
@@ -2417,13 +2417,13 @@ class binance(ccxt.async_support.binance):
|
|
2417
2417
|
subType, params = self.handle_sub_type_and_params('watchBalance', None, params)
|
2418
2418
|
isPortfolioMargin = None
|
2419
2419
|
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'watchBalance', 'papi', 'portfolioMargin', False)
|
2420
|
-
urlType = type
|
2421
|
-
if isPortfolioMargin:
|
2422
|
-
urlType = 'papi'
|
2423
2420
|
if self.isLinear(type, subType):
|
2424
2421
|
type = 'future'
|
2425
2422
|
elif self.isInverse(type, subType):
|
2426
2423
|
type = 'delivery'
|
2424
|
+
urlType = type
|
2425
|
+
if isPortfolioMargin:
|
2426
|
+
urlType = 'papi'
|
2427
2427
|
url = self.urls['api']['ws'][urlType] + '/' + self.options[type]['listenKey']
|
2428
2428
|
client = self.client(url)
|
2429
2429
|
self.set_balance_cache(client, type, isPortfolioMargin)
|
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
|