ccxt 4.3.62__py2.py3-none-any.whl → 4.3.63__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 +2 -1
- ccxt/abstract/binance.py +5 -5
- ccxt/abstract/binancecoinm.py +5 -5
- ccxt/abstract/binanceus.py +5 -5
- ccxt/abstract/binanceusdm.py +5 -5
- ccxt/abstract/cryptocom.py +11 -0
- ccxt/abstract/woo.py +3 -0
- ccxt/ace.py +33 -15
- ccxt/async_support/__init__.py +2 -1
- ccxt/async_support/ace.py +33 -15
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +6 -9
- ccxt/async_support/bingx.py +451 -151
- ccxt/async_support/coinbaseinternational.py +1 -1
- ccxt/async_support/cryptocom.py +17 -2
- ccxt/async_support/mercado.py +5 -1
- ccxt/async_support/woo.py +296 -81
- ccxt/async_support/xt.py +3 -3
- ccxt/base/errors.py +8 -1
- ccxt/base/exchange.py +8 -2
- ccxt/binance.py +6 -9
- ccxt/bingx.py +451 -151
- ccxt/coinbaseinternational.py +1 -1
- ccxt/cryptocom.py +17 -2
- ccxt/mercado.py +5 -1
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +56 -35
- ccxt/pro/bitfinex2.py +6 -4
- ccxt/pro/bitget.py +5 -2
- ccxt/pro/bitvavo.py +1 -1
- ccxt/pro/bybit.py +41 -18
- ccxt/pro/cryptocom.py +7 -2
- ccxt/pro/gate.py +6 -3
- ccxt/pro/htx.py +5 -1
- ccxt/pro/independentreserve.py +6 -4
- ccxt/pro/kraken.py +79 -6
- ccxt/pro/okx.py +4 -4
- ccxt/pro/poloniexfutures.py +5 -2
- ccxt/pro/woofipro.py +1 -1
- ccxt/woo.py +296 -81
- ccxt/xt.py +3 -3
- {ccxt-4.3.62.dist-info → ccxt-4.3.63.dist-info}/METADATA +4 -4
- {ccxt-4.3.62.dist-info → ccxt-4.3.63.dist-info}/RECORD +46 -46
- {ccxt-4.3.62.dist-info → ccxt-4.3.63.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.3.62.dist-info → ccxt-4.3.63.dist-info}/WHEEL +0 -0
- {ccxt-4.3.62.dist-info → ccxt-4.3.63.dist-info}/top_level.txt +0 -0
ccxt/coinbaseinternational.py
CHANGED
@@ -571,7 +571,7 @@ class coinbaseinternational(Exchange, ImplicitAPI):
|
|
571
571
|
}
|
572
572
|
return self.v1PrivatePostPortfoliosMargin(self.extend(request, params))
|
573
573
|
|
574
|
-
def fetch_deposits_withdrawals(self, code:
|
574
|
+
def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
575
575
|
"""
|
576
576
|
fetch history of deposits and withdrawals
|
577
577
|
:see: https://docs.cloud.coinbase.com/intx/reference/gettransfers
|
ccxt/cryptocom.py
CHANGED
@@ -176,6 +176,9 @@ class cryptocom(Exchange, ImplicitAPI):
|
|
176
176
|
'public/get-expired-settlement-price': 10 / 3,
|
177
177
|
'public/get-insurance': 1,
|
178
178
|
},
|
179
|
+
'post': {
|
180
|
+
'public/staking/get-conversion-rate': 2,
|
181
|
+
},
|
179
182
|
},
|
180
183
|
'private': {
|
181
184
|
'post': {
|
@@ -205,6 +208,16 @@ class cryptocom(Exchange, ImplicitAPI):
|
|
205
208
|
'private/get-accounts': 10 / 3,
|
206
209
|
'private/get-withdrawal-history': 10 / 3,
|
207
210
|
'private/get-deposit-history': 10 / 3,
|
211
|
+
'private/staking/stake': 2,
|
212
|
+
'private/staking/unstake': 2,
|
213
|
+
'private/staking/get-staking-position': 2,
|
214
|
+
'private/staking/get-staking-instruments': 2,
|
215
|
+
'private/staking/get-open-stake': 2,
|
216
|
+
'private/staking/get-stake-history': 2,
|
217
|
+
'private/staking/get-reward-history': 2,
|
218
|
+
'private/staking/convert': 2,
|
219
|
+
'private/staking/get-open-convert': 2,
|
220
|
+
'private/staking/get-convert-history': 2,
|
208
221
|
},
|
209
222
|
},
|
210
223
|
},
|
@@ -799,15 +812,17 @@ class cryptocom(Exchange, ImplicitAPI):
|
|
799
812
|
'timeframe': self.safe_string(self.timeframes, timeframe, timeframe),
|
800
813
|
}
|
801
814
|
if limit is not None:
|
815
|
+
if limit > 300:
|
816
|
+
limit = 300
|
802
817
|
request['count'] = limit
|
803
818
|
now = self.microseconds()
|
804
819
|
duration = self.parse_timeframe(timeframe)
|
805
820
|
until = self.safe_integer(params, 'until', now)
|
806
821
|
params = self.omit(params, ['until'])
|
807
822
|
if since is not None:
|
808
|
-
request['start_ts'] = since
|
823
|
+
request['start_ts'] = since - duration * 1000
|
809
824
|
if limit is not None:
|
810
|
-
request['end_ts'] = self.sum(since, duration *
|
825
|
+
request['end_ts'] = self.sum(since, duration * limit * 1000)
|
811
826
|
else:
|
812
827
|
request['end_ts'] = until
|
813
828
|
else:
|
ccxt/mercado.py
CHANGED
@@ -12,6 +12,7 @@ from ccxt.base.errors import ExchangeError
|
|
12
12
|
from ccxt.base.errors import ArgumentsRequired
|
13
13
|
from ccxt.base.errors import InvalidOrder
|
14
14
|
from ccxt.base.decimal_to_precision import TICK_SIZE
|
15
|
+
from ccxt.base.precise import Precise
|
15
16
|
|
16
17
|
|
17
18
|
class mercado(Exchange, ImplicitAPI):
|
@@ -444,7 +445,10 @@ class mercado(Exchange, ImplicitAPI):
|
|
444
445
|
if side == 'buy':
|
445
446
|
if price is None:
|
446
447
|
raise InvalidOrder(self.id + ' createOrder() requires the price argument with market buy orders to calculate total order cost(amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount')
|
447
|
-
|
448
|
+
amountString = self.number_to_string(amount)
|
449
|
+
priceString = self.number_to_string(price)
|
450
|
+
cost = self.parse_to_numeric(Precise.string_mul(amountString, priceString))
|
451
|
+
request['cost'] = self.price_to_precision(market['symbol'], cost)
|
448
452
|
else:
|
449
453
|
request['quantity'] = self.amount_to_precision(market['symbol'], amount)
|
450
454
|
response = getattr(self, method)(self.extend(request, params))
|
ccxt/pro/__init__.py
CHANGED
ccxt/pro/binance.py
CHANGED
@@ -12,7 +12,7 @@ from typing import List
|
|
12
12
|
from ccxt.base.errors import ArgumentsRequired
|
13
13
|
from ccxt.base.errors import BadRequest
|
14
14
|
from ccxt.base.errors import NotSupported
|
15
|
-
from ccxt.base.errors import
|
15
|
+
from ccxt.base.errors import ChecksumError
|
16
16
|
from ccxt.base.precise import Precise
|
17
17
|
|
18
18
|
|
@@ -30,7 +30,7 @@ class binance(ccxt.async_support.binance):
|
|
30
30
|
'watchBidsAsks': True,
|
31
31
|
'watchMyTrades': True,
|
32
32
|
'watchOHLCV': True,
|
33
|
-
'watchOHLCVForSymbols':
|
33
|
+
'watchOHLCVForSymbols': True,
|
34
34
|
'watchOrderBook': True,
|
35
35
|
'watchOrderBookForSymbols': True,
|
36
36
|
'watchOrders': True,
|
@@ -133,6 +133,7 @@ class binance(ccxt.async_support.binance):
|
|
133
133
|
},
|
134
134
|
'watchOrderBook': {
|
135
135
|
'maxRetries': 3,
|
136
|
+
'checksum': True,
|
136
137
|
},
|
137
138
|
'watchBalance': {
|
138
139
|
'fetchBalanceSnapshot': False, # or True
|
@@ -805,10 +806,10 @@ class binance(ccxt.async_support.binance):
|
|
805
806
|
if nonce < orderbook['nonce']:
|
806
807
|
client.resolve(orderbook, messageHash)
|
807
808
|
else:
|
808
|
-
checksum = self.
|
809
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
809
810
|
if checksum:
|
810
811
|
# todo: client.reject from handleOrderBookMessage properly
|
811
|
-
raise
|
812
|
+
raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
812
813
|
else:
|
813
814
|
# future
|
814
815
|
# 4. Drop any event where u is < lastUpdateId in the snapshot
|
@@ -820,10 +821,10 @@ class binance(ccxt.async_support.binance):
|
|
820
821
|
if nonce <= orderbook['nonce']:
|
821
822
|
client.resolve(orderbook, messageHash)
|
822
823
|
else:
|
823
|
-
checksum = self.
|
824
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
824
825
|
if checksum:
|
825
826
|
# todo: client.reject from handleOrderBookMessage properly
|
826
|
-
raise
|
827
|
+
raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
827
828
|
except Exception as e:
|
828
829
|
del self.orderbooks[symbol]
|
829
830
|
del client.subscriptions[messageHash]
|
@@ -1104,37 +1105,57 @@ class binance(ccxt.async_support.binance):
|
|
1104
1105
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1105
1106
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
1106
1107
|
"""
|
1108
|
+
params['callerMethodName'] = 'watchOHLCV'
|
1109
|
+
result = await self.watch_ohlcv_for_symbols([[symbol, timeframe]], since, limit, params)
|
1110
|
+
return result[symbol][timeframe]
|
1111
|
+
|
1112
|
+
async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
|
1113
|
+
"""
|
1114
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
1115
|
+
:param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
|
1116
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
1117
|
+
:param int [limit]: the maximum amount of candles to fetch
|
1118
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1119
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
1120
|
+
"""
|
1107
1121
|
await self.load_markets()
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
if
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1122
|
+
klineType = None
|
1123
|
+
klineType, params = self.handle_param_string_2(params, 'channel', 'name', 'kline')
|
1124
|
+
symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
|
1125
|
+
marketSymbols = self.market_symbols(symbols, None, False, False, True)
|
1126
|
+
firstMarket = self.market(marketSymbols[0])
|
1127
|
+
type = firstMarket['type']
|
1128
|
+
if firstMarket['contract']:
|
1129
|
+
type = 'future' if firstMarket['linear'] else 'delivery'
|
1130
|
+
rawHashes = []
|
1131
|
+
messageHashes = []
|
1132
|
+
for i in range(0, len(symbolsAndTimeframes)):
|
1133
|
+
symAndTf = symbolsAndTimeframes[i]
|
1134
|
+
symbolString = symAndTf[0]
|
1135
|
+
timeframeString = symAndTf[1]
|
1136
|
+
interval = self.safe_string(self.timeframes, timeframeString, timeframeString)
|
1137
|
+
market = self.market(symbolString)
|
1138
|
+
marketId = market['lowercaseId']
|
1139
|
+
if klineType == 'indexPriceKline':
|
1140
|
+
# weird behavior for index price kline we can't use the perp suffix
|
1141
|
+
marketId = marketId.replace('_perp', '')
|
1142
|
+
rawHashes.append(marketId + '@' + klineType + '_' + interval)
|
1143
|
+
messageHashes.append('ohlcv::' + symbolString + '::' + timeframeString)
|
1144
|
+
url = self.urls['api']['ws'][type] + '/' + self.stream(type, 'multipleOHLCV')
|
1123
1145
|
requestId = self.request_id(url)
|
1124
|
-
request
|
1146
|
+
request = {
|
1125
1147
|
'method': 'SUBSCRIBE',
|
1126
|
-
'params':
|
1127
|
-
messageHash,
|
1128
|
-
],
|
1148
|
+
'params': rawHashes,
|
1129
1149
|
'id': requestId,
|
1130
1150
|
}
|
1131
|
-
subscribe
|
1151
|
+
subscribe = {
|
1132
1152
|
'id': requestId,
|
1133
1153
|
}
|
1134
|
-
|
1154
|
+
symbol, timeframe, candles = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscribe)
|
1135
1155
|
if self.newUpdates:
|
1136
|
-
limit =
|
1137
|
-
|
1156
|
+
limit = candles.getLimit(symbol, limit)
|
1157
|
+
filtered = self.filter_by_since_limit(candles, since, limit, 0, True)
|
1158
|
+
return self.create_ohlcv_object(symbol, timeframe, filtered)
|
1138
1159
|
|
1139
1160
|
def handle_ohlcv(self, client: Client, message):
|
1140
1161
|
#
|
@@ -1174,11 +1195,9 @@ class binance(ccxt.async_support.binance):
|
|
1174
1195
|
if event == 'indexPriceKline':
|
1175
1196
|
# indexPriceKline doesn't have the _PERP suffix
|
1176
1197
|
marketId = self.safe_string(message, 'ps')
|
1177
|
-
lowercaseMarketId = marketId.lower()
|
1178
1198
|
interval = self.safe_string(kline, 'i')
|
1179
1199
|
# use a reverse lookup in a static map instead
|
1180
|
-
|
1181
|
-
messageHash = lowercaseMarketId + '@' + event + '_' + interval
|
1200
|
+
unifiedTimeframe = self.find_timeframe(interval)
|
1182
1201
|
parsed = [
|
1183
1202
|
self.safe_integer(kline, 't'),
|
1184
1203
|
self.safe_float(kline, 'o'),
|
@@ -1190,14 +1209,16 @@ class binance(ccxt.async_support.binance):
|
|
1190
1209
|
isSpot = ((client.url.find('/stream') > -1) or (client.url.find('/testnet.binance') > -1))
|
1191
1210
|
marketType = 'spot' if (isSpot) else 'contract'
|
1192
1211
|
symbol = self.safe_symbol(marketId, None, None, marketType)
|
1212
|
+
messageHash = 'ohlcv::' + symbol + '::' + unifiedTimeframe
|
1193
1213
|
self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
|
1194
|
-
stored = self.safe_value(self.ohlcvs[symbol],
|
1214
|
+
stored = self.safe_value(self.ohlcvs[symbol], unifiedTimeframe)
|
1195
1215
|
if stored is None:
|
1196
1216
|
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
1197
1217
|
stored = ArrayCacheByTimestamp(limit)
|
1198
|
-
self.ohlcvs[symbol][
|
1218
|
+
self.ohlcvs[symbol][unifiedTimeframe] = stored
|
1199
1219
|
stored.append(parsed)
|
1200
|
-
|
1220
|
+
resolveData = [symbol, unifiedTimeframe, stored]
|
1221
|
+
client.resolve(resolveData, messageHash)
|
1201
1222
|
|
1202
1223
|
async def fetch_ticker_ws(self, symbol: str, params={}) -> Ticker:
|
1203
1224
|
"""
|
ccxt/pro/bitfinex2.py
CHANGED
@@ -11,7 +11,7 @@ from ccxt.async_support.base.ws.client import Client
|
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
13
13
|
from ccxt.base.errors import AuthenticationError
|
14
|
-
from ccxt.base.errors import
|
14
|
+
from ccxt.base.errors import ChecksumError
|
15
15
|
from ccxt.base.precise import Precise
|
16
16
|
|
17
17
|
|
@@ -42,9 +42,9 @@ class bitfinex2(ccxt.async_support.bitfinex2):
|
|
42
42
|
'watchOrderBook': {
|
43
43
|
'prec': 'P0',
|
44
44
|
'freq': 'F0',
|
45
|
+
'checksum': True,
|
45
46
|
},
|
46
47
|
'ordersLimit': 1000,
|
47
|
-
'checksum': True,
|
48
48
|
},
|
49
49
|
})
|
50
50
|
|
@@ -641,10 +641,12 @@ class bitfinex2(ccxt.async_support.bitfinex2):
|
|
641
641
|
localChecksum = self.crc32(payload, True)
|
642
642
|
responseChecksum = self.safe_integer(message, 2)
|
643
643
|
if responseChecksum != localChecksum:
|
644
|
-
error = InvalidNonce(self.id + ' invalid checksum')
|
645
644
|
del client.subscriptions[messageHash]
|
646
645
|
del self.orderbooks[symbol]
|
647
|
-
|
646
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
647
|
+
if checksum:
|
648
|
+
error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
649
|
+
client.reject(error, messageHash)
|
648
650
|
|
649
651
|
async def watch_balance(self, params={}) -> Balances:
|
650
652
|
"""
|
ccxt/pro/bitget.py
CHANGED
@@ -14,7 +14,7 @@ from ccxt.base.errors import AuthenticationError
|
|
14
14
|
from ccxt.base.errors import ArgumentsRequired
|
15
15
|
from ccxt.base.errors import BadRequest
|
16
16
|
from ccxt.base.errors import RateLimitExceeded
|
17
|
-
from ccxt.base.errors import
|
17
|
+
from ccxt.base.errors import ChecksumError
|
18
18
|
from ccxt.base.precise import Precise
|
19
19
|
|
20
20
|
|
@@ -68,6 +68,9 @@ class bitget(ccxt.async_support.bitget):
|
|
68
68
|
'1d': '1D',
|
69
69
|
'1w': '1W',
|
70
70
|
},
|
71
|
+
'watchOrderBook': {
|
72
|
+
'checksum': True,
|
73
|
+
},
|
71
74
|
},
|
72
75
|
'streaming': {
|
73
76
|
'ping': self.ping,
|
@@ -539,9 +542,9 @@ class bitget(ccxt.async_support.bitget):
|
|
539
542
|
calculatedChecksum = self.crc32(payload, True)
|
540
543
|
responseChecksum = self.safe_integer(rawOrderBook, 'checksum')
|
541
544
|
if calculatedChecksum != responseChecksum:
|
542
|
-
error = InvalidNonce(self.id + ' invalid checksum')
|
543
545
|
del client.subscriptions[messageHash]
|
544
546
|
del self.orderbooks[symbol]
|
547
|
+
error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
545
548
|
client.reject(error, messageHash)
|
546
549
|
return
|
547
550
|
else:
|
ccxt/pro/bitvavo.py
CHANGED
@@ -476,7 +476,7 @@ class bitvavo(ccxt.async_support.bitvavo):
|
|
476
476
|
:param int [since]: the earliest time in ms to fetch trades for
|
477
477
|
:param int [limit]: the maximum number of trade structures to retrieve
|
478
478
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
479
|
-
:returns dict[]: a list of
|
479
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
480
480
|
"""
|
481
481
|
if symbol is None:
|
482
482
|
raise ArgumentsRequired(self.id + ' watchMyTrades() requires a symbol argument')
|
ccxt/pro/bybit.py
CHANGED
@@ -38,7 +38,7 @@ class bybit(ccxt.async_support.bybit):
|
|
38
38
|
'watchMyLiquidationsForSymbols': False,
|
39
39
|
'watchMyTrades': True,
|
40
40
|
'watchOHLCV': True,
|
41
|
-
'watchOHLCVForSymbols':
|
41
|
+
'watchOHLCVForSymbols': True,
|
42
42
|
'watchOrderBook': True,
|
43
43
|
'watchOrderBookForSymbols': True,
|
44
44
|
'watchOrders': True,
|
@@ -513,19 +513,42 @@ class bybit(ccxt.async_support.bybit):
|
|
513
513
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
514
514
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
515
515
|
"""
|
516
|
+
params['callerMethodName'] = 'watchOHLCV'
|
517
|
+
result = await self.watch_ohlcv_for_symbols([[symbol, timeframe]], since, limit, params)
|
518
|
+
return result[symbol][timeframe]
|
519
|
+
|
520
|
+
async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
|
521
|
+
"""
|
522
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
523
|
+
:see: https://bybit-exchange.github.io/docs/v5/websocket/public/kline
|
524
|
+
:see: https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
|
525
|
+
:param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
|
526
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
527
|
+
:param int [limit]: the maximum amount of candles to fetch
|
528
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
529
|
+
:returns dict: A list of candles ordered, open, high, low, close, volume
|
530
|
+
"""
|
516
531
|
await self.load_markets()
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
532
|
+
symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
|
533
|
+
marketSymbols = self.market_symbols(symbols, None, False, True, True)
|
534
|
+
firstSymbol = marketSymbols[0]
|
535
|
+
url = await self.get_url_by_market_type(firstSymbol, False, 'watchOHLCVForSymbols', params)
|
536
|
+
rawHashes = []
|
537
|
+
messageHashes = []
|
538
|
+
for i in range(0, len(symbolsAndTimeframes)):
|
539
|
+
data = symbolsAndTimeframes[i]
|
540
|
+
symbolString = self.safe_string(data, 0)
|
541
|
+
market = self.market(symbolString)
|
542
|
+
symbolString = market['symbol']
|
543
|
+
unfiedTimeframe = self.safe_string(data, 1)
|
544
|
+
timeframeId = self.safe_string(self.timeframes, unfiedTimeframe, unfiedTimeframe)
|
545
|
+
rawHashes.append('kline.' + timeframeId + '.' + market['id'])
|
546
|
+
messageHashes.append('ohlcv::' + symbolString + '::' + unfiedTimeframe)
|
547
|
+
symbol, timeframe, stored = await self.watch_topics(url, messageHashes, rawHashes, params)
|
526
548
|
if self.newUpdates:
|
527
|
-
limit =
|
528
|
-
|
549
|
+
limit = stored.getLimit(symbol, limit)
|
550
|
+
filtered = self.filter_by_since_limit(stored, since, limit, 0, True)
|
551
|
+
return self.create_ohlcv_object(symbol, timeframe, filtered)
|
529
552
|
|
530
553
|
def handle_ohlcv(self, client: Client, message):
|
531
554
|
#
|
@@ -564,16 +587,16 @@ class bybit(ccxt.async_support.bybit):
|
|
564
587
|
ohlcvsByTimeframe = self.safe_value(self.ohlcvs, symbol)
|
565
588
|
if ohlcvsByTimeframe is None:
|
566
589
|
self.ohlcvs[symbol] = {}
|
567
|
-
|
568
|
-
if stored is None:
|
590
|
+
if self.safe_value(ohlcvsByTimeframe, timeframe) is None:
|
569
591
|
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
570
|
-
|
571
|
-
|
592
|
+
self.ohlcvs[symbol][timeframe] = ArrayCacheByTimestamp(limit)
|
593
|
+
stored = self.ohlcvs[symbol][timeframe]
|
572
594
|
for i in range(0, len(data)):
|
573
595
|
parsed = self.parse_ws_ohlcv(data[i])
|
574
596
|
stored.append(parsed)
|
575
|
-
messageHash = '
|
576
|
-
|
597
|
+
messageHash = 'ohlcv::' + symbol + '::' + timeframe
|
598
|
+
resolveData = [symbol, timeframe, stored]
|
599
|
+
client.resolve(resolveData, messageHash)
|
577
600
|
|
578
601
|
def parse_ws_ohlcv(self, ohlcv, market=None) -> list:
|
579
602
|
#
|
ccxt/pro/cryptocom.py
CHANGED
@@ -11,7 +11,7 @@ from ccxt.async_support.base.ws.client import Client
|
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import AuthenticationError
|
13
13
|
from ccxt.base.errors import NetworkError
|
14
|
-
from ccxt.base.errors import
|
14
|
+
from ccxt.base.errors import ChecksumError
|
15
15
|
|
16
16
|
|
17
17
|
class cryptocom(ccxt.async_support.cryptocom):
|
@@ -52,6 +52,9 @@ class cryptocom(ccxt.async_support.cryptocom):
|
|
52
52
|
'fetchPositionsSnapshot': True, # or False
|
53
53
|
'awaitPositionsSnapshot': True, # whether to wait for the positions snapshot before providing updates
|
54
54
|
},
|
55
|
+
'watchOrderBook': {
|
56
|
+
'checksum': True,
|
57
|
+
},
|
55
58
|
},
|
56
59
|
'streaming': {
|
57
60
|
},
|
@@ -213,7 +216,9 @@ class cryptocom(ccxt.async_support.cryptocom):
|
|
213
216
|
previousNonce = self.safe_integer(data, 'pu')
|
214
217
|
currentNonce = orderbook['nonce']
|
215
218
|
if currentNonce != previousNonce:
|
216
|
-
|
219
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
220
|
+
if checksum:
|
221
|
+
raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
217
222
|
self.handle_deltas(orderbook['asks'], self.safe_value(books, 'asks', []))
|
218
223
|
self.handle_deltas(orderbook['bids'], self.safe_value(books, 'bids', []))
|
219
224
|
orderbook['nonce'] = nonce
|
ccxt/pro/gate.py
CHANGED
@@ -14,7 +14,7 @@ from ccxt.base.errors import AuthenticationError
|
|
14
14
|
from ccxt.base.errors import ArgumentsRequired
|
15
15
|
from ccxt.base.errors import BadRequest
|
16
16
|
from ccxt.base.errors import NotSupported
|
17
|
-
from ccxt.base.errors import
|
17
|
+
from ccxt.base.errors import ChecksumError
|
18
18
|
from ccxt.base.precise import Precise
|
19
19
|
|
20
20
|
|
@@ -105,6 +105,7 @@ class gate(ccxt.async_support.gate):
|
|
105
105
|
'interval': '100ms',
|
106
106
|
'snapshotDelay': 10, # how many deltas to cache before fetching a snapshot
|
107
107
|
'snapshotMaxRetries': 3,
|
108
|
+
'checksum': True,
|
108
109
|
},
|
109
110
|
'watchBalance': {
|
110
111
|
'settle': 'usdt', # or btc
|
@@ -460,10 +461,12 @@ class gate(ccxt.async_support.gate):
|
|
460
461
|
elif nonce >= deltaStart - 1:
|
461
462
|
self.handle_delta(storedOrderBook, delta)
|
462
463
|
else:
|
463
|
-
error = InvalidNonce(self.id + ' orderbook update has a nonce bigger than u')
|
464
464
|
del client.subscriptions[messageHash]
|
465
465
|
del self.orderbooks[symbol]
|
466
|
-
|
466
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
467
|
+
if checksum:
|
468
|
+
error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
469
|
+
client.reject(error, messageHash)
|
467
470
|
client.resolve(storedOrderBook, messageHash)
|
468
471
|
|
469
472
|
def get_cache_index(self, orderBook, cache):
|
ccxt/pro/htx.py
CHANGED
@@ -16,6 +16,7 @@ from ccxt.base.errors import BadRequest
|
|
16
16
|
from ccxt.base.errors import BadSymbol
|
17
17
|
from ccxt.base.errors import NetworkError
|
18
18
|
from ccxt.base.errors import InvalidNonce
|
19
|
+
from ccxt.base.errors import ChecksumError
|
19
20
|
|
20
21
|
|
21
22
|
class htx(ccxt.async_support.htx):
|
@@ -109,6 +110,7 @@ class htx(ccxt.async_support.htx):
|
|
109
110
|
'api': 'api', # or api-aws for clients hosted on AWS
|
110
111
|
'watchOrderBook': {
|
111
112
|
'maxRetries': 3,
|
113
|
+
'checksum': True,
|
112
114
|
},
|
113
115
|
'ws': {
|
114
116
|
'gunzip': True,
|
@@ -549,7 +551,9 @@ class htx(ccxt.async_support.htx):
|
|
549
551
|
orderbook.reset(snapshot)
|
550
552
|
orderbook['nonce'] = version
|
551
553
|
if (prevSeqNum is not None) and prevSeqNum > orderbook['nonce']:
|
552
|
-
|
554
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
555
|
+
if checksum:
|
556
|
+
raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
553
557
|
spotConditon = market['spot'] and (prevSeqNum == orderbook['nonce'])
|
554
558
|
nonSpotCondition = market['contract'] and (version - 1 == orderbook['nonce'])
|
555
559
|
if spotConditon or nonSpotCondition:
|
ccxt/pro/independentreserve.py
CHANGED
@@ -9,7 +9,7 @@ from ccxt.base.types import Int, OrderBook, Trade
|
|
9
9
|
from ccxt.async_support.base.ws.client import Client
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import NotSupported
|
12
|
-
from ccxt.base.errors import
|
12
|
+
from ccxt.base.errors import ChecksumError
|
13
13
|
|
14
14
|
|
15
15
|
class independentreserve(ccxt.async_support.independentreserve):
|
@@ -33,7 +33,9 @@ class independentreserve(ccxt.async_support.independentreserve):
|
|
33
33
|
},
|
34
34
|
},
|
35
35
|
'options': {
|
36
|
-
'
|
36
|
+
'watchOrderBook': {
|
37
|
+
'checksum': True, # TODO: currently only working for snapshot
|
38
|
+
},
|
37
39
|
},
|
38
40
|
'streaming': {
|
39
41
|
},
|
@@ -196,7 +198,7 @@ class independentreserve(ccxt.async_support.independentreserve):
|
|
196
198
|
self.handle_deltas(orderbook['bids'], bids)
|
197
199
|
orderbook['timestamp'] = timestamp
|
198
200
|
orderbook['datetime'] = self.iso8601(timestamp)
|
199
|
-
checksum = self.
|
201
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
200
202
|
if checksum and receivedSnapshot:
|
201
203
|
storedAsks = orderbook['asks']
|
202
204
|
storedBids = orderbook['bids']
|
@@ -212,7 +214,7 @@ class independentreserve(ccxt.async_support.independentreserve):
|
|
212
214
|
calculatedChecksum = self.crc32(payload, True)
|
213
215
|
responseChecksum = self.safe_integer(orderBook, 'Crc32')
|
214
216
|
if calculatedChecksum != responseChecksum:
|
215
|
-
error =
|
217
|
+
error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
216
218
|
del client.subscriptions[messageHash]
|
217
219
|
del self.orderbooks[symbol]
|
218
220
|
client.reject(error, messageHash)
|