ccxt 4.2.29__py2.py3-none-any.whl → 4.2.31__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 +3 -3
- ccxt/abstract/bybit.py +2 -2
- ccxt/abstract/coinbase.py +10 -0
- ccxt/abstract/okx.py +12 -1
- ccxt/ascendex.py +5 -5
- ccxt/async_support/__init__.py +3 -3
- ccxt/async_support/ascendex.py +5 -5
- ccxt/async_support/base/exchange.py +3 -3
- ccxt/async_support/bigone.py +2 -2
- ccxt/async_support/binance.py +892 -218
- ccxt/async_support/bingx.py +1 -1
- ccxt/async_support/bitfinex.py +1 -1
- ccxt/async_support/bitfinex2.py +421 -86
- ccxt/async_support/bitforex.py +3 -0
- ccxt/async_support/bitget.py +8 -4
- ccxt/async_support/bitmart.py +3 -3
- ccxt/async_support/bitmex.py +4 -4
- ccxt/async_support/bitrue.py +1 -1
- ccxt/async_support/bitso.py +1 -1
- ccxt/async_support/bitteam.py +2 -2
- ccxt/async_support/btcalpha.py +1 -1
- ccxt/async_support/bybit.py +3 -3
- ccxt/async_support/coinbase.py +20 -5
- ccxt/async_support/coincheck.py +1 -1
- ccxt/async_support/coinex.py +2 -2
- ccxt/async_support/coinlist.py +1 -1
- ccxt/async_support/coinmate.py +1 -1
- ccxt/async_support/coinmetro.py +2 -2
- ccxt/async_support/coinsph.py +1 -1
- ccxt/async_support/cryptocom.py +3 -3
- ccxt/async_support/deribit.py +1 -0
- ccxt/async_support/digifinex.py +6 -4
- ccxt/async_support/exmo.py +2 -2
- ccxt/async_support/gate.py +5 -5
- ccxt/async_support/gemini.py +3 -3
- ccxt/async_support/hitbtc.py +13 -17
- ccxt/async_support/hollaex.py +2 -2
- ccxt/async_support/htx.py +6 -6
- ccxt/async_support/huobijp.py +1 -1
- ccxt/async_support/kraken.py +3 -1
- ccxt/async_support/krakenfutures.py +4 -1
- ccxt/async_support/kucoin.py +17 -17
- ccxt/async_support/kucoinfutures.py +3 -3
- ccxt/async_support/lbank.py +4 -3
- ccxt/async_support/mexc.py +7 -7
- ccxt/async_support/novadax.py +1 -1
- ccxt/async_support/okcoin.py +2 -2
- ccxt/async_support/okx.py +22 -8
- ccxt/async_support/p2b.py +1 -0
- ccxt/async_support/phemex.py +3 -3
- ccxt/async_support/poloniexfutures.py +6 -3
- ccxt/async_support/probit.py +1 -1
- ccxt/async_support/timex.py +2 -2
- ccxt/async_support/tokocrypto.py +3 -3
- ccxt/async_support/wavesexchange.py +2 -2
- ccxt/async_support/whitebit.py +3 -3
- ccxt/async_support/woo.py +3 -3
- ccxt/async_support/yobit.py +1 -1
- ccxt/async_support/zaif.py +1 -1
- ccxt/async_support/zonda.py +3 -3
- ccxt/base/errors.py +13 -12
- ccxt/base/exchange.py +36 -26
- ccxt/bigone.py +2 -2
- ccxt/binance.py +892 -218
- ccxt/bingx.py +1 -1
- ccxt/bitfinex.py +1 -1
- ccxt/bitfinex2.py +421 -86
- ccxt/bitforex.py +3 -0
- ccxt/bitget.py +8 -4
- ccxt/bitmart.py +3 -3
- ccxt/bitmex.py +4 -4
- ccxt/bitrue.py +1 -1
- ccxt/bitso.py +1 -1
- ccxt/bitteam.py +2 -2
- ccxt/btcalpha.py +1 -1
- ccxt/bybit.py +3 -3
- ccxt/coinbase.py +20 -5
- ccxt/coincheck.py +1 -1
- ccxt/coinex.py +2 -2
- ccxt/coinlist.py +1 -1
- ccxt/coinmate.py +1 -1
- ccxt/coinmetro.py +2 -2
- ccxt/coinsph.py +1 -1
- ccxt/cryptocom.py +3 -3
- ccxt/deribit.py +1 -0
- ccxt/digifinex.py +6 -4
- ccxt/exmo.py +2 -2
- ccxt/gate.py +5 -5
- ccxt/gemini.py +3 -3
- ccxt/hitbtc.py +13 -17
- ccxt/hollaex.py +2 -2
- ccxt/htx.py +6 -6
- ccxt/huobijp.py +1 -1
- ccxt/kraken.py +3 -1
- ccxt/krakenfutures.py +4 -1
- ccxt/kucoin.py +17 -17
- ccxt/kucoinfutures.py +3 -3
- ccxt/lbank.py +4 -3
- ccxt/mexc.py +7 -7
- ccxt/novadax.py +1 -1
- ccxt/okcoin.py +2 -2
- ccxt/okx.py +22 -8
- ccxt/p2b.py +1 -0
- ccxt/phemex.py +3 -3
- ccxt/poloniexfutures.py +6 -3
- ccxt/pro/__init__.py +3 -1
- ccxt/pro/alpaca.py +1 -1
- ccxt/pro/binance.py +4 -4
- ccxt/pro/bitget.py +1 -1
- ccxt/pro/bitmart.py +1 -1
- ccxt/pro/bitmex.py +43 -7
- ccxt/pro/bitvavo.py +1 -1
- ccxt/pro/bybit.py +2 -2
- ccxt/pro/cex.py +2 -2
- ccxt/pro/independentreserve.py +1 -1
- ccxt/pro/okx.py +1 -1
- ccxt/pro/onetrading.py +2 -2
- ccxt/pro/p2b.py +407 -0
- ccxt/pro/probit.py +5 -5
- ccxt/pro/whitebit.py +1 -1
- ccxt/probit.py +1 -1
- ccxt/timex.py +2 -2
- ccxt/tokocrypto.py +3 -3
- ccxt/wavesexchange.py +2 -2
- ccxt/whitebit.py +3 -3
- ccxt/woo.py +3 -3
- ccxt/yobit.py +1 -1
- ccxt/zaif.py +1 -1
- ccxt/zonda.py +3 -3
- {ccxt-4.2.29.dist-info → ccxt-4.2.31.dist-info}/METADATA +6 -7
- {ccxt-4.2.29.dist-info → ccxt-4.2.31.dist-info}/RECORD +133 -132
- {ccxt-4.2.29.dist-info → ccxt-4.2.31.dist-info}/WHEEL +0 -0
- {ccxt-4.2.29.dist-info → ccxt-4.2.31.dist-info}/top_level.txt +0 -0
ccxt/pro/bitmex.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
import ccxt.async_support
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Strings, Ticker, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
@@ -28,7 +28,7 @@ class bitmex(ccxt.async_support.bitmex):
|
|
28
28
|
'watchOrders': True,
|
29
29
|
'watchPostions': True,
|
30
30
|
'watchTicker': True,
|
31
|
-
'watchTickers':
|
31
|
+
'watchTickers': True,
|
32
32
|
'watchTrades': True,
|
33
33
|
'watchTradesForSymbols': True,
|
34
34
|
},
|
@@ -79,6 +79,39 @@ class bitmex(ccxt.async_support.bitmex):
|
|
79
79
|
}
|
80
80
|
return await self.watch(url, messageHash, self.extend(request, params), messageHash)
|
81
81
|
|
82
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
83
|
+
"""
|
84
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
85
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
86
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
87
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
88
|
+
"""
|
89
|
+
await self.load_markets()
|
90
|
+
symbols = self.market_symbols(symbols, None, True)
|
91
|
+
name = 'instrument'
|
92
|
+
url = self.urls['api']['ws']
|
93
|
+
messageHashes = []
|
94
|
+
if symbols is not None:
|
95
|
+
for i in range(0, len(symbols)):
|
96
|
+
symbol = symbols[i]
|
97
|
+
market = self.market(symbol)
|
98
|
+
hash = name + ':' + market['id']
|
99
|
+
messageHashes.append(hash)
|
100
|
+
else:
|
101
|
+
messageHashes.append(name)
|
102
|
+
request = {
|
103
|
+
'op': 'subscribe',
|
104
|
+
'args': messageHashes,
|
105
|
+
}
|
106
|
+
ticker = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
|
107
|
+
if self.newUpdates:
|
108
|
+
if symbols is None:
|
109
|
+
return ticker
|
110
|
+
result = {}
|
111
|
+
result[ticker['symbol']] = ticker
|
112
|
+
return result
|
113
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
114
|
+
|
82
115
|
def handle_ticker(self, client: Client, message):
|
83
116
|
#
|
84
117
|
# {
|
@@ -307,18 +340,21 @@ class bitmex(ccxt.async_support.bitmex):
|
|
307
340
|
# }
|
308
341
|
#
|
309
342
|
table = self.safe_string(message, 'table')
|
310
|
-
data = self.
|
343
|
+
data = self.safe_list(message, 'data', [])
|
344
|
+
tickers = {}
|
311
345
|
for i in range(0, len(data)):
|
312
346
|
update = data[i]
|
313
|
-
marketId = self.
|
347
|
+
marketId = self.safe_string(update, 'symbol')
|
314
348
|
market = self.safe_market(marketId)
|
315
349
|
symbol = market['symbol']
|
316
350
|
messageHash = table + ':' + marketId
|
317
|
-
ticker = self.
|
318
|
-
info = self.
|
351
|
+
ticker = self.safe_dict(self.tickers, symbol, {})
|
352
|
+
info = self.safe_dict(ticker, 'info', {})
|
319
353
|
ticker = self.parse_ticker(self.extend(info, update), market)
|
354
|
+
tickers[symbol] = ticker
|
320
355
|
self.tickers[symbol] = ticker
|
321
356
|
client.resolve(ticker, messageHash)
|
357
|
+
client.resolve(tickers, 'instrument')
|
322
358
|
return message
|
323
359
|
|
324
360
|
async def watch_balance(self, params={}) -> Balances:
|
@@ -573,7 +609,7 @@ class bitmex(ccxt.async_support.bitmex):
|
|
573
609
|
return future
|
574
610
|
|
575
611
|
def handle_authentication_message(self, client: Client, message):
|
576
|
-
authenticated = self.
|
612
|
+
authenticated = self.safe_bool(message, 'success', False)
|
577
613
|
messageHash = 'authenticated'
|
578
614
|
if authenticated:
|
579
615
|
# we resolve the future here permanently so authentication only happens once
|
ccxt/pro/bitvavo.py
CHANGED
@@ -1152,7 +1152,7 @@ class bitvavo(ccxt.async_support.bitvavo):
|
|
1152
1152
|
# }
|
1153
1153
|
#
|
1154
1154
|
messageHash = 'authenticated'
|
1155
|
-
authenticated = self.
|
1155
|
+
authenticated = self.safe_bool(message, 'authenticated', False)
|
1156
1156
|
if authenticated:
|
1157
1157
|
# we resolve the future here permanently so authentication only happens once
|
1158
1158
|
client.resolve(message, messageHash)
|
ccxt/pro/bybit.py
CHANGED
@@ -1259,8 +1259,8 @@ class bybit(ccxt.async_support.bybit):
|
|
1259
1259
|
subType = None
|
1260
1260
|
subType, params = self.handle_sub_type_and_params('watchBalance', None, params)
|
1261
1261
|
unified = await self.isUnifiedEnabled()
|
1262
|
-
isUnifiedMargin = self.
|
1263
|
-
isUnifiedAccount = self.
|
1262
|
+
isUnifiedMargin = self.safe_bool(unified, 0, False)
|
1263
|
+
isUnifiedAccount = self.safe_bool(unified, 1, False)
|
1264
1264
|
url = self.get_url_by_market_type(None, True, method, params)
|
1265
1265
|
await self.authenticate(url)
|
1266
1266
|
topicByMarket = {
|
ccxt/pro/cex.py
CHANGED
@@ -686,7 +686,7 @@ class cex(ccxt.async_support.cex):
|
|
686
686
|
if order is None:
|
687
687
|
order = self.parse_ws_order_update(data, market)
|
688
688
|
order['remaining'] = remains
|
689
|
-
canceled = self.
|
689
|
+
canceled = self.safe_bool(data, 'cancel', False)
|
690
690
|
if canceled:
|
691
691
|
order['status'] = 'canceled'
|
692
692
|
if isTransaction:
|
@@ -767,7 +767,7 @@ class cex(ccxt.async_support.cex):
|
|
767
767
|
timestamp = time
|
768
768
|
if isTransaction:
|
769
769
|
timestamp = self.parse8601(time)
|
770
|
-
canceled = self.
|
770
|
+
canceled = self.safe_bool(order, 'cancel', False)
|
771
771
|
status = 'open'
|
772
772
|
if canceled:
|
773
773
|
status = 'canceled'
|
ccxt/pro/independentreserve.py
CHANGED
@@ -179,7 +179,7 @@ class independentreserve(ccxt.async_support.independentreserve):
|
|
179
179
|
orderBook = self.safe_value(message, 'Data', {})
|
180
180
|
messageHash = 'orderbook:' + symbol + ':' + depth
|
181
181
|
subscription = self.safe_value(client.subscriptions, messageHash, {})
|
182
|
-
receivedSnapshot = self.
|
182
|
+
receivedSnapshot = self.safe_bool(subscription, 'receivedSnapshot', False)
|
183
183
|
timestamp = self.safe_integer(message, 'Time')
|
184
184
|
storedOrderBook = self.safe_value(self.orderbooks, symbol)
|
185
185
|
if storedOrderBook is None:
|
ccxt/pro/okx.py
CHANGED
@@ -815,7 +815,7 @@ class okx(ccxt.async_support.okx):
|
|
815
815
|
# By default, receive order updates from any instrument type
|
816
816
|
type = None
|
817
817
|
type, params = self.handle_option_and_params(params, 'watchMyTrades', 'type', 'ANY')
|
818
|
-
isStop = self.
|
818
|
+
isStop = self.safe_bool(params, 'stop', False)
|
819
819
|
params = self.omit(params, ['stop'])
|
820
820
|
await self.load_markets()
|
821
821
|
await self.authenticate({'access': 'business' if isStop else 'private'})
|
ccxt/pro/onetrading.py
CHANGED
@@ -1020,7 +1020,7 @@ class onetrading(ccxt.async_support.onetrading):
|
|
1020
1020
|
subscription = self.safe_value(client.subscriptions, subscriptionHash)
|
1021
1021
|
if subscription is not None:
|
1022
1022
|
ohlcvMarket = self.safe_value(subscription, marketId, {})
|
1023
|
-
marketSubscribed = self.
|
1023
|
+
marketSubscribed = self.safe_bool(ohlcvMarket, timeframe, False)
|
1024
1024
|
if not marketSubscribed:
|
1025
1025
|
type = 'UPDATE_SUBSCRIPTION'
|
1026
1026
|
client.subscriptions[subscriptionHash] = None
|
@@ -1245,7 +1245,7 @@ class onetrading(ccxt.async_support.onetrading):
|
|
1245
1245
|
if subscription is not None:
|
1246
1246
|
for i in range(0, len(marketIds)):
|
1247
1247
|
marketId = marketIds[i]
|
1248
|
-
marketSubscribed = self.
|
1248
|
+
marketSubscribed = self.safe_bool(subscription, marketId, False)
|
1249
1249
|
if not marketSubscribed:
|
1250
1250
|
type = 'UPDATE_SUBSCRIPTION'
|
1251
1251
|
client.subscriptions[subscriptionHash] = None
|
ccxt/pro/p2b.py
ADDED
@@ -0,0 +1,407 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
4
|
+
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
5
|
+
|
6
|
+
import ccxt.async_support
|
7
|
+
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheByTimestamp
|
8
|
+
from ccxt.base.types import Int, OrderBook, Ticker, Trade
|
9
|
+
from ccxt.async_support.base.ws.client import Client
|
10
|
+
from typing import List
|
11
|
+
from ccxt.base.errors import ExchangeError
|
12
|
+
from ccxt.base.errors import BadRequest
|
13
|
+
|
14
|
+
|
15
|
+
class p2b(ccxt.async_support.p2b):
|
16
|
+
|
17
|
+
def describe(self):
|
18
|
+
return self.deep_extend(super(p2b, self).describe(), {
|
19
|
+
'has': {
|
20
|
+
'ws': True,
|
21
|
+
'cancelAllOrdersWs': False,
|
22
|
+
'cancelOrdersWs': False,
|
23
|
+
'cancelOrderWs': False,
|
24
|
+
'createOrderWs': False,
|
25
|
+
'editOrderWs': False,
|
26
|
+
'fetchBalanceWs': False,
|
27
|
+
'fetchOpenOrdersWs': False,
|
28
|
+
'fetchOrderWs': False,
|
29
|
+
'fetchTradesWs': False,
|
30
|
+
'watchBalance': False,
|
31
|
+
'watchMyTrades': False,
|
32
|
+
'watchOHLCV': True,
|
33
|
+
'watchOrderBook': True,
|
34
|
+
'watchOrders': False,
|
35
|
+
# 'watchStatus': True,
|
36
|
+
'watchTicker': True,
|
37
|
+
'watchTickers': False, # in the docs but does not return anything when subscribed to
|
38
|
+
'watchTrades': True,
|
39
|
+
},
|
40
|
+
'urls': {
|
41
|
+
'api': {
|
42
|
+
'ws': 'wss://apiws.p2pb2b.com/',
|
43
|
+
},
|
44
|
+
},
|
45
|
+
'options': {
|
46
|
+
'OHLCVLimit': 1000,
|
47
|
+
'tradesLimit': 1000,
|
48
|
+
'timeframes': {
|
49
|
+
'15m': 900,
|
50
|
+
'30m': 1800,
|
51
|
+
'1h': 3600,
|
52
|
+
'1d': 86400,
|
53
|
+
},
|
54
|
+
'watchTicker': {
|
55
|
+
'name': 'state', # or 'price'
|
56
|
+
},
|
57
|
+
'watchTickers': {
|
58
|
+
'name': 'state', # or 'price'
|
59
|
+
},
|
60
|
+
},
|
61
|
+
'streaming': {
|
62
|
+
'ping': self.ping,
|
63
|
+
},
|
64
|
+
})
|
65
|
+
|
66
|
+
async def subscribe(self, name: str, messageHash: str, request, params={}):
|
67
|
+
"""
|
68
|
+
* @ignore
|
69
|
+
Connects to a websocket channel
|
70
|
+
:param str name: name of the channel
|
71
|
+
:param str messageHash: string to look up in handler
|
72
|
+
:param str[]|float[] request: endpoint parameters
|
73
|
+
:param dict [params]: extra parameters specific to the p2b api
|
74
|
+
:returns dict: data from the websocket stream
|
75
|
+
"""
|
76
|
+
url = self.urls['api']['ws']
|
77
|
+
subscribe = {
|
78
|
+
'method': name,
|
79
|
+
'params': request,
|
80
|
+
'id': self.milliseconds(),
|
81
|
+
}
|
82
|
+
query = self.extend(subscribe, params)
|
83
|
+
return await self.watch(url, messageHash, query, messageHash)
|
84
|
+
|
85
|
+
async def watch_ohlcv(self, symbol: str, timeframe='15m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
86
|
+
"""
|
87
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market. Can only subscribe to one timeframe at a time for each symbol
|
88
|
+
:see: https://github.com/P2B-team/P2B-WSS-Public/blob/main/wss_documentation.md#kline-candlestick
|
89
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
90
|
+
:param str timeframe: 15m, 30m, 1h or 1d
|
91
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
92
|
+
:param int [limit]: the maximum amount of candles to fetch
|
93
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
94
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
95
|
+
"""
|
96
|
+
await self.load_markets()
|
97
|
+
timeframes = self.safe_value(self.options, 'timeframes', {})
|
98
|
+
channel = self.safe_integer(timeframes, timeframe)
|
99
|
+
if channel is None:
|
100
|
+
raise BadRequest(self.id + ' watchOHLCV cannot take a timeframe of ' + timeframe)
|
101
|
+
market = self.market(symbol)
|
102
|
+
request = [
|
103
|
+
market['id'],
|
104
|
+
channel,
|
105
|
+
]
|
106
|
+
messageHash = 'kline::' + market['symbol']
|
107
|
+
ohlcv = await self.subscribe('kline.subscribe', messageHash, request, params)
|
108
|
+
if self.newUpdates:
|
109
|
+
limit = ohlcv.getLimit(symbol, limit)
|
110
|
+
return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
|
111
|
+
|
112
|
+
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
113
|
+
"""
|
114
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
115
|
+
:see: https://github.com/P2B-team/P2B-WSS-Public/blob/main/wss_documentation.md#last-price
|
116
|
+
:see: https://github.com/P2B-team/P2B-WSS-Public/blob/main/wss_documentation.md#market-status
|
117
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
118
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
119
|
+
:param dict [params.method]: 'state'(default) or 'price'
|
120
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
121
|
+
"""
|
122
|
+
await self.load_markets()
|
123
|
+
watchTickerOptions = self.safe_value(self.options, 'watchTicker')
|
124
|
+
name = self.safe_string(watchTickerOptions, 'name', 'state') # or price
|
125
|
+
name, params = self.handle_option_and_params(params, 'method', 'name', name)
|
126
|
+
market = self.market(symbol)
|
127
|
+
request = [
|
128
|
+
market['id'],
|
129
|
+
]
|
130
|
+
messageHash = name + '::' + market['symbol']
|
131
|
+
return await self.subscribe(name + '.subscribe', messageHash, request, params)
|
132
|
+
|
133
|
+
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
134
|
+
"""
|
135
|
+
get the list of most recent trades for a particular symbol
|
136
|
+
:see: https://github.com/P2B-team/P2B-WSS-Public/blob/main/wss_documentation.md#deals
|
137
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
138
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
139
|
+
:param int [limit]: the maximum amount of trades to fetch
|
140
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
141
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
142
|
+
"""
|
143
|
+
await self.load_markets()
|
144
|
+
market = self.market(symbol)
|
145
|
+
request = [
|
146
|
+
market['id'],
|
147
|
+
]
|
148
|
+
messageHash = 'deals::' + market['symbol']
|
149
|
+
trades = await self.subscribe('deals.subscribe', messageHash, request, params)
|
150
|
+
if self.newUpdates:
|
151
|
+
limit = trades.getLimit(symbol, limit)
|
152
|
+
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
153
|
+
|
154
|
+
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
155
|
+
"""
|
156
|
+
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
157
|
+
:see: https://github.com/P2B-team/P2B-WSS-Public/blob/main/wss_documentation.md#depth-of-market
|
158
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
159
|
+
:param int [limit]: 1-100, default=100
|
160
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
161
|
+
:param float [params.interval]: 0, 0.00000001, 0.0000001, 0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, interval of precision for order, default=0.001
|
162
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
163
|
+
"""
|
164
|
+
await self.load_markets()
|
165
|
+
market = self.market(symbol)
|
166
|
+
name = 'depth.subscribe'
|
167
|
+
messageHash = 'orderbook::' + market['symbol']
|
168
|
+
interval = self.safe_string(params, 'interval', '0.001')
|
169
|
+
if limit is None:
|
170
|
+
limit = 100
|
171
|
+
request = [
|
172
|
+
market['id'],
|
173
|
+
limit,
|
174
|
+
interval,
|
175
|
+
]
|
176
|
+
orderbook = await self.subscribe(name, messageHash, request, params)
|
177
|
+
return orderbook.limit()
|
178
|
+
|
179
|
+
def handle_ohlcv(self, client: Client, message):
|
180
|
+
#
|
181
|
+
# {
|
182
|
+
# "method": "kline.update",
|
183
|
+
# "params": [
|
184
|
+
# [
|
185
|
+
# 1657648800, # Kline start time
|
186
|
+
# "0.054146", # Kline open price
|
187
|
+
# "0.053938", # Kline close price(current price)
|
188
|
+
# "0.054146", # Kline high price
|
189
|
+
# "0.053911", # Kline low price
|
190
|
+
# "596.4674", # Volume for stock currency
|
191
|
+
# "32.2298758767", # Volume for money currency
|
192
|
+
# "ETH_BTC" # Market
|
193
|
+
# ]
|
194
|
+
# ],
|
195
|
+
# "id": null
|
196
|
+
# }
|
197
|
+
#
|
198
|
+
data = self.safe_list(message, 'params')
|
199
|
+
data = self.safe_list(data, 0)
|
200
|
+
method = self.safe_string(message, 'method')
|
201
|
+
splitMethod = method.split('.')
|
202
|
+
channel = self.safe_string(splitMethod, 0)
|
203
|
+
marketId = self.safe_string(data, 7)
|
204
|
+
market = self.safe_market(marketId)
|
205
|
+
timeframes = self.safe_dict(self.options, 'timeframes', {})
|
206
|
+
timeframe = self.find_timeframe(channel, timeframes)
|
207
|
+
symbol = self.safe_string(market, 'symbol')
|
208
|
+
messageHash = channel + '::' + symbol
|
209
|
+
parsed = self.parse_ohlcv(data, market)
|
210
|
+
self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
|
211
|
+
stored = self.safe_value(self.ohlcvs[symbol], timeframe)
|
212
|
+
if symbol is not None:
|
213
|
+
if stored is None:
|
214
|
+
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
215
|
+
stored = ArrayCacheByTimestamp(limit)
|
216
|
+
self.ohlcvs[symbol][timeframe] = stored
|
217
|
+
stored.append(parsed)
|
218
|
+
client.resolve(stored, messageHash)
|
219
|
+
return message
|
220
|
+
|
221
|
+
def handle_trade(self, client: Client, message):
|
222
|
+
#
|
223
|
+
# {
|
224
|
+
# "method": "deals.update",
|
225
|
+
# "params": [
|
226
|
+
# "ETH_BTC",
|
227
|
+
# [
|
228
|
+
# {
|
229
|
+
# "id": 4503032979, # Order_id
|
230
|
+
# "amount": "0.103",
|
231
|
+
# "type": "sell", # Side
|
232
|
+
# "time": 1657661950.8487639, # Creation time
|
233
|
+
# "price": "0.05361"
|
234
|
+
# },
|
235
|
+
# ...
|
236
|
+
# ]
|
237
|
+
# ],
|
238
|
+
# "id": null
|
239
|
+
# }
|
240
|
+
#
|
241
|
+
data = self.safe_list(message, 'params', [])
|
242
|
+
trades = self.safe_list(data, 1)
|
243
|
+
marketId = self.safe_string(data, 0)
|
244
|
+
market = self.safe_market(marketId)
|
245
|
+
symbol = self.safe_string(market, 'symbol')
|
246
|
+
tradesArray = self.safe_value(self.trades, symbol)
|
247
|
+
if tradesArray is None:
|
248
|
+
tradesLimit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
249
|
+
tradesArray = ArrayCache(tradesLimit)
|
250
|
+
self.trades[symbol] = tradesArray
|
251
|
+
for i in range(0, len(trades)):
|
252
|
+
item = trades[i]
|
253
|
+
trade = self.parse_trade(item, market)
|
254
|
+
tradesArray.append(trade)
|
255
|
+
messageHash = 'deals::' + symbol
|
256
|
+
client.resolve(tradesArray, messageHash)
|
257
|
+
return message
|
258
|
+
|
259
|
+
def handle_ticker(self, client: Client, message):
|
260
|
+
#
|
261
|
+
# state
|
262
|
+
#
|
263
|
+
# {
|
264
|
+
# "method": "state.update",
|
265
|
+
# "params": [
|
266
|
+
# "ETH_BTC",
|
267
|
+
# {
|
268
|
+
# "high": "0.055774", # High price for the last 24h
|
269
|
+
# "close": "0.053679", # Close price for the last 24h
|
270
|
+
# "low": "0.053462", # Low price for the last 24h
|
271
|
+
# "period": 86400, # Period 24h
|
272
|
+
# "last": "0.053679", # Last price for the last 24h
|
273
|
+
# "volume": "38463.6132", # Stock volume for the last 24h
|
274
|
+
# "open": "0.055682", # Open price for the last 24h
|
275
|
+
# "deal": "2091.0038055314" # Money volume for the last 24h
|
276
|
+
# }
|
277
|
+
# ],
|
278
|
+
# "id": null
|
279
|
+
# }
|
280
|
+
#
|
281
|
+
# price
|
282
|
+
#
|
283
|
+
# {
|
284
|
+
# "method": "price.update",
|
285
|
+
# "params": [
|
286
|
+
# "ETH_BTC", # market
|
287
|
+
# "0.053836" # last price
|
288
|
+
# ],
|
289
|
+
# "id": null
|
290
|
+
# }
|
291
|
+
#
|
292
|
+
data = self.safe_list(message, 'params', [])
|
293
|
+
marketId = self.safe_string(data, 0)
|
294
|
+
market = self.safe_market(marketId)
|
295
|
+
method = self.safe_string(message, 'method')
|
296
|
+
splitMethod = method.split('.')
|
297
|
+
messageHashStart = self.safe_string(splitMethod, 0)
|
298
|
+
tickerData = self.safe_dict(data, 1)
|
299
|
+
ticker = None
|
300
|
+
if method == 'price.update':
|
301
|
+
lastPrice = self.safe_string(data, 1)
|
302
|
+
ticker = self.safe_ticker({
|
303
|
+
'last': lastPrice,
|
304
|
+
'close': lastPrice,
|
305
|
+
'symbol': market['symbol'],
|
306
|
+
})
|
307
|
+
else:
|
308
|
+
ticker = self.parse_ticker(tickerData, market)
|
309
|
+
symbol = ticker['symbol']
|
310
|
+
messageHash = messageHashStart + '::' + symbol
|
311
|
+
client.resolve(ticker, messageHash)
|
312
|
+
return message
|
313
|
+
|
314
|
+
def handle_order_book(self, client: Client, message):
|
315
|
+
#
|
316
|
+
# {
|
317
|
+
# "method": "depth.update",
|
318
|
+
# "params": [
|
319
|
+
# False, # True - all records, False - new records
|
320
|
+
# {
|
321
|
+
# "asks": [ # side
|
322
|
+
# [
|
323
|
+
# "19509.81", # price
|
324
|
+
# "0.277" # amount
|
325
|
+
# ]
|
326
|
+
# ]
|
327
|
+
# },
|
328
|
+
# "BTC_USDT"
|
329
|
+
# ],
|
330
|
+
# "id": null
|
331
|
+
# }
|
332
|
+
#
|
333
|
+
params = self.safe_list(message, 'params', [])
|
334
|
+
data = self.safe_dict(params, 1)
|
335
|
+
asks = self.safe_list(data, 'asks')
|
336
|
+
bids = self.safe_list(data, 'bids')
|
337
|
+
marketId = self.safe_string(params, 2)
|
338
|
+
market = self.safe_market(marketId)
|
339
|
+
symbol = market['symbol']
|
340
|
+
messageHash = 'orderbook::' + market['symbol']
|
341
|
+
subscription = self.safe_value(client.subscriptions, messageHash, {})
|
342
|
+
limit = self.safe_integer(subscription, 'limit')
|
343
|
+
orderbook = self.safe_value(self.orderbooks, symbol)
|
344
|
+
if orderbook is None:
|
345
|
+
self.orderbooks[symbol] = self.order_book({}, limit)
|
346
|
+
orderbook = self.orderbooks[symbol]
|
347
|
+
if bids is not None:
|
348
|
+
for i in range(0, len(bids)):
|
349
|
+
bid = self.safe_value(bids, i)
|
350
|
+
price = self.safe_number(bid, 0)
|
351
|
+
amount = self.safe_number(bid, 1)
|
352
|
+
orderbook['bids'].store(price, amount)
|
353
|
+
if asks is not None:
|
354
|
+
for i in range(0, len(asks)):
|
355
|
+
ask = self.safe_value(asks, i)
|
356
|
+
price = self.safe_number(ask, 0)
|
357
|
+
amount = self.safe_number(ask, 1)
|
358
|
+
orderbook['asks'].store(price, amount)
|
359
|
+
orderbook['symbol'] = symbol
|
360
|
+
client.resolve(orderbook, messageHash)
|
361
|
+
|
362
|
+
def handle_message(self, client: Client, message):
|
363
|
+
if self.handle_error_message(client, message):
|
364
|
+
return
|
365
|
+
result = self.safe_string(message, 'result')
|
366
|
+
if result == 'pong':
|
367
|
+
self.handle_pong(client, message)
|
368
|
+
return
|
369
|
+
method = self.safe_string(message, 'method')
|
370
|
+
methods = {
|
371
|
+
'depth.update': self.handle_order_book,
|
372
|
+
'price.update': self.handle_ticker,
|
373
|
+
'kline.update': self.handle_ohlcv,
|
374
|
+
'state.update': self.handle_ticker,
|
375
|
+
'deals.update': self.handle_trade,
|
376
|
+
}
|
377
|
+
endpoint = self.safe_value(methods, method)
|
378
|
+
if endpoint is not None:
|
379
|
+
return endpoint(client, message)
|
380
|
+
|
381
|
+
def handle_error_message(self, client: Client, message):
|
382
|
+
error = self.safe_string(message, 'error')
|
383
|
+
if error is not None:
|
384
|
+
raise ExchangeError(self.id + ' error: ' + self.json(error))
|
385
|
+
return False
|
386
|
+
|
387
|
+
def ping(self, client):
|
388
|
+
"""
|
389
|
+
:see: https://github.com/P2B-team/P2B-WSS-Public/blob/main/wss_documentation.md#ping
|
390
|
+
* @param client
|
391
|
+
"""
|
392
|
+
return {
|
393
|
+
'method': 'server.ping',
|
394
|
+
'params': [],
|
395
|
+
'id': self.milliseconds(),
|
396
|
+
}
|
397
|
+
|
398
|
+
def handle_pong(self, client: Client, message):
|
399
|
+
#
|
400
|
+
# {
|
401
|
+
# error: null,
|
402
|
+
# result: 'pong',
|
403
|
+
# id: 1706539608030
|
404
|
+
# }
|
405
|
+
#
|
406
|
+
client.lastPong = self.safe_integer(message, 'id')
|
407
|
+
return message
|
ccxt/pro/probit.py
CHANGED
@@ -103,7 +103,7 @@ class probit(ccxt.async_support.probit):
|
|
103
103
|
# }
|
104
104
|
# }
|
105
105
|
#
|
106
|
-
reset = self.
|
106
|
+
reset = self.safe_bool(message, 'reset', False)
|
107
107
|
data = self.safe_value(message, 'data', {})
|
108
108
|
currencyIds = list(data.keys())
|
109
109
|
if reset:
|
@@ -202,7 +202,7 @@ class probit(ccxt.async_support.probit):
|
|
202
202
|
symbol = self.safe_symbol(marketId)
|
203
203
|
market = self.safe_market(marketId)
|
204
204
|
trades = self.safe_value(message, 'recent_trades', [])
|
205
|
-
reset = self.
|
205
|
+
reset = self.safe_bool(message, 'reset', False)
|
206
206
|
messageHash = 'trades:' + symbol
|
207
207
|
stored = self.safe_value(self.trades, symbol)
|
208
208
|
if stored is None or reset:
|
@@ -268,7 +268,7 @@ class probit(ccxt.async_support.probit):
|
|
268
268
|
length = len(rawTrades)
|
269
269
|
if length == 0:
|
270
270
|
return
|
271
|
-
reset = self.
|
271
|
+
reset = self.safe_bool(message, 'reset', False)
|
272
272
|
messageHash = 'myTrades'
|
273
273
|
stored = self.myTrades
|
274
274
|
if (stored is None) or reset:
|
@@ -348,7 +348,7 @@ class probit(ccxt.async_support.probit):
|
|
348
348
|
if length == 0:
|
349
349
|
return
|
350
350
|
messageHash = 'orders'
|
351
|
-
reset = self.
|
351
|
+
reset = self.safe_bool(message, 'reset', False)
|
352
352
|
stored = self.orders
|
353
353
|
if stored is None or reset:
|
354
354
|
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
@@ -432,7 +432,7 @@ class probit(ccxt.async_support.probit):
|
|
432
432
|
if storedOrderBook is None:
|
433
433
|
storedOrderBook = self.order_book({})
|
434
434
|
self.orderbooks[symbol] = storedOrderBook
|
435
|
-
reset = self.
|
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')
|
438
438
|
storedOrderBook.reset(snapshot)
|
ccxt/pro/whitebit.py
CHANGED
@@ -698,7 +698,7 @@ class whitebit(ccxt.async_support.whitebit):
|
|
698
698
|
hasSymbolSubscription = True
|
699
699
|
market = self.market(symbol)
|
700
700
|
marketId = market['id']
|
701
|
-
isSubscribed = self.
|
701
|
+
isSubscribed = self.safe_bool(subscription, marketId, False)
|
702
702
|
if not isSubscribed:
|
703
703
|
subscription[marketId] = True
|
704
704
|
hasSymbolSubscription = False
|
ccxt/probit.py
CHANGED
@@ -297,7 +297,7 @@ class probit(Exchange, ImplicitAPI):
|
|
297
297
|
quoteId = self.safe_string(market, 'quote_currency_id')
|
298
298
|
base = self.safe_currency_code(baseId)
|
299
299
|
quote = self.safe_currency_code(quoteId)
|
300
|
-
closed = self.
|
300
|
+
closed = self.safe_bool(market, 'closed', False)
|
301
301
|
takerFeeRate = self.safe_string(market, 'taker_fee_rate')
|
302
302
|
taker = Precise.string_div(takerFeeRate, '100')
|
303
303
|
makerFeeRate = self.safe_string(market, 'maker_fee_rate')
|
ccxt/timex.py
CHANGED
@@ -109,7 +109,7 @@ class timex(Exchange, ImplicitAPI):
|
|
109
109
|
'rest': 'https://plasma-relay-backend.timex.io',
|
110
110
|
},
|
111
111
|
'www': 'https://timex.io',
|
112
|
-
'doc': 'https://
|
112
|
+
'doc': 'https://plasma-relay-backend.timex.io/swagger-ui/index.html',
|
113
113
|
'referral': 'https://timex.io/?refcode=1x27vNkTbP1uwkCck',
|
114
114
|
},
|
115
115
|
'api': {
|
@@ -701,7 +701,7 @@ class timex(Exchange, ImplicitAPI):
|
|
701
701
|
market = self.market(symbol)
|
702
702
|
uppercaseSide = side.upper()
|
703
703
|
uppercaseType = type.upper()
|
704
|
-
postOnly = self.
|
704
|
+
postOnly = self.safe_bool(params, 'postOnly', False)
|
705
705
|
if postOnly:
|
706
706
|
uppercaseType = 'POST_ONLY'
|
707
707
|
params = self.omit(params, ['postOnly'])
|