ccxt 4.3.40__py2.py3-none-any.whl → 4.3.41__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 +2 -0
- ccxt/abstract/binancecoinm.py +2 -0
- ccxt/abstract/binanceus.py +2 -0
- ccxt/abstract/binanceusdm.py +2 -0
- ccxt/abstract/okx.py +7 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +3 -0
- ccxt/async_support/bitfinex2.py +1 -1
- ccxt/async_support/bithumb.py +9 -1
- ccxt/async_support/bitstamp.py +38 -2
- ccxt/async_support/coinlist.py +19 -1
- ccxt/async_support/coinmate.py +19 -3
- ccxt/async_support/coinone.py +1 -1
- ccxt/async_support/coinspot.py +11 -2
- ccxt/async_support/independentreserve.py +33 -1
- ccxt/async_support/indodax.py +43 -2
- ccxt/async_support/okx.py +7 -0
- ccxt/async_support/upbit.py +13 -8
- ccxt/async_support/woo.py +6 -2
- ccxt/base/exchange.py +1 -1
- ccxt/binance.py +3 -0
- ccxt/bitfinex2.py +1 -1
- ccxt/bithumb.py +9 -1
- ccxt/bitstamp.py +38 -2
- ccxt/coinlist.py +19 -1
- ccxt/coinmate.py +19 -3
- ccxt/coinone.py +1 -1
- ccxt/coinspot.py +11 -2
- ccxt/independentreserve.py +33 -1
- ccxt/indodax.py +43 -2
- ccxt/okx.py +7 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/alpaca.py +5 -5
- ccxt/pro/ascendex.py +3 -3
- ccxt/pro/bingx.py +258 -42
- ccxt/pro/bitget.py +6 -5
- ccxt/pro/bitrue.py +3 -4
- ccxt/pro/currencycom.py +6 -5
- ccxt/pro/exmo.py +5 -6
- ccxt/pro/gemini.py +4 -3
- ccxt/pro/independentreserve.py +7 -7
- ccxt/pro/lbank.py +4 -4
- ccxt/pro/phemex.py +5 -5
- ccxt/pro/probit.py +4 -4
- ccxt/pro/upbit.py +295 -4
- ccxt/pro/wazirx.py +12 -12
- ccxt/upbit.py +13 -8
- ccxt/woo.py +6 -2
- {ccxt-4.3.40.dist-info → ccxt-4.3.41.dist-info}/METADATA +4 -4
- {ccxt-4.3.40.dist-info → ccxt-4.3.41.dist-info}/RECORD +54 -54
- {ccxt-4.3.40.dist-info → ccxt-4.3.41.dist-info}/WHEEL +0 -0
- {ccxt-4.3.40.dist-info → ccxt-4.3.41.dist-info}/top_level.txt +0 -0
ccxt/pro/bingx.py
CHANGED
@@ -5,10 +5,12 @@
|
|
5
5
|
|
6
6
|
import ccxt.async_support
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
|
8
|
-
from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Ticker, Trade
|
8
|
+
from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Strings, Ticker, Tickers, Trade
|
9
9
|
from ccxt.async_support.base.ws.client import Client
|
10
10
|
from typing import List
|
11
|
+
from ccxt.base.errors import ArgumentsRequired
|
11
12
|
from ccxt.base.errors import BadRequest
|
13
|
+
from ccxt.base.errors import NotSupported
|
12
14
|
from ccxt.base.errors import NetworkError
|
13
15
|
from ccxt.base.precise import Precise
|
14
16
|
|
@@ -21,11 +23,13 @@ class bingx(ccxt.async_support.bingx):
|
|
21
23
|
'ws': True,
|
22
24
|
'watchTrades': True,
|
23
25
|
'watchOrderBook': True,
|
26
|
+
'watchOrderBookForSymbols': True,
|
24
27
|
'watchOHLCV': True,
|
28
|
+
'watchOHLCVForSymbols': True,
|
25
29
|
'watchOrders': True,
|
26
30
|
'watchMyTrades': True,
|
27
31
|
'watchTicker': True,
|
28
|
-
'watchTickers':
|
32
|
+
'watchTickers': True,
|
29
33
|
'watchBalance': True,
|
30
34
|
},
|
31
35
|
'urls': {
|
@@ -73,6 +77,14 @@ class bingx(ccxt.async_support.bingx):
|
|
73
77
|
'fetchBalanceSnapshot': True, # needed to be True to keep track of used and free balance
|
74
78
|
'awaitBalanceSnapshot': False, # whether to wait for the balance snapshot before providing updates
|
75
79
|
},
|
80
|
+
'watchOrderBook': {
|
81
|
+
'depth': 100, # 5, 10, 20, 50, 100
|
82
|
+
'interval': 500, # 100, 200, 500, 1000
|
83
|
+
},
|
84
|
+
'watchOrderBookForSymbols': {
|
85
|
+
'depth': 100, # 5, 10, 20, 50, 100
|
86
|
+
'interval': 500, # 100, 200, 500, 1000
|
87
|
+
},
|
76
88
|
},
|
77
89
|
'streaming': {
|
78
90
|
'keepAlive': 1800000, # 30 minutes
|
@@ -93,15 +105,16 @@ class bingx(ccxt.async_support.bingx):
|
|
93
105
|
url = self.safe_value(self.urls['api']['ws'], marketType)
|
94
106
|
if url is None:
|
95
107
|
raise BadRequest(self.id + ' watchTrades is not supported for ' + marketType + ' markets.')
|
96
|
-
|
108
|
+
subscriptionHash = market['id'] + '@ticker'
|
109
|
+
messageHash = self.get_message_hash('ticker', market['symbol'])
|
97
110
|
uuid = self.uuid()
|
98
111
|
request: dict = {
|
99
112
|
'id': uuid,
|
100
|
-
'dataType':
|
113
|
+
'dataType': subscriptionHash,
|
101
114
|
}
|
102
115
|
if marketType == 'swap':
|
103
116
|
request['reqType'] = 'sub'
|
104
|
-
return await self.watch(url, messageHash, self.extend(request, query),
|
117
|
+
return await self.watch(url, messageHash, self.extend(request, query), subscriptionHash)
|
105
118
|
|
106
119
|
def handle_ticker(self, client: Client, message):
|
107
120
|
#
|
@@ -167,8 +180,9 @@ class bingx(ccxt.async_support.bingx):
|
|
167
180
|
symbol = market['symbol']
|
168
181
|
ticker = self.parse_ws_ticker(data, market)
|
169
182
|
self.tickers[symbol] = ticker
|
170
|
-
|
171
|
-
|
183
|
+
client.resolve(ticker, self.get_message_hash('ticker', symbol))
|
184
|
+
if self.safe_string(message, 'dataType') == 'all@ticker':
|
185
|
+
client.resolve(ticker, self.get_message_hash('ticker'))
|
172
186
|
|
173
187
|
def parse_ws_ticker(self, message, market=None):
|
174
188
|
#
|
@@ -220,6 +234,172 @@ class bingx(ccxt.async_support.bingx):
|
|
220
234
|
'info': message,
|
221
235
|
}, market)
|
222
236
|
|
237
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
238
|
+
"""
|
239
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
240
|
+
:see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20to%2024-hour%20price%20changes%20of%20all%20trading%20pairs
|
241
|
+
:param str[] symbols: unified symbol of the market to watch the tickers for
|
242
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
243
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
244
|
+
"""
|
245
|
+
await self.load_markets()
|
246
|
+
symbols = self.market_symbols(symbols, None, True, True, False)
|
247
|
+
firstMarket = None
|
248
|
+
marketType = None
|
249
|
+
symbolsDefined = (symbols is not None)
|
250
|
+
if symbolsDefined:
|
251
|
+
firstMarket = self.market(symbols[0])
|
252
|
+
marketType, params = self.handle_market_type_and_params('watchTickers', firstMarket, params)
|
253
|
+
if marketType == 'spot':
|
254
|
+
raise NotSupported(self.id + ' watchTickers is not supported for spot markets yet')
|
255
|
+
messageHashes = []
|
256
|
+
subscriptionHashes = ['all@ticker']
|
257
|
+
if symbolsDefined:
|
258
|
+
for i in range(0, len(symbols)):
|
259
|
+
symbol = symbols[i]
|
260
|
+
market = self.market(symbol)
|
261
|
+
messageHashes.append(self.get_message_hash('ticker', market['symbol']))
|
262
|
+
else:
|
263
|
+
messageHashes.append(self.get_message_hash('ticker'))
|
264
|
+
url = self.safe_string(self.urls['api']['ws'], marketType)
|
265
|
+
uuid = self.uuid()
|
266
|
+
request: dict = {
|
267
|
+
'id': uuid,
|
268
|
+
'dataType': 'all@ticker',
|
269
|
+
}
|
270
|
+
if marketType == 'swap':
|
271
|
+
request['reqType'] = 'sub'
|
272
|
+
result = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), subscriptionHashes)
|
273
|
+
if self.newUpdates:
|
274
|
+
newDict: dict = {}
|
275
|
+
newDict[result['symbol']] = result
|
276
|
+
return newDict
|
277
|
+
return self.tickers
|
278
|
+
|
279
|
+
async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
|
280
|
+
"""
|
281
|
+
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
282
|
+
:see: https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20Market%20Depth%20Data%20of%20all%20trading%20pairs
|
283
|
+
:param str[] symbols: unified array of symbols
|
284
|
+
:param int [limit]: the maximum amount of order book entries to return
|
285
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
286
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
287
|
+
"""
|
288
|
+
symbols = self.market_symbols(symbols, None, True, True, False)
|
289
|
+
firstMarket = None
|
290
|
+
marketType = None
|
291
|
+
symbolsDefined = (symbols is not None)
|
292
|
+
if symbolsDefined:
|
293
|
+
firstMarket = self.market(symbols[0])
|
294
|
+
marketType, params = self.handle_market_type_and_params('watchOrderBookForSymbols', firstMarket, params)
|
295
|
+
if marketType == 'spot':
|
296
|
+
raise NotSupported(self.id + ' watchOrderBookForSymbols is not supported for spot markets yet')
|
297
|
+
limit = self.get_order_book_limit_by_market_type(marketType, limit)
|
298
|
+
interval = None
|
299
|
+
interval, params = self.handle_option_and_params(params, 'watchOrderBookForSymbols', 'interval', 500)
|
300
|
+
self.check_required_argument('watchOrderBookForSymbols', interval, 'interval', [100, 200, 500, 1000])
|
301
|
+
channelName = 'depth' + str(limit) + '@' + str(interval) + 'ms'
|
302
|
+
subscriptionHash = 'all@' + channelName
|
303
|
+
messageHashes = []
|
304
|
+
if symbolsDefined:
|
305
|
+
for i in range(0, len(symbols)):
|
306
|
+
symbol = symbols[i]
|
307
|
+
market = self.market(symbol)
|
308
|
+
messageHashes.append(self.get_message_hash('orderbook', market['symbol']))
|
309
|
+
else:
|
310
|
+
messageHashes.append(self.get_message_hash('orderbook'))
|
311
|
+
url = self.safe_string(self.urls['api']['ws'], marketType)
|
312
|
+
uuid = self.uuid()
|
313
|
+
request: dict = {
|
314
|
+
'id': uuid,
|
315
|
+
'dataType': subscriptionHash,
|
316
|
+
}
|
317
|
+
if marketType == 'swap':
|
318
|
+
request['reqType'] = 'sub'
|
319
|
+
subscriptionArgs: dict = {
|
320
|
+
'symbols': symbols,
|
321
|
+
'limit': limit,
|
322
|
+
'interval': interval,
|
323
|
+
'params': params,
|
324
|
+
}
|
325
|
+
orderbook = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), [subscriptionHash], subscriptionArgs)
|
326
|
+
return orderbook.limit()
|
327
|
+
|
328
|
+
async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
|
329
|
+
"""
|
330
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
331
|
+
:param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
|
332
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
333
|
+
:param int [limit]: the maximum amount of candles to fetch
|
334
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
335
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
336
|
+
"""
|
337
|
+
symbolsLength = len(symbolsAndTimeframes)
|
338
|
+
if symbolsLength != 0 and not isinstance(symbolsAndTimeframes[0], list):
|
339
|
+
raise ArgumentsRequired(self.id + " watchOHLCVForSymbols() requires a an array like [['BTC/USDT:USDT', '1m'], ['LTC/USDT:USDT', '5m']]")
|
340
|
+
await self.load_markets()
|
341
|
+
messageHashes = []
|
342
|
+
marketType = None
|
343
|
+
chosenTimeframe = None
|
344
|
+
if symbolsLength != 0:
|
345
|
+
symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
|
346
|
+
symbols = self.market_symbols(symbols, None, True, True, False)
|
347
|
+
firstMarket = self.market(symbols[0])
|
348
|
+
marketType, params = self.handle_market_type_and_params('watchOrderBookForSymbols', firstMarket, params)
|
349
|
+
if marketType == 'spot':
|
350
|
+
raise NotSupported(self.id + ' watchOrderBookForSymbols is not supported for spot markets yet')
|
351
|
+
marketOptions = self.safe_dict(self.options, marketType)
|
352
|
+
timeframes = self.safe_dict(marketOptions, 'timeframes', {})
|
353
|
+
for i in range(0, len(symbolsAndTimeframes)):
|
354
|
+
symbolAndTimeframe = symbolsAndTimeframes[i]
|
355
|
+
sym = symbolAndTimeframe[0]
|
356
|
+
tf = symbolAndTimeframe[1]
|
357
|
+
market = self.market(sym)
|
358
|
+
rawTimeframe = self.safe_string(timeframes, tf, tf)
|
359
|
+
if chosenTimeframe is None:
|
360
|
+
chosenTimeframe = rawTimeframe
|
361
|
+
elif chosenTimeframe != rawTimeframe:
|
362
|
+
raise BadRequest(self.id + ' watchOHLCVForSymbols requires all timeframes to be the same')
|
363
|
+
messageHashes.append(self.get_message_hash('ohlcv', market['symbol'], chosenTimeframe))
|
364
|
+
subscriptionHash = 'all@kline_' + chosenTimeframe
|
365
|
+
url = self.safe_string(self.urls['api']['ws'], marketType)
|
366
|
+
uuid = self.uuid()
|
367
|
+
request: dict = {
|
368
|
+
'id': uuid,
|
369
|
+
'dataType': subscriptionHash,
|
370
|
+
}
|
371
|
+
if marketType == 'swap':
|
372
|
+
request['reqType'] = 'sub'
|
373
|
+
subscriptionArgs: dict = {
|
374
|
+
'limit': limit,
|
375
|
+
'params': params,
|
376
|
+
}
|
377
|
+
symbol, timeframe, candles = await self.watch_multiple(url, messageHashes, request, [subscriptionHash], subscriptionArgs)
|
378
|
+
if self.newUpdates:
|
379
|
+
limit = candles.getLimit(symbol, limit)
|
380
|
+
filtered = self.filter_by_since_limit(candles, since, limit, 0, True)
|
381
|
+
return self.create_ohlcv_object(symbol, timeframe, filtered)
|
382
|
+
|
383
|
+
def get_order_book_limit_by_market_type(self, marketType: str, limit: Int = None):
|
384
|
+
if limit is None:
|
385
|
+
limit = 100
|
386
|
+
else:
|
387
|
+
if marketType == 'swap' or marketType == 'future':
|
388
|
+
limit = self.find_nearest_ceiling([5, 10, 20, 50, 100], limit)
|
389
|
+
elif marketType == 'spot':
|
390
|
+
limit = self.find_nearest_ceiling([20, 100], limit)
|
391
|
+
return limit
|
392
|
+
|
393
|
+
def get_message_hash(self, unifiedChannel: str, symbol: Str = None, extra: Str = None):
|
394
|
+
hash = unifiedChannel
|
395
|
+
if symbol is not None:
|
396
|
+
hash += '::' + symbol
|
397
|
+
else:
|
398
|
+
hash += 's' # tickers, orderbooks, ohlcvs ...
|
399
|
+
if extra is not None:
|
400
|
+
hash += '::' + extra
|
401
|
+
return hash
|
402
|
+
|
223
403
|
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
224
404
|
"""
|
225
405
|
watches information on multiple trades made in a market
|
@@ -344,27 +524,31 @@ class bingx(ccxt.async_support.bingx):
|
|
344
524
|
await self.load_markets()
|
345
525
|
market = self.market(symbol)
|
346
526
|
marketType, query = self.handle_market_type_and_params('watchOrderBook', market, params)
|
347
|
-
|
348
|
-
|
349
|
-
else:
|
350
|
-
if marketType == 'swap':
|
351
|
-
if (limit != 5) and (limit != 10) and (limit != 20) and (limit != 50) and (limit != 100):
|
352
|
-
raise BadRequest(self.id + ' watchOrderBook()(swap) only supports limit 5, 10, 20, 50, and 100')
|
353
|
-
elif marketType == 'spot':
|
354
|
-
if (limit != 20) and (limit != 100):
|
355
|
-
raise BadRequest(self.id + ' watchOrderBook()(spot) only supports limit 20, and 100')
|
527
|
+
limit = self.get_order_book_limit_by_market_type(marketType, limit)
|
528
|
+
channelName = 'depth' + str(limit)
|
356
529
|
url = self.safe_value(self.urls['api']['ws'], marketType)
|
357
530
|
if url is None:
|
358
531
|
raise BadRequest(self.id + ' watchOrderBook is not supported for ' + marketType + ' markets.')
|
359
|
-
|
532
|
+
interval = None
|
533
|
+
if marketType != 'spot':
|
534
|
+
interval, params = self.handle_option_and_params(params, 'watchOrderBook', 'interval', 500)
|
535
|
+
self.check_required_argument('watchOrderBook', interval, 'interval', [100, 200, 500, 1000])
|
536
|
+
channelName = channelName + '@' + str(interval) + 'ms'
|
537
|
+
subscriptionHash = market['id'] + '@' + channelName
|
538
|
+
messageHash = self.get_message_hash('orderbook', market['symbol'])
|
360
539
|
uuid = self.uuid()
|
361
540
|
request: dict = {
|
362
541
|
'id': uuid,
|
363
|
-
'dataType':
|
542
|
+
'dataType': subscriptionHash,
|
364
543
|
}
|
365
544
|
if marketType == 'swap':
|
366
545
|
request['reqType'] = 'sub'
|
367
|
-
|
546
|
+
subscriptionArgs: dict = {
|
547
|
+
'limit': limit,
|
548
|
+
'interval': interval,
|
549
|
+
'params': params,
|
550
|
+
}
|
551
|
+
orderbook = await self.watch(url, messageHash, self.deep_extend(request, query), subscriptionHash, subscriptionArgs)
|
368
552
|
return orderbook.limit()
|
369
553
|
|
370
554
|
def handle_delta(self, bookside, delta):
|
@@ -399,7 +583,7 @@ class bingx(ccxt.async_support.bingx):
|
|
399
583
|
#
|
400
584
|
# {
|
401
585
|
# "code": 0,
|
402
|
-
# "dataType": "BTC-USDT@depth20",
|
586
|
+
# "dataType": "BTC-USDT@depth20@100ms", #or "all@depth20@100ms"
|
403
587
|
# "data": {
|
404
588
|
# "bids": [
|
405
589
|
# ['28852.9', "34.2621"],
|
@@ -408,24 +592,37 @@ class bingx(ccxt.async_support.bingx):
|
|
408
592
|
# "asks": [
|
409
593
|
# ['28864.9', "23.4079"],
|
410
594
|
# ...
|
411
|
-
# ]
|
595
|
+
# ],
|
596
|
+
# "symbol": "BTC-USDT", # self key exists only in "all" subscription
|
412
597
|
# }
|
413
598
|
# }
|
414
599
|
#
|
415
|
-
data = self.
|
416
|
-
|
417
|
-
|
600
|
+
data = self.safe_dict(message, 'data', {})
|
601
|
+
dataType = self.safe_string(message, 'dataType')
|
602
|
+
parts = dataType.split('@')
|
603
|
+
firstPart = parts[0]
|
604
|
+
isAllEndpoint = (firstPart == 'all')
|
605
|
+
marketId = self.safe_string(data, 'symbol', firstPart)
|
418
606
|
isSwap = client.url.find('swap') >= 0
|
419
607
|
marketType = 'swap' if isSwap else 'spot'
|
420
608
|
market = self.safe_market(marketId, None, None, marketType)
|
421
609
|
symbol = market['symbol']
|
422
|
-
|
423
|
-
|
424
|
-
|
610
|
+
if self.safe_value(self.orderbooks, symbol) is None:
|
611
|
+
# limit = [5, 10, 20, 50, 100]
|
612
|
+
subscriptionHash = dataType
|
613
|
+
subscription = client.subscriptions[subscriptionHash]
|
614
|
+
limit = self.safe_integer(subscription, 'limit')
|
615
|
+
self.orderbooks[symbol] = self.order_book({}, limit)
|
616
|
+
orderbook = self.orderbooks[symbol]
|
425
617
|
snapshot = self.parse_order_book(data, symbol, None, 'bids', 'asks', 0, 1)
|
426
618
|
orderbook.reset(snapshot)
|
427
619
|
self.orderbooks[symbol] = orderbook
|
620
|
+
messageHash = self.get_message_hash('orderbook', symbol)
|
428
621
|
client.resolve(orderbook, messageHash)
|
622
|
+
# resolve for "all"
|
623
|
+
if isAllEndpoint:
|
624
|
+
messageHashForAll = self.get_message_hash('orderbook')
|
625
|
+
client.resolve(orderbook, messageHashForAll)
|
429
626
|
|
430
627
|
def parse_ws_ohlcv(self, ohlcv, market=None) -> list:
|
431
628
|
#
|
@@ -496,30 +693,43 @@ class bingx(ccxt.async_support.bingx):
|
|
496
693
|
# ]
|
497
694
|
# }
|
498
695
|
#
|
499
|
-
data = self.
|
696
|
+
data = self.safe_list(message, 'data', [])
|
500
697
|
candles = None
|
501
698
|
if isinstance(data, list):
|
502
699
|
candles = data
|
503
700
|
else:
|
504
|
-
candles = [self.
|
505
|
-
|
506
|
-
timeframeId = messageHash.split('_')[1]
|
507
|
-
marketId = messageHash.split('@')[0]
|
701
|
+
candles = [self.safe_list(data, 'K', [])]
|
702
|
+
dataType = self.safe_string(message, 'dataType')
|
508
703
|
isSwap = client.url.find('swap') >= 0
|
704
|
+
parts = dataType.split('@')
|
705
|
+
firstPart = parts[0]
|
706
|
+
isAllEndpoint = (firstPart == 'all')
|
707
|
+
marketId = self.safe_string(message, 's', firstPart)
|
509
708
|
marketType = 'swap' if isSwap else 'spot'
|
510
709
|
market = self.safe_market(marketId, None, None, marketType)
|
511
710
|
symbol = market['symbol']
|
512
711
|
self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
712
|
+
rawTimeframe = dataType.split('_')[1]
|
713
|
+
marketOptions = self.safe_dict(self.options, marketType)
|
714
|
+
timeframes = self.safe_dict(marketOptions, 'timeframes', {})
|
715
|
+
unifiedTimeframe = self.find_timeframe(rawTimeframe, timeframes)
|
716
|
+
if self.safe_value(self.ohlcvs[symbol], rawTimeframe) is None:
|
717
|
+
subscriptionHash = dataType
|
718
|
+
subscription = client.subscriptions[subscriptionHash]
|
719
|
+
limit = self.safe_integer(subscription, 'limit')
|
720
|
+
self.ohlcvs[symbol][unifiedTimeframe] = ArrayCacheByTimestamp(limit)
|
721
|
+
stored = self.ohlcvs[symbol][unifiedTimeframe]
|
518
722
|
for i in range(0, len(candles)):
|
519
723
|
candle = candles[i]
|
520
724
|
parsed = self.parse_ws_ohlcv(candle, market)
|
521
725
|
stored.append(parsed)
|
522
|
-
|
726
|
+
resolveData = [symbol, unifiedTimeframe, stored]
|
727
|
+
messageHash = self.get_message_hash('ohlcv', symbol, unifiedTimeframe)
|
728
|
+
client.resolve(resolveData, messageHash)
|
729
|
+
# resolve for "all"
|
730
|
+
if isAllEndpoint:
|
731
|
+
messageHashForAll = self.get_message_hash('ohlcv', None, unifiedTimeframe)
|
732
|
+
client.resolve(resolveData, messageHashForAll)
|
523
733
|
|
524
734
|
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
525
735
|
"""
|
@@ -541,16 +751,22 @@ class bingx(ccxt.async_support.bingx):
|
|
541
751
|
raise BadRequest(self.id + ' watchOHLCV is not supported for ' + marketType + ' markets.')
|
542
752
|
options = self.safe_value(self.options, marketType, {})
|
543
753
|
timeframes = self.safe_value(options, 'timeframes', {})
|
544
|
-
|
545
|
-
messageHash = market['
|
754
|
+
rawTimeframe = self.safe_string(timeframes, timeframe, timeframe)
|
755
|
+
messageHash = self.get_message_hash('ohlcv', market['symbol'], timeframe)
|
756
|
+
subscriptionHash = market['id'] + '@kline_' + rawTimeframe
|
546
757
|
uuid = self.uuid()
|
547
758
|
request: dict = {
|
548
759
|
'id': uuid,
|
549
|
-
'dataType':
|
760
|
+
'dataType': subscriptionHash,
|
550
761
|
}
|
551
762
|
if marketType == 'swap':
|
552
763
|
request['reqType'] = 'sub'
|
553
|
-
|
764
|
+
subscriptionArgs: dict = {
|
765
|
+
'limit': limit,
|
766
|
+
'params': params,
|
767
|
+
}
|
768
|
+
result = await self.watch(url, messageHash, self.extend(request, query), subscriptionHash, subscriptionArgs)
|
769
|
+
ohlcv = result[2]
|
554
770
|
if self.newUpdates:
|
555
771
|
limit = ohlcv.getLimit(symbol, limit)
|
556
772
|
return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
|
ccxt/pro/bitget.py
CHANGED
@@ -939,7 +939,7 @@ class bitget(ccxt.async_support.bitget):
|
|
939
939
|
type, params = self.handle_market_type_and_params('watchOrders', market, params)
|
940
940
|
subType = None
|
941
941
|
subType, params = self.handle_sub_type_and_params('watchOrders', market, params, 'linear')
|
942
|
-
if (type == 'spot') and (symbol is None):
|
942
|
+
if (type == 'spot' or type == 'margin') and (symbol is None):
|
943
943
|
raise ArgumentsRequired(self.id + ' watchOrders requires a symbol argument for ' + type + ' markets.')
|
944
944
|
if (productType is None) and (type != 'spot') and (symbol is None):
|
945
945
|
messageHash = messageHash + ':' + subType
|
@@ -955,7 +955,7 @@ class bitget(ccxt.async_support.bitget):
|
|
955
955
|
subscriptionHash = subscriptionHash + ':' + symbol
|
956
956
|
if isTrigger:
|
957
957
|
subscriptionHash = subscriptionHash + ':stop' # we don't want to re-use the same subscription hash for stop orders
|
958
|
-
instId = marketId if (type == 'spot') else 'default' # different from other streams here the 'rest' id is required for spot markets, contract markets require default here
|
958
|
+
instId = marketId if (type == 'spot' or type == 'margin') else 'default' # different from other streams here the 'rest' id is required for spot markets, contract markets require default here
|
959
959
|
channel = 'orders-algo' if isTrigger else 'orders'
|
960
960
|
marginMode = None
|
961
961
|
marginMode, params = self.handle_margin_mode_and_params('watchOrders', params)
|
@@ -1011,9 +1011,10 @@ class bitget(ccxt.async_support.bitget):
|
|
1011
1011
|
# "ts": 1701923982497
|
1012
1012
|
# }
|
1013
1013
|
#
|
1014
|
-
arg = self.
|
1014
|
+
arg = self.safe_dict(message, 'arg', {})
|
1015
1015
|
channel = self.safe_string(arg, 'channel')
|
1016
1016
|
instType = self.safe_string(arg, 'instType')
|
1017
|
+
argInstId = self.safe_string(arg, 'instId')
|
1017
1018
|
marketType = None
|
1018
1019
|
if instType == 'SPOT':
|
1019
1020
|
marketType = 'spot'
|
@@ -1035,7 +1036,7 @@ class bitget(ccxt.async_support.bitget):
|
|
1035
1036
|
marketSymbols: dict = {}
|
1036
1037
|
for i in range(0, len(data)):
|
1037
1038
|
order = data[i]
|
1038
|
-
marketId = self.safe_string(order, 'instId')
|
1039
|
+
marketId = self.safe_string(order, 'instId', argInstId)
|
1039
1040
|
market = self.safe_market(marketId, None, None, marketType)
|
1040
1041
|
parsed = self.parse_ws_order(order, market)
|
1041
1042
|
stored.append(parsed)
|
@@ -1228,7 +1229,7 @@ class bitget(ccxt.async_support.bitget):
|
|
1228
1229
|
filledAmount = self.safe_string(order, 'baseVolume')
|
1229
1230
|
totalAmount = self.safe_string(order, 'size')
|
1230
1231
|
cost = self.safe_string(order, 'fillNotionalUsd')
|
1231
|
-
remaining =
|
1232
|
+
remaining = Precise.string_sub(totalAmount, totalFilled)
|
1232
1233
|
return self.safe_order({
|
1233
1234
|
'info': order,
|
1234
1235
|
'symbol': symbol,
|
ccxt/pro/bitrue.py
CHANGED
@@ -341,12 +341,11 @@ class bitrue(ccxt.async_support.bitrue):
|
|
341
341
|
symbol = market['symbol']
|
342
342
|
timestamp = self.safe_integer(message, 'ts')
|
343
343
|
tick = self.safe_value(message, 'tick', {})
|
344
|
-
|
345
|
-
|
346
|
-
|
344
|
+
if not (symbol in self.orderbooks):
|
345
|
+
self.orderbooks[symbol] = self.order_book()
|
346
|
+
orderbook = self.orderbooks[symbol]
|
347
347
|
snapshot = self.parse_order_book(tick, symbol, timestamp, 'buys', 'asks')
|
348
348
|
orderbook.reset(snapshot)
|
349
|
-
self.orderbooks[symbol] = orderbook
|
350
349
|
messageHash = 'orderbook:' + symbol
|
351
350
|
client.resolve(orderbook, messageHash)
|
352
351
|
|
ccxt/pro/currencycom.py
CHANGED
@@ -441,16 +441,17 @@ class currencycom(ccxt.async_support.currencycom):
|
|
441
441
|
destination = 'depthMarketData.subscribe'
|
442
442
|
messageHash = destination + ':' + symbol
|
443
443
|
timestamp = self.safe_integer(data, 'ts')
|
444
|
-
orderbook = self.safe_value(self.orderbooks, symbol)
|
445
|
-
if
|
446
|
-
|
444
|
+
# orderbook = self.safe_value(self.orderbooks, symbol)
|
445
|
+
if not (symbol in self.orderbooks):
|
446
|
+
self.orderbooks[symbol] = self.order_book()
|
447
|
+
orderbook = self.orderbooks[symbol]
|
447
448
|
orderbook.reset({
|
448
449
|
'symbol': symbol,
|
449
450
|
'timestamp': timestamp,
|
450
451
|
'datetime': self.iso8601(timestamp),
|
451
452
|
})
|
452
|
-
bids = self.
|
453
|
-
asks = self.
|
453
|
+
bids = self.safe_dict(data, 'bid', {})
|
454
|
+
asks = self.safe_dict(data, 'ofr', {})
|
454
455
|
self.handle_deltas(orderbook['bids'], bids)
|
455
456
|
self.handle_deltas(orderbook['asks'], asks)
|
456
457
|
self.orderbooks[symbol] = orderbook
|
ccxt/pro/exmo.py
CHANGED
@@ -495,17 +495,16 @@ class exmo(ccxt.async_support.exmo):
|
|
495
495
|
orderBook = self.safe_value(message, 'data', {})
|
496
496
|
messageHash = 'orderbook:' + symbol
|
497
497
|
timestamp = self.safe_integer(message, 'ts')
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
self.orderbooks[symbol] = orderbook
|
498
|
+
if not (symbol in self.orderbooks):
|
499
|
+
self.orderbooks[symbol] = self.order_book({})
|
500
|
+
orderbook = self.orderbooks[symbol]
|
502
501
|
event = self.safe_string(message, 'event')
|
503
502
|
if event == 'snapshot':
|
504
503
|
snapshot = self.parse_order_book(orderBook, symbol, timestamp, 'bid', 'ask')
|
505
504
|
orderbook.reset(snapshot)
|
506
505
|
else:
|
507
|
-
asks = self.
|
508
|
-
bids = self.
|
506
|
+
asks = self.safe_list(orderBook, 'ask', [])
|
507
|
+
bids = self.safe_list(orderBook, 'bid', [])
|
509
508
|
self.handle_deltas(orderbook['asks'], asks)
|
510
509
|
self.handle_deltas(orderbook['bids'], bids)
|
511
510
|
orderbook['timestamp'] = timestamp
|
ccxt/pro/gemini.py
CHANGED
@@ -366,9 +366,10 @@ class gemini(ccxt.async_support.gemini):
|
|
366
366
|
market = self.safe_market(marketId)
|
367
367
|
symbol = market['symbol']
|
368
368
|
messageHash = 'orderbook:' + symbol
|
369
|
-
orderbook = self.safe_value(self.orderbooks, symbol)
|
370
|
-
if
|
371
|
-
|
369
|
+
# orderbook = self.safe_value(self.orderbooks, symbol)
|
370
|
+
if not (symbol in self.orderbooks):
|
371
|
+
self.orderbooks[symbol] = self.order_book()
|
372
|
+
orderbook = self.orderbooks[symbol]
|
372
373
|
for i in range(0, len(changes)):
|
373
374
|
delta = changes[i]
|
374
375
|
price = self.safe_number(delta, 1)
|
ccxt/pro/independentreserve.py
CHANGED
@@ -176,22 +176,22 @@ class independentreserve(ccxt.async_support.independentreserve):
|
|
176
176
|
base = self.safe_currency_code(baseId)
|
177
177
|
quote = self.safe_currency_code(quoteId)
|
178
178
|
symbol = base + '/' + quote
|
179
|
-
orderBook = self.
|
179
|
+
orderBook = self.safe_dict(message, 'Data', {})
|
180
180
|
messageHash = 'orderbook:' + symbol + ':' + depth
|
181
181
|
subscription = self.safe_value(client.subscriptions, messageHash, {})
|
182
182
|
receivedSnapshot = self.safe_bool(subscription, 'receivedSnapshot', False)
|
183
183
|
timestamp = self.safe_integer(message, 'Time')
|
184
|
-
orderbook = self.safe_value(self.orderbooks, symbol)
|
185
|
-
if
|
186
|
-
|
187
|
-
|
184
|
+
# orderbook = self.safe_value(self.orderbooks, symbol)
|
185
|
+
if not (symbol in self.orderbooks):
|
186
|
+
self.orderbooks[symbol] = self.order_book({})
|
187
|
+
orderbook = self.orderbooks[symbol]
|
188
188
|
if event == 'OrderBookSnapshot':
|
189
189
|
snapshot = self.parse_order_book(orderBook, symbol, timestamp, 'Bids', 'Offers', 'Price', 'Volume')
|
190
190
|
orderbook.reset(snapshot)
|
191
191
|
subscription['receivedSnapshot'] = True
|
192
192
|
else:
|
193
|
-
asks = self.
|
194
|
-
bids = self.
|
193
|
+
asks = self.safe_list(orderBook, 'Offers', [])
|
194
|
+
bids = self.safe_list(orderBook, 'Bids', [])
|
195
195
|
self.handle_deltas(orderbook['asks'], asks)
|
196
196
|
self.handle_deltas(orderbook['bids'], bids)
|
197
197
|
orderbook['timestamp'] = timestamp
|
ccxt/pro/lbank.py
CHANGED
@@ -751,10 +751,10 @@ class lbank(ccxt.async_support.lbank):
|
|
751
751
|
orderBook = self.safe_value(message, 'depth', message)
|
752
752
|
datetime = self.safe_string(message, 'TS')
|
753
753
|
timestamp = self.parse8601(datetime)
|
754
|
-
orderbook = self.safe_value(self.orderbooks, symbol)
|
755
|
-
if
|
756
|
-
|
757
|
-
|
754
|
+
# orderbook = self.safe_value(self.orderbooks, symbol)
|
755
|
+
if not (symbol in self.orderbooks):
|
756
|
+
self.orderbooks[symbol] = self.order_book({})
|
757
|
+
orderbook = self.orderbooks[symbol]
|
758
758
|
snapshot = self.parse_order_book(orderBook, symbol, timestamp, 'bids', 'asks')
|
759
759
|
orderbook.reset(snapshot)
|
760
760
|
messageHash = 'orderbook:' + symbol
|
ccxt/pro/phemex.py
CHANGED
@@ -677,11 +677,11 @@ class phemex(ccxt.async_support.phemex):
|
|
677
677
|
self.orderbooks[symbol] = orderbook
|
678
678
|
client.resolve(orderbook, messageHash)
|
679
679
|
else:
|
680
|
-
|
681
|
-
|
682
|
-
changes = self.
|
683
|
-
asks = self.
|
684
|
-
bids = self.
|
680
|
+
if symbol in self.orderbooks:
|
681
|
+
orderbook = self.orderbooks[symbol]
|
682
|
+
changes = self.safe_dict_2(message, 'book', 'orderbook_p', {})
|
683
|
+
asks = self.safe_list(changes, 'asks', [])
|
684
|
+
bids = self.safe_list(changes, 'bids', [])
|
685
685
|
self.custom_handle_deltas(orderbook['asks'], asks, market)
|
686
686
|
self.custom_handle_deltas(orderbook['bids'], bids, market)
|
687
687
|
orderbook['nonce'] = nonce
|
ccxt/pro/probit.py
CHANGED
@@ -428,10 +428,10 @@ class probit(ccxt.async_support.probit):
|
|
428
428
|
symbol = self.safe_symbol(marketId)
|
429
429
|
dataBySide = self.group_by(orderBook, 'side')
|
430
430
|
messageHash = 'orderbook:' + symbol
|
431
|
-
orderbook = self.safe_value(self.orderbooks, symbol)
|
432
|
-
if
|
433
|
-
|
434
|
-
|
431
|
+
# orderbook = self.safe_value(self.orderbooks, symbol)
|
432
|
+
if not (symbol in self.orderbooks):
|
433
|
+
self.orderbooks[symbol] = self.order_book({})
|
434
|
+
orderbook = self.orderbooks[symbol]
|
435
435
|
reset = self.safe_bool(message, 'reset', False)
|
436
436
|
if reset:
|
437
437
|
snapshot = self.parse_order_book(dataBySide, symbol, None, 'buy', 'sell', 'price', 'quantity')
|