ccxt 4.3.62__py2.py3-none-any.whl → 4.3.64__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/kucoin.py +1 -0
- ccxt/abstract/kucoinfutures.py +1 -0
- ccxt/abstract/woo.py +3 -0
- ccxt/ace.py +33 -15
- ccxt/alpaca.py +1 -0
- ccxt/async_support/__init__.py +2 -1
- ccxt/async_support/ace.py +33 -15
- ccxt/async_support/alpaca.py +1 -0
- ccxt/async_support/base/exchange.py +4 -4
- ccxt/async_support/binance.py +6 -9
- ccxt/async_support/bingx.py +534 -152
- ccxt/async_support/bitfinex.py +1 -1
- ccxt/async_support/bitfinex2.py +1 -1
- ccxt/async_support/coinbaseinternational.py +1 -1
- ccxt/async_support/cryptocom.py +17 -2
- ccxt/async_support/independentreserve.py +103 -1
- ccxt/async_support/kucoin.py +2 -0
- ccxt/async_support/mercado.py +5 -1
- ccxt/async_support/whitebit.py +1 -1
- ccxt/async_support/woo.py +321 -81
- ccxt/async_support/xt.py +3 -3
- ccxt/async_support/yobit.py +1 -1
- ccxt/async_support/zonda.py +1 -1
- ccxt/base/errors.py +8 -1
- ccxt/base/exchange.py +11 -5
- ccxt/binance.py +6 -9
- ccxt/bingx.py +534 -152
- ccxt/bitfinex.py +1 -1
- ccxt/bitfinex2.py +1 -1
- ccxt/coinbaseinternational.py +1 -1
- ccxt/cryptocom.py +17 -2
- ccxt/independentreserve.py +103 -1
- ccxt/kucoin.py +2 -0
- 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/bitmart.py +3 -3
- ccxt/pro/bitvavo.py +1 -1
- ccxt/pro/bybit.py +41 -18
- ccxt/pro/cryptocom.py +7 -2
- ccxt/pro/gate.py +7 -4
- ccxt/pro/gemini.py +4 -2
- ccxt/pro/htx.py +5 -1
- ccxt/pro/independentreserve.py +6 -4
- ccxt/pro/kraken.py +79 -6
- ccxt/pro/okx.py +5 -5
- ccxt/pro/onetrading.py +3 -2
- ccxt/pro/oxfun.py +1 -1
- ccxt/pro/poloniexfutures.py +5 -2
- ccxt/pro/vertex.py +3 -2
- ccxt/pro/woo.py +2 -1
- ccxt/pro/woofipro.py +3 -2
- ccxt/test/tests_async.py +3 -3
- ccxt/test/tests_helpers.py +1 -1
- ccxt/test/tests_init.py +3 -3
- ccxt/test/tests_sync.py +3 -3
- ccxt/whitebit.py +1 -1
- ccxt/woo.py +321 -81
- ccxt/xt.py +3 -3
- ccxt/yobit.py +1 -1
- ccxt/zonda.py +1 -1
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/METADATA +4 -4
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/RECORD +74 -74
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/WHEEL +0 -0
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/top_level.txt +0 -0
ccxt/bitfinex.py
CHANGED
@@ -1556,7 +1556,7 @@ class bitfinex(Exchange, ImplicitAPI):
|
|
1556
1556
|
# ]
|
1557
1557
|
#
|
1558
1558
|
response = self.safe_value(responses, 0, {})
|
1559
|
-
id = self.
|
1559
|
+
id = self.safe_integer(response, 'withdrawal_id')
|
1560
1560
|
message = self.safe_string(response, 'message')
|
1561
1561
|
errorMessage = self.find_broadly_matched_key(self.exceptions['broad'], message)
|
1562
1562
|
if id == 0:
|
ccxt/bitfinex2.py
CHANGED
@@ -2237,7 +2237,7 @@ class bitfinex2(Exchange, ImplicitAPI):
|
|
2237
2237
|
if feeCost is not None:
|
2238
2238
|
feeCost = Precise.string_abs(feeCost)
|
2239
2239
|
amount = self.safe_number(data, 5)
|
2240
|
-
id = self.
|
2240
|
+
id = self.safe_integer(data, 0)
|
2241
2241
|
status = 'ok'
|
2242
2242
|
if id == 0:
|
2243
2243
|
id = None
|
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/independentreserve.py
CHANGED
@@ -6,8 +6,9 @@
|
|
6
6
|
from ccxt.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.independentreserve import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, TradingFees
|
9
|
+
from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, TradingFees, Transaction
|
10
10
|
from typing import List
|
11
|
+
from ccxt.base.errors import BadRequest
|
11
12
|
from ccxt.base.decimal_to_precision import TICK_SIZE
|
12
13
|
from ccxt.base.precise import Precise
|
13
14
|
|
@@ -79,6 +80,7 @@ class independentreserve(Exchange, ImplicitAPI):
|
|
79
80
|
'setLeverage': False,
|
80
81
|
'setMarginMode': False,
|
81
82
|
'setPositionMode': False,
|
83
|
+
'withdraw': True,
|
82
84
|
},
|
83
85
|
'urls': {
|
84
86
|
'logo': 'https://user-images.githubusercontent.com/51840849/87182090-1e9e9080-c2ec-11ea-8e49-563db9a38f37.jpg',
|
@@ -752,6 +754,106 @@ class independentreserve(Exchange, ImplicitAPI):
|
|
752
754
|
'network': None,
|
753
755
|
}
|
754
756
|
|
757
|
+
def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
|
758
|
+
"""
|
759
|
+
make a withdrawal
|
760
|
+
:see: https://www.independentreserve.com/features/api#WithdrawDigitalCurrency
|
761
|
+
:param str code: unified currency code
|
762
|
+
:param float amount: the amount to withdraw
|
763
|
+
:param str address: the address to withdraw to
|
764
|
+
:param str tag:
|
765
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
766
|
+
*
|
767
|
+
* EXCHANGE SPECIFIC PARAMETERS
|
768
|
+
:param dict [params.comment]: withdrawal comment, should not exceed 500 characters
|
769
|
+
:returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
|
770
|
+
"""
|
771
|
+
tag, params = self.handle_withdraw_tag_and_params(tag, params)
|
772
|
+
self.load_markets()
|
773
|
+
currency = self.currency(code)
|
774
|
+
request: dict = {
|
775
|
+
'primaryCurrencyCode': currency['id'],
|
776
|
+
'withdrawalAddress': address,
|
777
|
+
'amount': self.currency_to_precision(code, amount),
|
778
|
+
}
|
779
|
+
if tag is not None:
|
780
|
+
request['destinationTag'] = tag
|
781
|
+
networkCode = None
|
782
|
+
networkCode, params = self.handle_network_code_and_params(params)
|
783
|
+
if networkCode is not None:
|
784
|
+
raise BadRequest(self.id + ' withdraw() does not accept params["networkCode"]')
|
785
|
+
response = self.privatePostWithdrawDigitalCurrency(self.extend(request, params))
|
786
|
+
#
|
787
|
+
# {
|
788
|
+
# "TransactionGuid": "dc932e19-562b-4c50-821e-a73fd048b93b",
|
789
|
+
# "PrimaryCurrencyCode": "Bch",
|
790
|
+
# "CreatedTimestampUtc": "2020-04-01T05:26:30.5093622+00:00",
|
791
|
+
# "Amount": {
|
792
|
+
# "Total": 0.1231,
|
793
|
+
# "Fee": 0.0001
|
794
|
+
# },
|
795
|
+
# "Destination": {
|
796
|
+
# "Address": "bc1qhpqxkjpvgkckw530yfmxyr53c94q8f4273a7ez",
|
797
|
+
# "Tag": null
|
798
|
+
# },
|
799
|
+
# "Status": "Pending",
|
800
|
+
# "Transaction": null
|
801
|
+
# }
|
802
|
+
#
|
803
|
+
return self.parse_transaction(response, currency)
|
804
|
+
|
805
|
+
def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
|
806
|
+
#
|
807
|
+
# {
|
808
|
+
# "TransactionGuid": "dc932e19-562b-4c50-821e-a73fd048b93b",
|
809
|
+
# "PrimaryCurrencyCode": "Bch",
|
810
|
+
# "CreatedTimestampUtc": "2020-04-01T05:26:30.5093622+00:00",
|
811
|
+
# "Amount": {
|
812
|
+
# "Total": 0.1231,
|
813
|
+
# "Fee": 0.0001
|
814
|
+
# },
|
815
|
+
# "Destination": {
|
816
|
+
# "Address": "bc1qhpqxkjpvgkckw530yfmxyr53c94q8f4273a7ez",
|
817
|
+
# "Tag": null
|
818
|
+
# },
|
819
|
+
# "Status": "Pending",
|
820
|
+
# "Transaction": null
|
821
|
+
# }
|
822
|
+
#
|
823
|
+
amount = self.safe_dict(transaction, 'Amount')
|
824
|
+
destination = self.safe_dict(transaction, 'Destination')
|
825
|
+
currencyId = self.safe_string(transaction, 'PrimaryCurrencyCode')
|
826
|
+
datetime = self.safe_string(transaction, 'CreatedTimestampUtc')
|
827
|
+
address = self.safe_string(destination, 'Address')
|
828
|
+
tag = self.safe_string(destination, 'Tag')
|
829
|
+
code = self.safe_currency_code(currencyId, currency)
|
830
|
+
return {
|
831
|
+
'info': transaction,
|
832
|
+
'id': self.safe_string(transaction, 'TransactionGuid'),
|
833
|
+
'txid': None,
|
834
|
+
'type': 'withdraw',
|
835
|
+
'currency': code,
|
836
|
+
'network': None,
|
837
|
+
'amount': self.safe_number(amount, 'Total'),
|
838
|
+
'status': self.safe_string(transaction, 'Status'),
|
839
|
+
'timestamp': self.parse8601(datetime),
|
840
|
+
'datetime': datetime,
|
841
|
+
'address': address,
|
842
|
+
'addressFrom': None,
|
843
|
+
'addressTo': address,
|
844
|
+
'tag': tag,
|
845
|
+
'tagFrom': None,
|
846
|
+
'tagTo': tag,
|
847
|
+
'updated': None,
|
848
|
+
'comment': None,
|
849
|
+
'fee': {
|
850
|
+
'currency': code,
|
851
|
+
'cost': self.safe_number(amount, 'Fee'),
|
852
|
+
'rate': None,
|
853
|
+
},
|
854
|
+
'internal': False,
|
855
|
+
}
|
856
|
+
|
755
857
|
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
|
756
858
|
url = self.urls['api'][api] + '/' + path
|
757
859
|
if api == 'public':
|
ccxt/kucoin.py
CHANGED
@@ -178,6 +178,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
178
178
|
'status': 4.5, # 3PW
|
179
179
|
# margin trading
|
180
180
|
'mark-price/{symbol}/current': 3, # 2PW
|
181
|
+
'mark-price/all-symbols': 3,
|
181
182
|
'margin/config': 25, # 25SW
|
182
183
|
},
|
183
184
|
'post': {
|
@@ -663,6 +664,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
663
664
|
'currencies': 'v3',
|
664
665
|
'currencies/{currency}': 'v3',
|
665
666
|
'symbols': 'v2',
|
667
|
+
'mark-price/all-symbols': 'v3',
|
666
668
|
},
|
667
669
|
},
|
668
670
|
'private': {
|
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/bitmart.py
CHANGED
@@ -707,8 +707,8 @@ class bitmart(ccxt.async_support.bitmart):
|
|
707
707
|
symbol = market['symbol']
|
708
708
|
openTimestamp = self.safe_integer(position, 'create_time')
|
709
709
|
timestamp = self.safe_integer(position, 'update_time')
|
710
|
-
side = self.
|
711
|
-
marginModeId = self.
|
710
|
+
side = self.safe_integer(position, 'position_type')
|
711
|
+
marginModeId = self.safe_integer(position, 'open_type')
|
712
712
|
return self.safe_position({
|
713
713
|
'info': position,
|
714
714
|
'id': None,
|
@@ -1234,7 +1234,7 @@ class bitmart(ccxt.async_support.bitmart):
|
|
1234
1234
|
ob['symbol'] = symbol
|
1235
1235
|
self.orderbooks[symbol] = ob
|
1236
1236
|
orderbook = self.orderbooks[symbol]
|
1237
|
-
way = self.
|
1237
|
+
way = self.safe_integer(data, 'way')
|
1238
1238
|
side = 'bids' if (way == 1) else 'asks'
|
1239
1239
|
if way == 1:
|
1240
1240
|
orderbook[side] = Bids([], limit)
|
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
|