ccxt 4.3.32__py2.py3-none-any.whl → 4.3.34__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 +1 -0
- ccxt/abstract/binancecoinm.py +1 -0
- ccxt/abstract/binanceus.py +1 -0
- ccxt/abstract/binanceusdm.py +1 -0
- ccxt/abstract/bitget.py +1 -1
- ccxt/ace.py +2 -2
- ccxt/alpaca.py +1 -1
- ccxt/ascendex.py +2 -2
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/ace.py +2 -2
- ccxt/async_support/alpaca.py +1 -1
- ccxt/async_support/ascendex.py +2 -2
- ccxt/async_support/base/exchange.py +17 -1
- ccxt/async_support/bigone.py +2 -2
- ccxt/async_support/binance.py +4 -3
- ccxt/async_support/bingx.py +2 -2
- ccxt/async_support/bit2c.py +1 -1
- ccxt/async_support/bitbank.py +1 -1
- ccxt/async_support/bitbns.py +1 -1
- ccxt/async_support/bitfinex.py +2 -2
- ccxt/async_support/bitfinex2.py +1 -1
- ccxt/async_support/bitflyer.py +1 -1
- ccxt/async_support/bitget.py +4 -4
- ccxt/async_support/bithumb.py +1 -1
- ccxt/async_support/bitmart.py +2 -2
- ccxt/async_support/bitmex.py +3 -3
- ccxt/async_support/bitopro.py +3 -3
- ccxt/async_support/bitrue.py +2 -2
- ccxt/async_support/bitso.py +2 -2
- ccxt/async_support/bitstamp.py +2 -2
- ccxt/async_support/bitteam.py +3 -3
- ccxt/async_support/bitvavo.py +2 -2
- ccxt/async_support/blockchaincom.py +1 -1
- ccxt/async_support/blofin.py +3 -3
- ccxt/async_support/btcalpha.py +3 -3
- ccxt/async_support/btcbox.py +1 -1
- ccxt/async_support/btcmarkets.py +3 -3
- ccxt/async_support/btcturk.py +1 -1
- ccxt/async_support/bybit.py +2 -2
- ccxt/async_support/cex.py +1 -1
- ccxt/async_support/coinbase.py +96 -55
- ccxt/async_support/coinbaseexchange.py +1 -1
- ccxt/async_support/coinbaseinternational.py +3 -3
- ccxt/async_support/coincheck.py +2 -2
- ccxt/async_support/coinex.py +2 -2
- ccxt/async_support/coinlist.py +2 -2
- ccxt/async_support/coinmate.py +2 -2
- ccxt/async_support/coinmetro.py +2 -2
- ccxt/async_support/coinone.py +1 -1
- ccxt/async_support/coinsph.py +2 -2
- ccxt/async_support/cryptocom.py +1 -1
- ccxt/async_support/currencycom.py +2 -2
- ccxt/async_support/delta.py +1 -1
- ccxt/async_support/deribit.py +2 -2
- ccxt/async_support/digifinex.py +2 -2
- ccxt/async_support/exmo.py +2 -2
- ccxt/async_support/gate.py +2 -2
- ccxt/async_support/gemini.py +2 -2
- ccxt/async_support/hitbtc.py +2 -2
- ccxt/async_support/hollaex.py +1 -1
- ccxt/async_support/htx.py +2 -2
- ccxt/async_support/huobijp.py +2 -2
- ccxt/async_support/hyperliquid.py +2 -2
- ccxt/async_support/idex.py +2 -2
- ccxt/async_support/indodax.py +2 -2
- ccxt/async_support/kraken.py +2 -2
- ccxt/async_support/krakenfutures.py +1 -1
- ccxt/async_support/kucoin.py +2 -2
- ccxt/async_support/kuna.py +2 -2
- ccxt/async_support/latoken.py +2 -2
- ccxt/async_support/lbank.py +1 -1
- ccxt/async_support/luno.py +1 -1
- ccxt/async_support/lykke.py +1 -1
- ccxt/async_support/mercado.py +1 -1
- ccxt/async_support/mexc.py +1 -1
- ccxt/async_support/ndax.py +2 -2
- ccxt/async_support/novadax.py +3 -3
- ccxt/async_support/oceanex.py +2 -2
- ccxt/async_support/okcoin.py +3 -3
- ccxt/async_support/okx.py +3 -3
- ccxt/async_support/onetrading.py +2 -2
- ccxt/async_support/p2b.py +2 -2
- ccxt/async_support/paymium.py +1 -1
- ccxt/async_support/phemex.py +4 -4
- ccxt/async_support/poloniex.py +3 -3
- ccxt/async_support/poloniexfutures.py +2 -2
- ccxt/async_support/probit.py +3 -3
- ccxt/async_support/timex.py +2 -2
- ccxt/async_support/tokocrypto.py +1 -1
- ccxt/async_support/tradeogre.py +1 -1
- ccxt/async_support/upbit.py +3 -3
- ccxt/async_support/wavesexchange.py +1 -1
- ccxt/async_support/wazirx.py +3 -3
- ccxt/async_support/whitebit.py +3 -3
- ccxt/async_support/woo.py +3 -3
- ccxt/async_support/woofipro.py +3 -3
- ccxt/async_support/yobit.py +1 -1
- ccxt/async_support/zaif.py +2 -2
- ccxt/async_support/zonda.py +1 -1
- ccxt/base/exchange.py +25 -3
- ccxt/base/types.py +0 -1
- ccxt/bigone.py +2 -2
- ccxt/binance.py +4 -3
- ccxt/bingx.py +2 -2
- ccxt/bit2c.py +1 -1
- ccxt/bitbank.py +1 -1
- ccxt/bitbns.py +1 -1
- ccxt/bitfinex.py +2 -2
- ccxt/bitfinex2.py +1 -1
- ccxt/bitflyer.py +1 -1
- ccxt/bitget.py +4 -4
- ccxt/bithumb.py +1 -1
- ccxt/bitmart.py +2 -2
- ccxt/bitmex.py +3 -3
- ccxt/bitopro.py +3 -3
- ccxt/bitrue.py +2 -2
- ccxt/bitso.py +2 -2
- ccxt/bitstamp.py +2 -2
- ccxt/bitteam.py +3 -3
- ccxt/bitvavo.py +2 -2
- ccxt/blockchaincom.py +1 -1
- ccxt/blofin.py +3 -3
- ccxt/btcalpha.py +3 -3
- ccxt/btcbox.py +1 -1
- ccxt/btcmarkets.py +3 -3
- ccxt/btcturk.py +1 -1
- ccxt/bybit.py +2 -2
- ccxt/cex.py +1 -1
- ccxt/coinbase.py +96 -55
- ccxt/coinbaseexchange.py +1 -1
- ccxt/coinbaseinternational.py +3 -3
- ccxt/coincheck.py +2 -2
- ccxt/coinex.py +2 -2
- ccxt/coinlist.py +2 -2
- ccxt/coinmate.py +2 -2
- ccxt/coinmetro.py +2 -2
- ccxt/coinone.py +1 -1
- ccxt/coinsph.py +2 -2
- ccxt/cryptocom.py +1 -1
- ccxt/currencycom.py +2 -2
- ccxt/delta.py +1 -1
- ccxt/deribit.py +2 -2
- ccxt/digifinex.py +2 -2
- ccxt/exmo.py +2 -2
- ccxt/gate.py +2 -2
- ccxt/gemini.py +2 -2
- ccxt/hitbtc.py +2 -2
- ccxt/hollaex.py +1 -1
- ccxt/htx.py +2 -2
- ccxt/huobijp.py +2 -2
- ccxt/hyperliquid.py +2 -2
- ccxt/idex.py +2 -2
- ccxt/indodax.py +2 -2
- ccxt/kraken.py +2 -2
- ccxt/krakenfutures.py +1 -1
- ccxt/kucoin.py +2 -2
- ccxt/kuna.py +2 -2
- ccxt/latoken.py +2 -2
- ccxt/lbank.py +1 -1
- ccxt/luno.py +1 -1
- ccxt/lykke.py +1 -1
- ccxt/mercado.py +1 -1
- ccxt/mexc.py +1 -1
- ccxt/ndax.py +2 -2
- ccxt/novadax.py +3 -3
- ccxt/oceanex.py +2 -2
- ccxt/okcoin.py +3 -3
- ccxt/okx.py +3 -3
- ccxt/onetrading.py +2 -2
- ccxt/p2b.py +2 -2
- ccxt/paymium.py +1 -1
- ccxt/phemex.py +4 -4
- ccxt/poloniex.py +3 -3
- ccxt/poloniexfutures.py +2 -2
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +331 -2
- ccxt/pro/bitmex.py +98 -1
- ccxt/pro/bybit.py +82 -1
- ccxt/pro/gate.py +173 -1
- ccxt/pro/kucoinfutures.py +4 -0
- ccxt/pro/okx.py +245 -2
- ccxt/probit.py +3 -3
- ccxt/test/base/__init__.py +1 -0
- ccxt/test/base/test_liquidation.py +50 -0
- ccxt/timex.py +2 -2
- ccxt/tokocrypto.py +1 -1
- ccxt/tradeogre.py +1 -1
- ccxt/upbit.py +3 -3
- ccxt/wavesexchange.py +1 -1
- ccxt/wazirx.py +3 -3
- ccxt/whitebit.py +3 -3
- ccxt/woo.py +3 -3
- ccxt/woofipro.py +3 -3
- ccxt/yobit.py +1 -1
- ccxt/zaif.py +2 -2
- ccxt/zonda.py +1 -1
- {ccxt-4.3.32.dist-info → ccxt-4.3.34.dist-info}/METADATA +4 -4
- {ccxt-4.3.32.dist-info → ccxt-4.3.34.dist-info}/RECORD +201 -200
- {ccxt-4.3.32.dist-info → ccxt-4.3.34.dist-info}/WHEEL +0 -0
- {ccxt-4.3.32.dist-info → ccxt-4.3.34.dist-info}/top_level.txt +0 -0
ccxt/pro/binance.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, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Liquidation, Num, Order, OrderBook, OrderSide, OrderType, 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 ArgumentsRequired
|
@@ -23,6 +23,10 @@ class binance(ccxt.async_support.binance):
|
|
23
23
|
'has': {
|
24
24
|
'ws': True,
|
25
25
|
'watchBalance': True,
|
26
|
+
'watchLiquidations': True,
|
27
|
+
'watchLiquidationsForSymbols': True,
|
28
|
+
'watchMyLiquidations': True,
|
29
|
+
'watchMyLiquidationsForSymbols': True,
|
26
30
|
'watchBidsAsks': True,
|
27
31
|
'watchMyTrades': True,
|
28
32
|
'watchOHLCV': True,
|
@@ -107,6 +111,8 @@ class binance(ccxt.async_support.binance):
|
|
107
111
|
# get updates every 1000ms or 100ms
|
108
112
|
# or every 0ms in real-time for futures
|
109
113
|
'watchOrderBookRate': 100,
|
114
|
+
'liquidationsLimit': 1000,
|
115
|
+
'myLiquidationsLimit': 1000,
|
110
116
|
'tradesLimit': 1000,
|
111
117
|
'ordersLimit': 1000,
|
112
118
|
'OHLCVLimit': 1000,
|
@@ -131,6 +137,9 @@ class binance(ccxt.async_support.binance):
|
|
131
137
|
'fetchBalanceSnapshot': False, # or True
|
132
138
|
'awaitBalanceSnapshot': True, # whether to wait for the balance snapshot before providing updates
|
133
139
|
},
|
140
|
+
'watchLiquidationsForSymbols': {
|
141
|
+
'defaultType': 'swap',
|
142
|
+
},
|
134
143
|
'watchPositions': {
|
135
144
|
'fetchPositionsSnapshot': True, # or False
|
136
145
|
'awaitPositionsSnapshot': True, # whether to wait for the positions snapshot before providing updates
|
@@ -159,7 +168,7 @@ class binance(ccxt.async_support.binance):
|
|
159
168
|
self.options['requestId'][url] = newValue
|
160
169
|
return newValue
|
161
170
|
|
162
|
-
def stream(self, type, subscriptionHash, numSubscriptions=1):
|
171
|
+
def stream(self, type: Str, subscriptionHash: Str, numSubscriptions=1):
|
163
172
|
streamBySubscriptionsHash = self.safe_dict(self.options, 'streamBySubscriptionsHash', self.create_safe_dictionary())
|
164
173
|
stream = self.safe_string(streamBySubscriptionsHash, subscriptionHash)
|
165
174
|
if stream is None:
|
@@ -182,6 +191,324 @@ class binance(ccxt.async_support.binance):
|
|
182
191
|
self.options['numSubscriptionsByStream'][stream] = subscriptionsByStream + numSubscriptions
|
183
192
|
return stream
|
184
193
|
|
194
|
+
async def watch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
195
|
+
"""
|
196
|
+
watch the public liquidations of a trading pair
|
197
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#liquidation-order-streams
|
198
|
+
:see: https://binance-docs.github.io/apidocs/delivery/en/#liquidation-order-streams
|
199
|
+
:param str symbol: unified CCXT market symbol
|
200
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
201
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
202
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
203
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
204
|
+
"""
|
205
|
+
return self.watch_liquidations_for_symbols([symbol], since, limit, params)
|
206
|
+
|
207
|
+
async def watch_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
208
|
+
"""
|
209
|
+
watch the public liquidations of a trading pair
|
210
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#all-market-liquidation-order-streams
|
211
|
+
:see: https://binance-docs.github.io/apidocs/delivery/en/#all-market-liquidation-order-streams
|
212
|
+
:param str symbol: unified CCXT market symbol
|
213
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
214
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
215
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
216
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
217
|
+
"""
|
218
|
+
await self.load_markets()
|
219
|
+
subscriptionHashes = []
|
220
|
+
messageHashes = []
|
221
|
+
streamHash = 'liquidations'
|
222
|
+
symbols = self.market_symbols(symbols, None, True, True)
|
223
|
+
if self.is_empty(symbols):
|
224
|
+
subscriptionHashes.append('!' + 'forceOrder@arr')
|
225
|
+
messageHashes.append('liquidations')
|
226
|
+
else:
|
227
|
+
for i in range(0, len(symbols)):
|
228
|
+
market = self.market(symbols[i])
|
229
|
+
subscriptionHashes.append(market['id'] + '@forceOrder')
|
230
|
+
messageHashes.append('liquidations::' + symbols[i])
|
231
|
+
streamHash += '::' + ','.join(symbols)
|
232
|
+
firstMarket = self.get_market_from_symbols(symbols)
|
233
|
+
type = None
|
234
|
+
type, params = self.handle_market_type_and_params('watchLiquidationsForSymbols', firstMarket, params)
|
235
|
+
if type == 'spot':
|
236
|
+
raise BadRequest(self.id + 'watchLiquidationsForSymbols is not supported for swap symbols')
|
237
|
+
subType = None
|
238
|
+
subType, params = self.handle_sub_type_and_params('watchLiquidationsForSymbols', firstMarket, params)
|
239
|
+
if self.isLinear(type, subType):
|
240
|
+
type = 'future'
|
241
|
+
elif self.isInverse(type, subType):
|
242
|
+
type = 'delivery'
|
243
|
+
numSubscriptions = len(subscriptionHashes)
|
244
|
+
url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, numSubscriptions)
|
245
|
+
requestId = self.request_id(url)
|
246
|
+
request = {
|
247
|
+
'method': 'SUBSCRIBE',
|
248
|
+
'params': subscriptionHashes,
|
249
|
+
'id': requestId,
|
250
|
+
}
|
251
|
+
subscribe = {
|
252
|
+
'id': requestId,
|
253
|
+
}
|
254
|
+
newLiquidations = await self.watch_multiple(url, messageHashes, self.extend(request, params), subscriptionHashes, subscribe)
|
255
|
+
if self.newUpdates:
|
256
|
+
return newLiquidations
|
257
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
|
258
|
+
|
259
|
+
def handle_liquidation(self, client: Client, message):
|
260
|
+
#
|
261
|
+
# future
|
262
|
+
# {
|
263
|
+
# "e":"forceOrder",
|
264
|
+
# "E":1698871323061,
|
265
|
+
# "o":{
|
266
|
+
# "s":"BTCUSDT",
|
267
|
+
# "S":"BUY",
|
268
|
+
# "o":"LIMIT",
|
269
|
+
# "f":"IOC",
|
270
|
+
# "q":"1.437",
|
271
|
+
# "p":"35100.81",
|
272
|
+
# "ap":"34959.70",
|
273
|
+
# "X":"FILLED",
|
274
|
+
# "l":"1.437",
|
275
|
+
# "z":"1.437",
|
276
|
+
# "T":1698871323059
|
277
|
+
# }
|
278
|
+
# }
|
279
|
+
# delivery
|
280
|
+
# {
|
281
|
+
# "e":"forceOrder", # Event Type
|
282
|
+
# "E": 1591154240950, # Event Time
|
283
|
+
# "o":{
|
284
|
+
# "s":"BTCUSD_200925", # Symbol
|
285
|
+
# "ps": "BTCUSD", # Pair
|
286
|
+
# "S":"SELL", # Side
|
287
|
+
# "o":"LIMIT", # Order Type
|
288
|
+
# "f":"IOC", # Time in Force
|
289
|
+
# "q":"1", # Original Quantity
|
290
|
+
# "p":"9425.5", # Price
|
291
|
+
# "ap":"9496.5", # Average Price
|
292
|
+
# "X":"FILLED", # Order Status
|
293
|
+
# "l":"1", # Order Last Filled Quantity
|
294
|
+
# "z":"1", # Order Filled Accumulated Quantity
|
295
|
+
# "T": 1591154240949, # Order Trade Time
|
296
|
+
# }
|
297
|
+
# }
|
298
|
+
#
|
299
|
+
rawLiquidation = self.safe_value(message, 'o', {})
|
300
|
+
marketId = self.safe_string(rawLiquidation, 's')
|
301
|
+
market = self.safe_market(marketId, None, '', 'contract')
|
302
|
+
symbol = market['symbol']
|
303
|
+
liquidation = self.parse_ws_liquidation(rawLiquidation, market)
|
304
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
305
|
+
if liquidations is None:
|
306
|
+
limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
|
307
|
+
liquidations = ArrayCache(limit)
|
308
|
+
liquidations.append(liquidation)
|
309
|
+
self.liquidations[symbol] = liquidations
|
310
|
+
client.resolve([liquidation], 'liquidations')
|
311
|
+
client.resolve([liquidation], 'liquidations::' + symbol)
|
312
|
+
|
313
|
+
def parse_ws_liquidation(self, liquidation, market=None):
|
314
|
+
#
|
315
|
+
# future
|
316
|
+
# {
|
317
|
+
# "s":"BTCUSDT",
|
318
|
+
# "S":"BUY",
|
319
|
+
# "o":"LIMIT",
|
320
|
+
# "f":"IOC",
|
321
|
+
# "q":"1.437",
|
322
|
+
# "p":"35100.81",
|
323
|
+
# "ap":"34959.70",
|
324
|
+
# "X":"FILLED",
|
325
|
+
# "l":"1.437",
|
326
|
+
# "z":"1.437",
|
327
|
+
# "T":1698871323059
|
328
|
+
# }
|
329
|
+
# delivery
|
330
|
+
# {
|
331
|
+
# "s":"BTCUSD_200925", # Symbol
|
332
|
+
# "ps": "BTCUSD", # Pair
|
333
|
+
# "S":"SELL", # Side
|
334
|
+
# "o":"LIMIT", # Order Type
|
335
|
+
# "f":"IOC", # Time in Force
|
336
|
+
# "q":"1", # Original Quantity
|
337
|
+
# "p":"9425.5", # Price
|
338
|
+
# "ap":"9496.5", # Average Price
|
339
|
+
# "X":"FILLED", # Order Status
|
340
|
+
# "l":"1", # Order Last Filled Quantity
|
341
|
+
# "z":"1", # Order Filled Accumulated Quantity
|
342
|
+
# "T": 1591154240949, # Order Trade Time
|
343
|
+
# }
|
344
|
+
# myLiquidation
|
345
|
+
# {
|
346
|
+
# "s":"BTCUSDT", # Symbol
|
347
|
+
# "c":"TEST", # Client Order Id
|
348
|
+
# # special client order id:
|
349
|
+
# # starts with "autoclose-": liquidation order
|
350
|
+
# # "adl_autoclose": ADL auto close order
|
351
|
+
# # "settlement_autoclose-": settlement order for delisting or delivery
|
352
|
+
# "S":"SELL", # Side
|
353
|
+
# "o":"TRAILING_STOP_MARKET", # Order Type
|
354
|
+
# "f":"GTC", # Time in Force
|
355
|
+
# "q":"0.001", # Original Quantity
|
356
|
+
# "p":"0", # Original Price
|
357
|
+
# "ap":"0", # Average Price
|
358
|
+
# "sp":"7103.04", # Stop Price. Please ignore with TRAILING_STOP_MARKET order
|
359
|
+
# "x":"NEW", # Execution Type
|
360
|
+
# "X":"NEW", # Order Status
|
361
|
+
# "i":8886774, # Order Id
|
362
|
+
# "l":"0", # Order Last Filled Quantity
|
363
|
+
# "z":"0", # Order Filled Accumulated Quantity
|
364
|
+
# "L":"0", # Last Filled Price
|
365
|
+
# "N":"USDT", # Commission Asset, will not push if no commission
|
366
|
+
# "n":"0", # Commission, will not push if no commission
|
367
|
+
# "T":1568879465650, # Order Trade Time
|
368
|
+
# "t":0, # Trade Id
|
369
|
+
# "b":"0", # Bids Notional
|
370
|
+
# "a":"9.91", # Ask Notional
|
371
|
+
# "m":false, # Is self trade the maker side?
|
372
|
+
# "R":false, # Is self reduce only
|
373
|
+
# "wt":"CONTRACT_PRICE", # Stop Price Working Type
|
374
|
+
# "ot":"TRAILING_STOP_MARKET",// Original Order Type
|
375
|
+
# "ps":"LONG", # Position Side
|
376
|
+
# "cp":false, # If Close-All, pushed with conditional order
|
377
|
+
# "AP":"7476.89", # Activation Price, only puhed with TRAILING_STOP_MARKET order
|
378
|
+
# "cr":"5.0", # Callback Rate, only puhed with TRAILING_STOP_MARKET order
|
379
|
+
# "pP": False, # If price protection is turned on
|
380
|
+
# "si": 0, # ignore
|
381
|
+
# "ss": 0, # ignore
|
382
|
+
# "rp":"0", # Realized Profit of the trade
|
383
|
+
# "V":"EXPIRE_TAKER", # STP mode
|
384
|
+
# "pm":"OPPONENT", # Price match mode
|
385
|
+
# "gtd":0 # TIF GTD order auto cancel time
|
386
|
+
# }
|
387
|
+
#
|
388
|
+
marketId = self.safe_string(liquidation, 's')
|
389
|
+
market = self.safe_market(marketId, market)
|
390
|
+
timestamp = self.safe_integer(liquidation, 'T')
|
391
|
+
return self.safe_liquidation({
|
392
|
+
'info': liquidation,
|
393
|
+
'symbol': self.safe_symbol(marketId, market),
|
394
|
+
'contracts': self.safe_number(liquidation, 'l'),
|
395
|
+
'contractSize': self.safe_number(market, 'contractSize'),
|
396
|
+
'price': self.safe_number(liquidation, 'ap'),
|
397
|
+
'baseValue': None,
|
398
|
+
'quoteValue': None,
|
399
|
+
'timestamp': timestamp,
|
400
|
+
'datetime': self.iso8601(timestamp),
|
401
|
+
})
|
402
|
+
|
403
|
+
async def watch_my_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
404
|
+
"""
|
405
|
+
watch the private liquidations of a trading pair
|
406
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#event-order-update
|
407
|
+
:see: https://binance-docs.github.io/apidocs/delivery/en/#event-order-update
|
408
|
+
:param str symbol: unified CCXT market symbol
|
409
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
410
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
411
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
412
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
413
|
+
"""
|
414
|
+
return self.watch_my_liquidations_for_symbols([symbol], since, limit, params)
|
415
|
+
|
416
|
+
async def watch_my_liquidations_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
417
|
+
"""
|
418
|
+
watch the private liquidations of a trading pair
|
419
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#event-order-update
|
420
|
+
:see: https://binance-docs.github.io/apidocs/delivery/en/#event-order-update
|
421
|
+
:param str symbol: unified CCXT market symbol
|
422
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
423
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
424
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
425
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
426
|
+
"""
|
427
|
+
await self.load_markets()
|
428
|
+
symbols = self.market_symbols(symbols, None, True, True, True)
|
429
|
+
market = self.get_market_from_symbols(symbols)
|
430
|
+
messageHashes = ['myLiquidations']
|
431
|
+
if not self.is_empty(symbols):
|
432
|
+
for i in range(0, len(symbols)):
|
433
|
+
symbol = symbols[i]
|
434
|
+
messageHashes.append('myLiquidations::' + symbol)
|
435
|
+
type = None
|
436
|
+
type, params = self.handle_market_type_and_params('watchMyLiquidationsForSymbols', market, params)
|
437
|
+
subType = None
|
438
|
+
subType, params = self.handle_sub_type_and_params('watchMyLiquidationsForSymbols', market, params)
|
439
|
+
if self.isLinear(type, subType):
|
440
|
+
type = 'future'
|
441
|
+
elif self.isInverse(type, subType):
|
442
|
+
type = 'delivery'
|
443
|
+
await self.authenticate(params)
|
444
|
+
url = self.urls['api']['ws'][type] + '/' + self.options[type]['listenKey']
|
445
|
+
message = None
|
446
|
+
newLiquidations = await self.watch_multiple(url, messageHashes, message, [type])
|
447
|
+
if self.newUpdates:
|
448
|
+
return newLiquidations
|
449
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit)
|
450
|
+
|
451
|
+
def handle_my_liquidation(self, client: Client, message):
|
452
|
+
#
|
453
|
+
# {
|
454
|
+
# "s":"BTCUSDT", # Symbol
|
455
|
+
# "c":"TEST", # Client Order Id
|
456
|
+
# # special client order id:
|
457
|
+
# # starts with "autoclose-": liquidation order
|
458
|
+
# # "adl_autoclose": ADL auto close order
|
459
|
+
# # "settlement_autoclose-": settlement order for delisting or delivery
|
460
|
+
# "S":"SELL", # Side
|
461
|
+
# "o":"TRAILING_STOP_MARKET", # Order Type
|
462
|
+
# "f":"GTC", # Time in Force
|
463
|
+
# "q":"0.001", # Original Quantity
|
464
|
+
# "p":"0", # Original Price
|
465
|
+
# "ap":"0", # Average Price
|
466
|
+
# "sp":"7103.04", # Stop Price. Please ignore with TRAILING_STOP_MARKET order
|
467
|
+
# "x":"NEW", # Execution Type
|
468
|
+
# "X":"NEW", # Order Status
|
469
|
+
# "i":8886774, # Order Id
|
470
|
+
# "l":"0", # Order Last Filled Quantity
|
471
|
+
# "z":"0", # Order Filled Accumulated Quantity
|
472
|
+
# "L":"0", # Last Filled Price
|
473
|
+
# "N":"USDT", # Commission Asset, will not push if no commission
|
474
|
+
# "n":"0", # Commission, will not push if no commission
|
475
|
+
# "T":1568879465650, # Order Trade Time
|
476
|
+
# "t":0, # Trade Id
|
477
|
+
# "b":"0", # Bids Notional
|
478
|
+
# "a":"9.91", # Ask Notional
|
479
|
+
# "m":false, # Is self trade the maker side?
|
480
|
+
# "R":false, # Is self reduce only
|
481
|
+
# "wt":"CONTRACT_PRICE", # Stop Price Working Type
|
482
|
+
# "ot":"TRAILING_STOP_MARKET",// Original Order Type
|
483
|
+
# "ps":"LONG", # Position Side
|
484
|
+
# "cp":false, # If Close-All, pushed with conditional order
|
485
|
+
# "AP":"7476.89", # Activation Price, only puhed with TRAILING_STOP_MARKET order
|
486
|
+
# "cr":"5.0", # Callback Rate, only puhed with TRAILING_STOP_MARKET order
|
487
|
+
# "pP": False, # If price protection is turned on
|
488
|
+
# "si": 0, # ignore
|
489
|
+
# "ss": 0, # ignore
|
490
|
+
# "rp":"0", # Realized Profit of the trade
|
491
|
+
# "V":"EXPIRE_TAKER", # STP mode
|
492
|
+
# "pm":"OPPONENT", # Price match mode
|
493
|
+
# "gtd":0 # TIF GTD order auto cancel time
|
494
|
+
# }
|
495
|
+
#
|
496
|
+
orderType = self.safe_string(message, 'o')
|
497
|
+
if orderType != 'LIQUIDATION':
|
498
|
+
return
|
499
|
+
marketId = self.safe_string(message, 's')
|
500
|
+
market = self.safe_market(marketId)
|
501
|
+
symbol = self.safe_symbol(marketId)
|
502
|
+
liquidation = self.parse_ws_liquidation(message, market)
|
503
|
+
myLiquidations = self.safe_value(self.myLiquidations, symbol)
|
504
|
+
if myLiquidations is None:
|
505
|
+
limit = self.safe_integer(self.options, 'myLiquidationsLimit', 1000)
|
506
|
+
myLiquidations = ArrayCache(limit)
|
507
|
+
myLiquidations.append(liquidation)
|
508
|
+
self.myLiquidations[symbol] = myLiquidations
|
509
|
+
client.resolve([liquidation], 'myLiquidations')
|
510
|
+
client.resolve([liquidation], 'myLiquidations::' + symbol)
|
511
|
+
|
185
512
|
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
186
513
|
"""
|
187
514
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
@@ -2590,6 +2917,7 @@ class binance(ccxt.async_support.binance):
|
|
2590
2917
|
message = self.safe_dict(message, 'o', message)
|
2591
2918
|
self.handle_my_trade(client, message)
|
2592
2919
|
self.handle_order(client, message)
|
2920
|
+
self.handle_my_liquidation(client, message)
|
2593
2921
|
|
2594
2922
|
async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
|
2595
2923
|
"""
|
@@ -3131,6 +3459,7 @@ class binance(ccxt.async_support.binance):
|
|
3131
3459
|
'ACCOUNT_UPDATE': self.handle_acount_update,
|
3132
3460
|
'executionReport': self.handle_order_update,
|
3133
3461
|
'ORDER_TRADE_UPDATE': self.handle_order_update,
|
3462
|
+
'forceOrder': self.handle_liquidation,
|
3134
3463
|
}
|
3135
3464
|
event = self.safe_string(message, 'e')
|
3136
3465
|
if isinstance(message, list):
|
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, Tickers, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Liquidation, 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
|
@@ -21,6 +21,10 @@ class bitmex(ccxt.async_support.bitmex):
|
|
21
21
|
'has': {
|
22
22
|
'ws': True,
|
23
23
|
'watchBalance': True,
|
24
|
+
'watchLiquidations': True,
|
25
|
+
'watchLiquidationsForSymbols': True,
|
26
|
+
'watchMyLiquidations': None,
|
27
|
+
'watchMyLiquidationsForSymbols': None,
|
24
28
|
'watchMyTrades': True,
|
25
29
|
'watchOHLCV': True,
|
26
30
|
'watchOrderBook': True,
|
@@ -350,6 +354,98 @@ class bitmex(ccxt.async_support.bitmex):
|
|
350
354
|
client.resolve(fullParsedTicker, 'alltickers')
|
351
355
|
return message
|
352
356
|
|
357
|
+
async def watch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
358
|
+
"""
|
359
|
+
watch the public liquidations of a trading pair
|
360
|
+
:see: https://www.bitmex.com/app/wsAPI#Liquidation
|
361
|
+
:param str symbol: unified CCXT market symbol
|
362
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
363
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
364
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
365
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
366
|
+
"""
|
367
|
+
return self.watch_liquidations_for_symbols([symbol], since, limit, params)
|
368
|
+
|
369
|
+
async def watch_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
370
|
+
"""
|
371
|
+
watch the public liquidations of a trading pair
|
372
|
+
:see: https://www.bitmex.com/app/wsAPI#Liquidation
|
373
|
+
:param str symbol: unified CCXT market symbol
|
374
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
375
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
376
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
377
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
378
|
+
"""
|
379
|
+
await self.load_markets()
|
380
|
+
symbols = self.market_symbols(symbols, None, True, True)
|
381
|
+
messageHashes = []
|
382
|
+
subscriptionHashes = []
|
383
|
+
if self.is_empty(symbols):
|
384
|
+
subscriptionHashes.append('liquidation')
|
385
|
+
messageHashes.append('liquidations')
|
386
|
+
else:
|
387
|
+
for i in range(0, len(symbols)):
|
388
|
+
symbol = symbols[i]
|
389
|
+
market = self.market(symbol)
|
390
|
+
subscriptionHashes.append('liquidation:' + market['id'])
|
391
|
+
messageHashes.append('liquidations::' + symbol)
|
392
|
+
url = self.urls['api']['ws']
|
393
|
+
request = {
|
394
|
+
'op': 'subscribe',
|
395
|
+
'args': subscriptionHashes,
|
396
|
+
}
|
397
|
+
newLiquidations = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), subscriptionHashes)
|
398
|
+
if self.newUpdates:
|
399
|
+
return newLiquidations
|
400
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
|
401
|
+
|
402
|
+
def handle_liquidation(self, client: Client, message):
|
403
|
+
#
|
404
|
+
# {
|
405
|
+
# "table":"liquidation",
|
406
|
+
# "action":"partial",
|
407
|
+
# "keys":[
|
408
|
+
# "orderID"
|
409
|
+
# ],
|
410
|
+
# "types":{
|
411
|
+
# "orderID":"guid",
|
412
|
+
# "symbol":"symbol",
|
413
|
+
# "side":"symbol",
|
414
|
+
# "price":"float",
|
415
|
+
# "leavesQty":"long"
|
416
|
+
# },
|
417
|
+
# "filter":{},
|
418
|
+
# "data":[
|
419
|
+
# {
|
420
|
+
# "orderID":"e0a568ee-7830-4428-92c3-73e82b9576ce",
|
421
|
+
# "symbol":"XPLAUSDT",
|
422
|
+
# "side":"Sell",
|
423
|
+
# "price":0.206,
|
424
|
+
# "leavesQty":340
|
425
|
+
# }
|
426
|
+
# ]
|
427
|
+
# }
|
428
|
+
#
|
429
|
+
rawLiquidations = self.safe_value(message, 'data', [])
|
430
|
+
newLiquidations = []
|
431
|
+
for i in range(0, len(rawLiquidations)):
|
432
|
+
rawLiquidation = rawLiquidations[i]
|
433
|
+
liquidation = self.parse_liquidation(rawLiquidation)
|
434
|
+
symbol = liquidation['symbol']
|
435
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
436
|
+
if liquidations is None:
|
437
|
+
limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
|
438
|
+
liquidations = ArrayCache(limit)
|
439
|
+
liquidations.append(liquidation)
|
440
|
+
self.liquidations[symbol] = liquidations
|
441
|
+
newLiquidations.append(liquidation)
|
442
|
+
client.resolve(newLiquidations, 'liquidations')
|
443
|
+
liquidationsBySymbol = self.index_by(newLiquidations, 'symbol')
|
444
|
+
symbols = list(liquidationsBySymbol.keys())
|
445
|
+
for i in range(0, len(symbols)):
|
446
|
+
symbol = symbols[i]
|
447
|
+
client.resolve(liquidationsBySymbol[symbol], 'liquidations::' + symbol)
|
448
|
+
|
353
449
|
async def watch_balance(self, params={}) -> Balances:
|
354
450
|
"""
|
355
451
|
watch balance and get the amount of funds available for trading or funds locked in orders
|
@@ -1541,6 +1637,7 @@ class bitmex(ccxt.async_support.bitmex):
|
|
1541
1637
|
'order': self.handle_orders,
|
1542
1638
|
'execution': self.handle_my_trades,
|
1543
1639
|
'margin': self.handle_balance,
|
1640
|
+
'liquidation': self.handle_liquidation,
|
1544
1641
|
'position': self.handle_positions,
|
1545
1642
|
}
|
1546
1643
|
method = self.safe_value(methods, table)
|
ccxt/pro/bybit.py
CHANGED
@@ -7,7 +7,7 @@ import ccxt.async_support
|
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
|
8
8
|
import asyncio
|
9
9
|
import hashlib
|
10
|
-
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
|
10
|
+
from ccxt.base.types import Balances, Int, Liquidation, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
|
11
11
|
from ccxt.async_support.base.ws.client import Client
|
12
12
|
from typing import List
|
13
13
|
from ccxt.base.errors import ExchangeError
|
@@ -32,6 +32,10 @@ class bybit(ccxt.async_support.bybit):
|
|
32
32
|
'fetchTradesWs': False,
|
33
33
|
'fetchBalanceWs': False,
|
34
34
|
'watchBalance': True,
|
35
|
+
'watchLiquidations': True,
|
36
|
+
'watchLiquidationsForSymbols': False,
|
37
|
+
'watchMyLiquidations': False,
|
38
|
+
'watchMyLiquidationsForSymbols': False,
|
35
39
|
'watchMyTrades': True,
|
36
40
|
'watchOHLCV': True,
|
37
41
|
'watchOHLCVForSymbols': False,
|
@@ -1124,6 +1128,82 @@ class bybit(ccxt.async_support.bybit):
|
|
1124
1128
|
client.resolve(positions, messageHash)
|
1125
1129
|
client.resolve(newPositions, 'positions')
|
1126
1130
|
|
1131
|
+
async def watch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
1132
|
+
"""
|
1133
|
+
watch the public liquidations of a trading pair
|
1134
|
+
:see: https://bybit-exchange.github.io/docs/v5/websocket/public/liquidation
|
1135
|
+
:param str symbol: unified CCXT market symbol
|
1136
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
1137
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
1138
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
1139
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
1140
|
+
"""
|
1141
|
+
await self.load_markets()
|
1142
|
+
market = self.market(symbol)
|
1143
|
+
symbol = market['symbol']
|
1144
|
+
url = self.get_url_by_market_type(symbol, False, 'watchLiquidations', params)
|
1145
|
+
params = self.clean_params(params)
|
1146
|
+
messageHash = 'liquidations::' + symbol
|
1147
|
+
topic = 'liquidation.' + market['id']
|
1148
|
+
newLiquidation = await self.watch_topics(url, [messageHash], [topic], params)
|
1149
|
+
if self.newUpdates:
|
1150
|
+
return [newLiquidation]
|
1151
|
+
return self.filter_by_symbols_since_limit(self.liquidations, [symbol], since, limit, True)
|
1152
|
+
|
1153
|
+
def handle_liquidation(self, client: Client, message):
|
1154
|
+
#
|
1155
|
+
# {
|
1156
|
+
# "data": {
|
1157
|
+
# "price": "0.03803",
|
1158
|
+
# "side": "Buy",
|
1159
|
+
# "size": "1637",
|
1160
|
+
# "symbol": "GALAUSDT",
|
1161
|
+
# "updatedTime": 1673251091822
|
1162
|
+
# },
|
1163
|
+
# "topic": "liquidation.GALAUSDT",
|
1164
|
+
# "ts": 1673251091822,
|
1165
|
+
# "type": "snapshot"
|
1166
|
+
# }
|
1167
|
+
#
|
1168
|
+
rawLiquidation = self.safe_dict(message, 'data', {})
|
1169
|
+
marketId = self.safe_string(rawLiquidation, 'symbol')
|
1170
|
+
market = self.safe_market(marketId, None, '', 'contract')
|
1171
|
+
symbol = self.safe_symbol(marketId)
|
1172
|
+
liquidation = self.parse_ws_liquidation(rawLiquidation, market)
|
1173
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
1174
|
+
if liquidations is None:
|
1175
|
+
limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
|
1176
|
+
liquidations = ArrayCache(limit)
|
1177
|
+
liquidations.append(liquidation)
|
1178
|
+
self.liquidations[symbol] = liquidations
|
1179
|
+
client.resolve([liquidation], 'liquidations')
|
1180
|
+
client.resolve([liquidation], 'liquidations::' + symbol)
|
1181
|
+
|
1182
|
+
def parse_ws_liquidation(self, liquidation, market=None):
|
1183
|
+
#
|
1184
|
+
# {
|
1185
|
+
# "price": "0.03803",
|
1186
|
+
# "side": "Buy",
|
1187
|
+
# "size": "1637",
|
1188
|
+
# "symbol": "GALAUSDT",
|
1189
|
+
# "updatedTime": 1673251091822
|
1190
|
+
# }
|
1191
|
+
#
|
1192
|
+
marketId = self.safe_string(liquidation, 'symbol')
|
1193
|
+
market = self.safe_market(marketId, market, '', 'contract')
|
1194
|
+
timestamp = self.safe_integer(liquidation, 'updatedTime')
|
1195
|
+
return self.safe_liquidation({
|
1196
|
+
'info': liquidation,
|
1197
|
+
'symbol': self.safe_symbol(marketId, market),
|
1198
|
+
'contracts': self.safe_number(liquidation, 'size'),
|
1199
|
+
'contractSize': self.safe_number(market, 'contractSize'),
|
1200
|
+
'price': self.safe_number(liquidation, 'price'),
|
1201
|
+
'baseValue': None,
|
1202
|
+
'quoteValue': None,
|
1203
|
+
'timestamp': timestamp,
|
1204
|
+
'datetime': self.iso8601(timestamp),
|
1205
|
+
})
|
1206
|
+
|
1127
1207
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1128
1208
|
"""
|
1129
1209
|
watches information on multiple orders made by the user
|
@@ -1830,6 +1910,7 @@ class bybit(ccxt.async_support.bybit):
|
|
1830
1910
|
'ticketInfo': self.handle_my_trades,
|
1831
1911
|
'user.openapi.perp.trade': self.handle_my_trades,
|
1832
1912
|
'position': self.handle_positions,
|
1913
|
+
'liquidation': self.handle_liquidation,
|
1833
1914
|
'pong': self.handle_pong,
|
1834
1915
|
'order.create': self.handle_order_ws,
|
1835
1916
|
'order.amend': self.handle_order_ws,
|