ccxt 2.9.10__py2.py3-none-any.whl → 2.9.12__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.
Potentially problematic release.
This version of ccxt might be problematic. Click here for more details.
- ccxt/__init__.py +1 -1
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/bitget.py +2 -0
- ccxt/async_support/bybit.py +99 -45
- ccxt/async_support/novadax.py +3 -0
- ccxt/async_support/okx.py +5 -1
- ccxt/base/exchange.py +1 -1
- ccxt/bitget.py +2 -0
- ccxt/bybit.py +99 -45
- ccxt/novadax.py +3 -0
- ccxt/okx.py +5 -1
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/base/exchange.py +1 -1
- ccxt/pro/binance.py +2 -2
- ccxt/pro/bitfinex2.py +5 -3
- ccxt/pro/bybit.py +505 -502
- {ccxt-2.9.10.dist-info → ccxt-2.9.12.dist-info}/METADATA +4 -4
- {ccxt-2.9.10.dist-info → ccxt-2.9.12.dist-info}/RECORD +21 -21
- {ccxt-2.9.10.dist-info → ccxt-2.9.12.dist-info}/WHEEL +0 -0
- {ccxt-2.9.10.dist-info → ccxt-2.9.12.dist-info}/top_level.txt +0 -0
ccxt/pro/bybit.py
CHANGED
@@ -32,47 +32,43 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
32
32
|
'api': {
|
33
33
|
'ws': {
|
34
34
|
'public': {
|
35
|
-
'spot': 'wss://stream.{hostname}/
|
36
|
-
'inverse': 'wss://stream.{hostname}/
|
37
|
-
'
|
38
|
-
'
|
39
|
-
'option': 'wss://stream.{hostname}/option/usdc/public/v3',
|
40
|
-
'swap': 'wss://stream.{hostname}/contract/usdc/public/v3',
|
41
|
-
},
|
35
|
+
'spot': 'wss://stream.{hostname}/v5/public/spot',
|
36
|
+
'inverse': 'wss://stream.{hostname}/v5/public/inverse',
|
37
|
+
'option': 'wss://stream.{hostname}/v5/public/option',
|
38
|
+
'linear': 'wss://stream.{hostname}/v5/public/linear',
|
42
39
|
},
|
43
40
|
'private': {
|
44
|
-
'spot':
|
45
|
-
|
46
|
-
'
|
47
|
-
'nonUnified': 'wss://stream.{hostname}/contract/private/v3',
|
41
|
+
'spot': {
|
42
|
+
'unified': 'wss://stream.{hostname}/v5/private',
|
43
|
+
'nonUnified': 'wss://stream.{hostname}/spot/private/v3',
|
48
44
|
},
|
45
|
+
'contract': 'wss://stream.{hostname}/v5/private',
|
46
|
+
'usdc': 'wss://stream.{hostname}/trade/option/usdc/private/v1',
|
49
47
|
},
|
50
48
|
},
|
51
49
|
},
|
52
50
|
'test': {
|
53
51
|
'ws': {
|
54
52
|
'public': {
|
55
|
-
'spot': 'wss://stream-testnet.{hostname}/
|
56
|
-
'inverse': 'wss://stream-testnet.{hostname}/
|
57
|
-
'
|
58
|
-
'
|
59
|
-
'option': 'wss://stream-testnet.{hostname}/option/usdc/public/v3',
|
60
|
-
'swap': 'wss://stream-testnet.{hostname}/contract/usdc/public/v3',
|
61
|
-
},
|
53
|
+
'spot': 'wss://stream-testnet.{hostname}/v5/public/spot',
|
54
|
+
'inverse': 'wss://stream-testnet.{hostname}/v5/public/inverse',
|
55
|
+
'linear': 'wss://stream-testnet.{hostname}/v5/public/linear',
|
56
|
+
'option': 'wss://stream-testnet.{hostname}/v5/public/option',
|
62
57
|
},
|
63
58
|
'private': {
|
64
|
-
'spot':
|
65
|
-
|
66
|
-
'
|
67
|
-
'nonUnified': 'wss://stream-testnet.{hostname}/contract/private/v3',
|
59
|
+
'spot': {
|
60
|
+
'unified': 'wss://stream-testnet.{hostname}/v5/private',
|
61
|
+
'nonUnified': 'wss://stream-testnet.{hostname}/spot/private/v3',
|
68
62
|
},
|
63
|
+
'contract': 'wss://stream-testnet.{hostname}/v5/private',
|
64
|
+
'usdc': 'wss://stream-testnet.{hostname}/trade/option/usdc/private/v1',
|
69
65
|
},
|
70
66
|
},
|
71
67
|
},
|
72
68
|
},
|
73
69
|
'options': {
|
74
70
|
'watchTicker': {
|
75
|
-
'name': 'tickers', # 'tickers' for 24hr statistical ticker or '
|
71
|
+
'name': 'tickers', # 'tickers' for 24hr statistical ticker or 'tickers_lt' for leverage token ticker
|
76
72
|
},
|
77
73
|
'spot': {
|
78
74
|
'timeframes': {
|
@@ -126,43 +122,35 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
126
122
|
self.options['requestId'] = requestId
|
127
123
|
return requestId
|
128
124
|
|
129
|
-
def get_url_by_market_type(self, symbol=None, isPrivate=False,
|
125
|
+
def get_url_by_market_type(self, symbol=None, isPrivate=False, method=None, params={}):
|
130
126
|
accessibility = 'private' if isPrivate else 'public'
|
131
127
|
isUsdcSettled = None
|
132
128
|
isSpot = None
|
133
129
|
type = None
|
134
|
-
isUsdtSettled = None
|
135
130
|
market = None
|
136
131
|
url = self.urls['api']['ws']
|
137
132
|
if symbol is not None:
|
138
133
|
market = self.market(symbol)
|
139
134
|
isUsdcSettled = market['settle'] == 'USDC'
|
140
|
-
isUsdtSettled = market['settle'] == 'USDT'
|
141
|
-
isSpot = market['spot']
|
142
135
|
type = market['type']
|
143
136
|
else:
|
144
137
|
type, params = self.handle_market_type_and_params(method, None, params)
|
145
138
|
defaultSettle = self.safe_string(self.options, 'defaultSettle')
|
146
139
|
defaultSettle = self.safe_string_2(params, 'settle', 'defaultSettle', defaultSettle)
|
147
140
|
isUsdcSettled = (defaultSettle == 'USDC')
|
148
|
-
|
149
|
-
isSpot = (type == 'spot')
|
141
|
+
isSpot = (type == 'spot')
|
150
142
|
if isPrivate:
|
151
|
-
if
|
152
|
-
url = url[accessibility]['spot']
|
153
|
-
else:
|
154
|
-
margin = 'unified' if isUnifiedMargin else 'nonUnified'
|
155
|
-
url = url[accessibility]['contract'][margin]
|
143
|
+
url = url[accessibility]['usdc'] if (isUsdcSettled) else url[accessibility]['contract']
|
156
144
|
else:
|
157
145
|
if isSpot:
|
158
146
|
url = url[accessibility]['spot']
|
159
|
-
elif
|
160
|
-
|
161
|
-
|
162
|
-
url = url[accessibility][
|
147
|
+
elif type == 'swap':
|
148
|
+
subType = None
|
149
|
+
subType, params = self.handle_sub_type_and_params(method, market, params, 'linear')
|
150
|
+
url = url[accessibility][subType]
|
163
151
|
else:
|
164
|
-
#
|
165
|
-
url = url[accessibility]['
|
152
|
+
# option
|
153
|
+
url = url[accessibility]['option']
|
166
154
|
url = self.implode_hostname(url)
|
167
155
|
return url
|
168
156
|
|
@@ -173,6 +161,8 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
173
161
|
async def watch_ticker(self, symbol, params={}):
|
174
162
|
"""
|
175
163
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
164
|
+
see https://bybit-exchange.github.io/docs/v5/websocket/public/ticker
|
165
|
+
see https://bybit-exchange.github.io/docs/v5/websocket/public/etp-ticker
|
176
166
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
177
167
|
:param dict params: extra parameters specific to the bybit api endpoint
|
178
168
|
:returns dict: a `ticker structure <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
|
@@ -180,7 +170,7 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
180
170
|
await self.load_markets()
|
181
171
|
market = self.market(symbol)
|
182
172
|
messageHash = 'ticker:' + market['symbol']
|
183
|
-
url = self.get_url_by_market_type(symbol, False,
|
173
|
+
url = self.get_url_by_market_type(symbol, False, params)
|
184
174
|
params = self.clean_params(params)
|
185
175
|
options = self.safe_value(self.options, 'watchTicker', {})
|
186
176
|
topic = self.safe_string(options, 'name', 'tickers')
|
@@ -192,67 +182,104 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
192
182
|
|
193
183
|
def handle_ticker(self, client, message):
|
194
184
|
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
200
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
210
|
-
#
|
211
|
-
#
|
212
|
-
#
|
213
|
-
#
|
214
|
-
#
|
215
|
-
#
|
216
|
-
#
|
217
|
-
#
|
218
|
-
#
|
219
|
-
#
|
220
|
-
#
|
221
|
-
#
|
222
|
-
#
|
223
|
-
#
|
224
|
-
#
|
225
|
-
#
|
226
|
-
#
|
227
|
-
#
|
228
|
-
#
|
229
|
-
#
|
230
|
-
#
|
231
|
-
#
|
232
|
-
#
|
233
|
-
#
|
234
|
-
#
|
235
|
-
#
|
236
|
-
#
|
237
|
-
#
|
238
|
-
#
|
239
|
-
#
|
240
|
-
#
|
241
|
-
#
|
242
|
-
#
|
243
|
-
#
|
244
|
-
#
|
245
|
-
#
|
246
|
-
#
|
247
|
-
#
|
248
|
-
#
|
249
|
-
#
|
250
|
-
#
|
251
|
-
#
|
252
|
-
#
|
253
|
-
#
|
254
|
-
#
|
255
|
-
#
|
185
|
+
# linear
|
186
|
+
# {
|
187
|
+
# "topic": "tickers.BTCUSDT",
|
188
|
+
# "type": "snapshot",
|
189
|
+
# "data": {
|
190
|
+
# "symbol": "BTCUSDT",
|
191
|
+
# "tickDirection": "PlusTick",
|
192
|
+
# "price24hPcnt": "0.017103",
|
193
|
+
# "lastPrice": "17216.00",
|
194
|
+
# "prevPrice24h": "16926.50",
|
195
|
+
# "highPrice24h": "17281.50",
|
196
|
+
# "lowPrice24h": "16915.00",
|
197
|
+
# "prevPrice1h": "17238.00",
|
198
|
+
# "markPrice": "17217.33",
|
199
|
+
# "indexPrice": "17227.36",
|
200
|
+
# "openInterest": "68744.761",
|
201
|
+
# "openInterestValue": "1183601235.91",
|
202
|
+
# "turnover24h": "1570383121.943499",
|
203
|
+
# "volume24h": "91705.276",
|
204
|
+
# "nextFundingTime": "1673280000000",
|
205
|
+
# "fundingRate": "-0.000212",
|
206
|
+
# "bid1Price": "17215.50",
|
207
|
+
# "bid1Size": "84.489",
|
208
|
+
# "ask1Price": "17216.00",
|
209
|
+
# "ask1Size": "83.020"
|
210
|
+
# },
|
211
|
+
# "cs": 24987956059,
|
212
|
+
# "ts": 1673272861686
|
213
|
+
# }
|
214
|
+
#
|
215
|
+
# option
|
216
|
+
# {
|
217
|
+
# "id": "tickers.BTC-6JAN23-17500-C-2480334983-1672917511074",
|
218
|
+
# "topic": "tickers.BTC-6JAN23-17500-C",
|
219
|
+
# "ts": 1672917511074,
|
220
|
+
# "data": {
|
221
|
+
# "symbol": "BTC-6JAN23-17500-C",
|
222
|
+
# "bidPrice": "0",
|
223
|
+
# "bidSize": "0",
|
224
|
+
# "bidIv": "0",
|
225
|
+
# "askPrice": "10",
|
226
|
+
# "askSize": "5.1",
|
227
|
+
# "askIv": "0.514",
|
228
|
+
# "lastPrice": "10",
|
229
|
+
# "highPrice24h": "25",
|
230
|
+
# "lowPrice24h": "5",
|
231
|
+
# "markPrice": "7.86976724",
|
232
|
+
# "indexPrice": "16823.73",
|
233
|
+
# "markPriceIv": "0.4896",
|
234
|
+
# "underlyingPrice": "16815.1",
|
235
|
+
# "openInterest": "49.85",
|
236
|
+
# "turnover24h": "446802.8473",
|
237
|
+
# "volume24h": "26.55",
|
238
|
+
# "totalVolume": "86",
|
239
|
+
# "totalTurnover": "1437431",
|
240
|
+
# "delta": "0.047831",
|
241
|
+
# "gamma": "0.00021453",
|
242
|
+
# "vega": "0.81351067",
|
243
|
+
# "theta": "-19.9115368",
|
244
|
+
# "predictedDeliveryPrice": "0",
|
245
|
+
# "change24h": "-0.33333334"
|
246
|
+
# },
|
247
|
+
# "type": "snapshot"
|
248
|
+
# }
|
249
|
+
#
|
250
|
+
# spot
|
251
|
+
# {
|
252
|
+
# "topic": "tickers.BTCUSDT",
|
253
|
+
# "ts": 1673853746003,
|
254
|
+
# "type": "snapshot",
|
255
|
+
# "cs": 2588407389,
|
256
|
+
# "data": {
|
257
|
+
# "symbol": "BTCUSDT",
|
258
|
+
# "lastPrice": "21109.77",
|
259
|
+
# "highPrice24h": "21426.99",
|
260
|
+
# "lowPrice24h": "20575",
|
261
|
+
# "prevPrice24h": "20704.93",
|
262
|
+
# "volume24h": "6780.866843",
|
263
|
+
# "turnover24h": "141946527.22907118",
|
264
|
+
# "price24hPcnt": "0.0196",
|
265
|
+
# "usdIndexPrice": "21120.2400136"
|
266
|
+
# }
|
267
|
+
# }
|
268
|
+
#
|
269
|
+
# lt ticker
|
270
|
+
# {
|
271
|
+
# "topic": "tickers_lt.EOS3LUSDT",
|
272
|
+
# "ts": 1672325446847,
|
273
|
+
# "type": "snapshot",
|
274
|
+
# "data": {
|
275
|
+
# "symbol": "EOS3LUSDT",
|
276
|
+
# "lastPrice": "0.41477848043290448",
|
277
|
+
# "highPrice24h": "0.435285472510871305",
|
278
|
+
# "lowPrice24h": "0.394601507960931382",
|
279
|
+
# "prevPrice24h": "0.431502290172376349",
|
280
|
+
# "price24hPcnt": "-0.0388"
|
281
|
+
# }
|
282
|
+
# }
|
256
283
|
#
|
257
284
|
topic = self.safe_string(message, 'topic', '')
|
258
285
|
updateType = self.safe_string(message, 'type', '')
|
@@ -284,6 +311,8 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
284
311
|
async def watch_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
|
285
312
|
"""
|
286
313
|
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
314
|
+
see https://bybit-exchange.github.io/docs/v5/websocket/public/kline
|
315
|
+
see https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
|
287
316
|
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
288
317
|
:param str timeframe: the length of time each candle represents
|
289
318
|
:param int|None since: timestamp in ms of the earliest candle to fetch
|
@@ -294,13 +323,10 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
294
323
|
await self.load_markets()
|
295
324
|
market = self.market(symbol)
|
296
325
|
symbol = market['symbol']
|
297
|
-
url = self.get_url_by_market_type(symbol, False,
|
326
|
+
url = self.get_url_by_market_type(symbol, False, params)
|
298
327
|
params = self.clean_params(params)
|
299
328
|
ohlcv = None
|
300
|
-
|
301
|
-
marketOptions = self.safe_value(self.options, marketType, {})
|
302
|
-
timeframes = self.safe_value(marketOptions, 'timeframes', {})
|
303
|
-
timeframeId = self.safe_string(timeframes, timeframe, timeframe)
|
329
|
+
timeframeId = self.safe_string(self.timeframes, timeframe, timeframe)
|
304
330
|
topics = ['kline.' + timeframeId + '.' + market['id']]
|
305
331
|
messageHash = 'kline' + ':' + timeframeId + ':' + symbol
|
306
332
|
ohlcv = await self.watch_topics(url, messageHash, topics, params)
|
@@ -310,43 +336,26 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
310
336
|
|
311
337
|
def handle_ohlcv(self, client, message):
|
312
338
|
#
|
313
|
-
#
|
314
|
-
#
|
315
|
-
#
|
316
|
-
#
|
317
|
-
#
|
318
|
-
#
|
319
|
-
#
|
320
|
-
#
|
321
|
-
#
|
322
|
-
#
|
323
|
-
#
|
324
|
-
#
|
325
|
-
#
|
326
|
-
#
|
327
|
-
#
|
328
|
-
#
|
329
|
-
#
|
330
|
-
#
|
331
|
-
#
|
332
|
-
#
|
333
|
-
# }
|
334
|
-
#
|
335
|
-
# spot
|
336
|
-
# {
|
337
|
-
# "data": {
|
338
|
-
# "t": 1661742000000,
|
339
|
-
# "s": "BTCUSDT",
|
340
|
-
# "c": "19685.55",
|
341
|
-
# "h": "19756.95",
|
342
|
-
# "l": "19674.61",
|
343
|
-
# "o": "19705.38",
|
344
|
-
# "v": "0.232154"
|
345
|
-
# },
|
346
|
-
# "type": "delta",
|
347
|
-
# "topic": "kline.1h.BTCUSDT",
|
348
|
-
# "ts": 1661745259605
|
349
|
-
# }
|
339
|
+
# {
|
340
|
+
# "topic": "kline.5.BTCUSDT",
|
341
|
+
# "data": [
|
342
|
+
# {
|
343
|
+
# "start": 1672324800000,
|
344
|
+
# "end": 1672325099999,
|
345
|
+
# "interval": "5",
|
346
|
+
# "open": "16649.5",
|
347
|
+
# "close": "16677",
|
348
|
+
# "high": "16677",
|
349
|
+
# "low": "16608",
|
350
|
+
# "volume": "2.081",
|
351
|
+
# "turnover": "34666.4005",
|
352
|
+
# "confirm": False,
|
353
|
+
# "timestamp": 1672324988882
|
354
|
+
# }
|
355
|
+
# ],
|
356
|
+
# "ts": 1672324988882,
|
357
|
+
# "type": "snapshot"
|
358
|
+
# }
|
350
359
|
#
|
351
360
|
data = self.safe_value(message, 'data', {})
|
352
361
|
topic = self.safe_string(message, 'topic')
|
@@ -366,17 +375,13 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
366
375
|
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
367
376
|
stored = ArrayCacheByTimestamp(limit)
|
368
377
|
self.ohlcvs[symbol][timeframeId] = stored
|
369
|
-
|
370
|
-
|
371
|
-
parsed = self.parse_ws_contract_ohlcv(data[i])
|
372
|
-
stored.append(parsed)
|
373
|
-
else:
|
374
|
-
parsed = self.parse_ohlcv(data, market)
|
378
|
+
for i in range(0, len(data)):
|
379
|
+
parsed = self.parse_ws_ohlcv(data[i])
|
375
380
|
stored.append(parsed)
|
376
381
|
messageHash = 'kline' + ':' + timeframeId + ':' + symbol
|
377
382
|
client.resolve(stored, messageHash)
|
378
383
|
|
379
|
-
def
|
384
|
+
def parse_ws_ohlcv(self, ohlcv):
|
380
385
|
#
|
381
386
|
# {
|
382
387
|
# "start": 1670363160000,
|
@@ -404,6 +409,7 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
404
409
|
async def watch_order_book(self, symbol, limit=None, params={}):
|
405
410
|
"""
|
406
411
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
412
|
+
see https://bybit-exchange.github.io/docs/v5/websocket/public/orderbook
|
407
413
|
:param str symbol: unified symbol of the market to fetch the order book for
|
408
414
|
:param int|None limit: the maximum amount of order book entries to return.
|
409
415
|
:param dict params: extra parameters specific to the bybit api endpoint
|
@@ -412,81 +418,60 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
412
418
|
await self.load_markets()
|
413
419
|
market = self.market(symbol)
|
414
420
|
symbol = market['symbol']
|
415
|
-
url = self.get_url_by_market_type(symbol, False,
|
421
|
+
url = self.get_url_by_market_type(symbol, False, params)
|
416
422
|
params = self.clean_params(params)
|
417
423
|
messageHash = 'orderbook' + ':' + symbol
|
418
424
|
if limit is None:
|
419
425
|
if market['spot']:
|
420
|
-
limit =
|
426
|
+
limit = 50
|
421
427
|
else:
|
422
|
-
limit =
|
428
|
+
limit = 500
|
423
429
|
else:
|
424
430
|
if not market['spot']:
|
425
|
-
# bybit only support limit 1, 50
|
426
|
-
if (limit != 1) and (limit != 50) and (limit != 200):
|
427
|
-
raise BadRequest(self.id + ' watchOrderBook() can only use limit 1, 50 and
|
431
|
+
# bybit only support limit 1, 50, 200, 500 for contract
|
432
|
+
if (limit != 1) and (limit != 50) and (limit != 200) and (limit != 500):
|
433
|
+
raise BadRequest(self.id + ' watchOrderBook() can only use limit 1, 50, 200 and 500.')
|
428
434
|
topics = ['orderbook.' + str(limit) + '.' + market['id']]
|
429
435
|
orderbook = await self.watch_topics(url, messageHash, topics, params)
|
430
436
|
return orderbook.limit()
|
431
437
|
|
432
438
|
def handle_order_book(self, client, message):
|
433
439
|
#
|
434
|
-
# spot snapshot
|
435
440
|
# {
|
441
|
+
# "topic": "orderbook.50.BTCUSDT",
|
442
|
+
# "type": "snapshot",
|
443
|
+
# "ts": 1672304484978,
|
436
444
|
# "data": {
|
437
445
|
# "s": "BTCUSDT",
|
438
|
-
# "t": 1661743689733,
|
439
446
|
# "b": [
|
447
|
+
# ...,
|
440
448
|
# [
|
441
|
-
# "
|
442
|
-
# "0.
|
449
|
+
# "16493.50",
|
450
|
+
# "0.006"
|
443
451
|
# ],
|
444
|
-
#
|
452
|
+
# [
|
453
|
+
# "16493.00",
|
454
|
+
# "0.100"
|
455
|
+
# ]
|
445
456
|
# ],
|
446
457
|
# "a": [
|
447
458
|
# [
|
448
|
-
# "
|
449
|
-
# "0.
|
459
|
+
# "16611.00",
|
460
|
+
# "0.029"
|
450
461
|
# ],
|
451
|
-
#
|
452
|
-
#
|
453
|
-
#
|
454
|
-
#
|
455
|
-
#
|
456
|
-
#
|
462
|
+
# [
|
463
|
+
# "16612.00",
|
464
|
+
# "0.213"
|
465
|
+
# ],
|
466
|
+
# ],
|
467
|
+
# "u": 18521288,
|
468
|
+
# "seq": 7961638724
|
469
|
+
# }
|
457
470
|
# }
|
458
471
|
#
|
459
|
-
# contract
|
460
|
-
# {
|
461
|
-
# "topic": "orderbook.50.BTCUSDT",
|
462
|
-
# "type": "snapshot",
|
463
|
-
# "ts": 1668748553479,
|
464
|
-
# "data": {
|
465
|
-
# "s": "BTCUSDT",
|
466
|
-
# "b": [
|
467
|
-
# [
|
468
|
-
# "17053.00", #price
|
469
|
-
# "0.021" #size
|
470
|
-
# ],
|
471
|
-
# ....
|
472
|
-
# ],
|
473
|
-
# "a": [
|
474
|
-
# [
|
475
|
-
# "17054.00",
|
476
|
-
# "6.288"
|
477
|
-
# ],
|
478
|
-
# ....
|
479
|
-
# ],
|
480
|
-
# "u": 3083181,
|
481
|
-
# "seq": 7545268447
|
482
|
-
# }
|
483
|
-
# }
|
484
|
-
#
|
485
472
|
isSpot = client.url.find('spot') >= 0
|
486
473
|
type = self.safe_string(message, 'type')
|
487
474
|
isSnapshot = (type == 'snapshot')
|
488
|
-
if isSpot:
|
489
|
-
isSnapshot = True
|
490
475
|
data = self.safe_value(message, 'data', {})
|
491
476
|
marketId = self.safe_string(data, 's')
|
492
477
|
marketType = 'spot' if isSpot else 'contract'
|
@@ -521,6 +506,7 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
521
506
|
async def watch_trades(self, symbol, since=None, limit=None, params={}):
|
522
507
|
"""
|
523
508
|
watches information on multiple trades made in a market
|
509
|
+
see https://bybit-exchange.github.io/docs/v5/websocket/public/trade
|
524
510
|
:param str symbol: unified market symbol of the market orders were made in
|
525
511
|
:param int|None since: the earliest time in ms to fetch orders for
|
526
512
|
:param int|None limit: the maximum number of orde structures to retrieve
|
@@ -530,18 +516,10 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
530
516
|
await self.load_markets()
|
531
517
|
market = self.market(symbol)
|
532
518
|
symbol = market['symbol']
|
533
|
-
url = self.get_url_by_market_type(symbol, False,
|
519
|
+
url = self.get_url_by_market_type(symbol, False, params)
|
534
520
|
params = self.clean_params(params)
|
535
521
|
messageHash = 'trade:' + symbol
|
536
|
-
topic =
|
537
|
-
if market['spot']:
|
538
|
-
topic = 'trade.' + market['id']
|
539
|
-
else:
|
540
|
-
topic = 'publicTrade.'
|
541
|
-
if market['option']:
|
542
|
-
topic += market['baseId']
|
543
|
-
else:
|
544
|
-
topic += market['id']
|
522
|
+
topic = 'publicTrade.' + market['id']
|
545
523
|
trades = await self.watch_topics(url, messageHash, [topic], params)
|
546
524
|
if self.newUpdates:
|
547
525
|
limit = trades.getLimit(symbol, limit)
|
@@ -549,53 +527,32 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
549
527
|
|
550
528
|
def handle_trades(self, client, message):
|
551
529
|
#
|
552
|
-
#
|
553
|
-
#
|
554
|
-
#
|
555
|
-
#
|
556
|
-
#
|
557
|
-
#
|
558
|
-
#
|
559
|
-
#
|
560
|
-
#
|
561
|
-
#
|
562
|
-
#
|
563
|
-
#
|
564
|
-
#
|
565
|
-
#
|
566
|
-
#
|
567
|
-
#
|
568
|
-
#
|
569
|
-
# }
|
570
|
-
#
|
571
|
-
# spot
|
572
|
-
# {
|
573
|
-
# "data": {
|
574
|
-
# "v": "2100000000001992601",
|
575
|
-
# "t": 1661742109857,
|
576
|
-
# "p": "19706.87",
|
577
|
-
# "q": "0.000158",
|
578
|
-
# "m": True
|
579
|
-
# },
|
580
|
-
# "type": "delta",
|
581
|
-
# "topic": "trade.BTCUSDT",
|
582
|
-
# "ts": 1661742109863
|
583
|
-
# }
|
530
|
+
# {
|
531
|
+
# "topic": "publicTrade.BTCUSDT",
|
532
|
+
# "type": "snapshot",
|
533
|
+
# "ts": 1672304486868,
|
534
|
+
# "data": [
|
535
|
+
# {
|
536
|
+
# "T": 1672304486865,
|
537
|
+
# "s": "BTCUSDT",
|
538
|
+
# "S": "Buy",
|
539
|
+
# "v": "0.001",
|
540
|
+
# "p": "16578.50",
|
541
|
+
# "L": "PlusTick",
|
542
|
+
# "i": "20f43950-d8dd-5b31-9112-a178eb6023af",
|
543
|
+
# "BT": False
|
544
|
+
# }
|
545
|
+
# ]
|
546
|
+
# }
|
584
547
|
#
|
585
548
|
data = self.safe_value(message, 'data', {})
|
586
549
|
topic = self.safe_string(message, 'topic')
|
587
|
-
trades =
|
550
|
+
trades = data
|
588
551
|
parts = topic.split('.')
|
589
|
-
|
590
|
-
marketType = 'spot' if (
|
552
|
+
isSpot = client.url.find('spot') >= 0
|
553
|
+
marketType = 'spot' if (isSpot) else 'contract'
|
591
554
|
marketId = self.safe_string(parts, 1)
|
592
555
|
market = self.safe_market(marketId, None, None, marketType)
|
593
|
-
if isinstance(data, list):
|
594
|
-
# contract markets
|
595
|
-
trades = data
|
596
|
-
else:
|
597
|
-
# spot markets
|
598
|
-
trades = [data]
|
599
556
|
symbol = market['symbol']
|
600
557
|
stored = self.safe_value(self.trades, symbol)
|
601
558
|
if stored is None:
|
@@ -610,51 +567,16 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
610
567
|
|
611
568
|
def parse_ws_trade(self, trade, market=None):
|
612
569
|
#
|
613
|
-
#
|
614
|
-
# {
|
615
|
-
# T: 1670198879981,
|
616
|
-
# s: 'BTCUSDT',
|
617
|
-
# S: 'Buy',
|
618
|
-
# v: '0.001',
|
619
|
-
# p: '17130.00',
|
620
|
-
# L: 'ZeroPlusTick',
|
621
|
-
# i: 'a807f4ee-2e8b-5f21-a02a-3e258ddbfdc9',
|
622
|
-
# BT: False
|
623
|
-
# }
|
624
|
-
# contract private
|
625
|
-
#
|
626
|
-
# parsed by rest implementation
|
627
|
-
# {
|
628
|
-
# "symbol": "BITUSDT",
|
629
|
-
# "execFee": "0.02022",
|
630
|
-
# "execId": "beba036f-9fb4-59a7-84b7-2620e5d13e1c",
|
631
|
-
# "execPrice": "0.674",
|
632
|
-
# "execQty": "50",
|
633
|
-
# "execType": "Trade",
|
634
|
-
# "execValue": "33.7",
|
635
|
-
# "feeRate": "0.0006",
|
636
|
-
# "lastLiquidityInd": "RemovedLiquidity",
|
637
|
-
# "leavesQty": "0",
|
638
|
-
# "orderId": "ddbea432-2bd7-45dd-ab42-52d920b8136d",
|
639
|
-
# "orderLinkId": "b001",
|
640
|
-
# "orderPrice": "0.707",
|
641
|
-
# "orderQty": "50",
|
642
|
-
# "orderType": "Market",
|
643
|
-
# "stopOrderType": "UNKNOWN",
|
644
|
-
# "side": "Buy",
|
645
|
-
# "execTime": "1659057535081",
|
646
|
-
# "closedSize": "0"
|
647
|
-
# }
|
648
|
-
#
|
649
|
-
# spot public
|
650
|
-
#
|
570
|
+
# public
|
651
571
|
# {
|
652
|
-
#
|
653
|
-
#
|
654
|
-
#
|
655
|
-
#
|
656
|
-
#
|
657
|
-
#
|
572
|
+
# "T": 1672304486865,
|
573
|
+
# "s": "BTCUSDT",
|
574
|
+
# "S": "Buy",
|
575
|
+
# "v": "0.001",
|
576
|
+
# "p": "16578.50",
|
577
|
+
# "L": "PlusTick",
|
578
|
+
# "i": "20f43950-d8dd-5b31-9112-a178eb6023af",
|
579
|
+
# "BT": False
|
658
580
|
# }
|
659
581
|
#
|
660
582
|
# spot private
|
@@ -678,6 +600,8 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
678
600
|
id = self.safe_string_n(trade, ['i', 'T', 'v'])
|
679
601
|
isContract = ('BT' in trade)
|
680
602
|
marketType = 'contract' if isContract else 'spot'
|
603
|
+
if market is not None:
|
604
|
+
marketType = market['type']
|
681
605
|
marketId = self.safe_string(trade, 's')
|
682
606
|
market = self.safe_market(marketId, market, None, marketType)
|
683
607
|
symbol = market['symbol']
|
@@ -712,14 +636,15 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
712
636
|
def get_private_type(self, url):
|
713
637
|
if url.find('spot') >= 0:
|
714
638
|
return 'spot'
|
715
|
-
elif url.find('
|
639
|
+
elif url.find('v5/private') >= 0:
|
716
640
|
return 'unified'
|
717
|
-
|
718
|
-
return '
|
641
|
+
else:
|
642
|
+
return 'usdc'
|
719
643
|
|
720
644
|
async def watch_my_trades(self, symbol=None, since=None, limit=None, params={}):
|
721
645
|
"""
|
722
646
|
watches information on multiple trades made by the user
|
647
|
+
see https://bybit-exchange.github.io/docs/v5/websocket/private/execution
|
723
648
|
:param str symbol: unified market symbol of the market orders were made in
|
724
649
|
:param int|None since: the earliest time in ms to fetch orders for
|
725
650
|
:param int|None limit: the maximum number of orde structures to retrieve
|
@@ -733,14 +658,12 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
733
658
|
if symbol is not None:
|
734
659
|
symbol = self.symbol(symbol)
|
735
660
|
messageHash += ':' + symbol
|
736
|
-
|
737
|
-
isUnifiedMargin = self.safe_value(unified, 0, False)
|
738
|
-
url = self.get_url_by_market_type(symbol, True, isUnifiedMargin, method, params)
|
661
|
+
url = self.get_url_by_market_type(symbol, True, method, params)
|
739
662
|
await self.authenticate(url)
|
740
663
|
topicByMarket = {
|
741
664
|
'spot': 'ticketInfo',
|
742
|
-
'
|
743
|
-
'
|
665
|
+
'unified': 'execution',
|
666
|
+
'usdc': 'user.openapi.perp.trade',
|
744
667
|
}
|
745
668
|
topic = self.safe_value(topicByMarket, self.get_private_type(url))
|
746
669
|
trades = await self.watch_topics(url, messageHash, [topic], params)
|
@@ -750,6 +673,7 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
750
673
|
|
751
674
|
def handle_my_trades(self, client, message):
|
752
675
|
#
|
676
|
+
# spot
|
753
677
|
# {
|
754
678
|
# "type": "snapshot",
|
755
679
|
# "topic": "ticketInfo",
|
@@ -773,39 +697,48 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
773
697
|
# }
|
774
698
|
# ]
|
775
699
|
# }
|
776
|
-
#
|
700
|
+
# unified
|
777
701
|
# {
|
778
|
-
#
|
779
|
-
#
|
780
|
-
#
|
781
|
-
#
|
782
|
-
#
|
783
|
-
#
|
784
|
-
#
|
785
|
-
#
|
786
|
-
#
|
787
|
-
#
|
788
|
-
#
|
789
|
-
#
|
790
|
-
#
|
791
|
-
#
|
792
|
-
#
|
793
|
-
#
|
794
|
-
#
|
795
|
-
#
|
796
|
-
#
|
797
|
-
#
|
798
|
-
#
|
799
|
-
#
|
800
|
-
#
|
702
|
+
# "id": "592324803b2785-26fa-4214-9963-bdd4727f07be",
|
703
|
+
# "topic": "execution",
|
704
|
+
# "creationTime": 1672364174455,
|
705
|
+
# "data": [
|
706
|
+
# {
|
707
|
+
# "category": "linear",
|
708
|
+
# "symbol": "XRPUSDT",
|
709
|
+
# "execFee": "0.005061",
|
710
|
+
# "execId": "7e2ae69c-4edf-5800-a352-893d52b446aa",
|
711
|
+
# "execPrice": "0.3374",
|
712
|
+
# "execQty": "25",
|
713
|
+
# "execType": "Trade",
|
714
|
+
# "execValue": "8.435",
|
715
|
+
# "isMaker": False,
|
716
|
+
# "feeRate": "0.0006",
|
717
|
+
# "tradeIv": "",
|
718
|
+
# "markIv": "",
|
719
|
+
# "blockTradeId": "",
|
720
|
+
# "markPrice": "0.3391",
|
721
|
+
# "indexPrice": "",
|
722
|
+
# "underlyingPrice": "",
|
723
|
+
# "leavesQty": "0",
|
724
|
+
# "orderId": "f6e324ff-99c2-4e89-9739-3086e47f9381",
|
725
|
+
# "orderLinkId": "",
|
726
|
+
# "orderPrice": "0.3207",
|
727
|
+
# "orderQty": "25",
|
728
|
+
# "orderType": "Market",
|
729
|
+
# "stopOrderType": "UNKNOWN",
|
730
|
+
# "side": "Sell",
|
731
|
+
# "execTime": "1672364174443",
|
732
|
+
# "isLeverage": "0"
|
733
|
+
# }
|
801
734
|
# ]
|
802
735
|
# }
|
803
736
|
#
|
804
737
|
topic = self.safe_string(message, 'topic')
|
805
738
|
spot = topic == 'ticketInfo'
|
806
739
|
data = self.safe_value(message, 'data', [])
|
807
|
-
|
808
|
-
|
740
|
+
if not isinstance(data, list):
|
741
|
+
data = self.safe_value(data, 'result', [])
|
809
742
|
if self.myTrades is None:
|
810
743
|
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
811
744
|
self.myTrades = ArrayCacheBySymbolById(limit)
|
@@ -829,6 +762,7 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
829
762
|
async def watch_orders(self, symbol=None, since=None, limit=None, params={}):
|
830
763
|
"""
|
831
764
|
watches information on multiple orders made by the user
|
765
|
+
see https://bybit-exchange.github.io/docs/v5/websocket/private/order
|
832
766
|
:param str|None symbol: unified market symbol of the market orders were made in
|
833
767
|
:param int|None since: the earliest time in ms to fetch orders for
|
834
768
|
:param int|None limit: the maximum number of orde structures to retrieve
|
@@ -841,14 +775,12 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
841
775
|
if symbol is not None:
|
842
776
|
symbol = self.symbol(symbol)
|
843
777
|
messageHash += ':' + symbol
|
844
|
-
|
845
|
-
isUnifiedMargin = self.safe_value(unified, 0, False)
|
846
|
-
url = self.get_url_by_market_type(None, True, isUnifiedMargin, method, params)
|
778
|
+
url = self.get_url_by_market_type(symbol, True, method, params)
|
847
779
|
await self.authenticate(url)
|
848
780
|
topicsByMarket = {
|
849
781
|
'spot': ['order', 'stopOrder'],
|
850
|
-
'
|
851
|
-
'
|
782
|
+
'unified': ['order'],
|
783
|
+
'usdc': ['user.openapi.perp.order'],
|
852
784
|
}
|
853
785
|
topics = self.safe_value(topicsByMarket, self.get_private_type(url))
|
854
786
|
orders = await self.watch_topics(url, messageHash, topics, params)
|
@@ -895,91 +827,59 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
895
827
|
# }
|
896
828
|
# ]
|
897
829
|
# }
|
898
|
-
#
|
830
|
+
# unified
|
899
831
|
# {
|
900
|
-
# "
|
832
|
+
# "id": "5923240c6880ab-c59f-420b-9adb-3639adc9dd90",
|
833
|
+
# "topic": "order",
|
834
|
+
# "creationTime": 1672364262474,
|
901
835
|
# "data": [
|
902
836
|
# {
|
903
|
-
# "symbol": "
|
904
|
-
# "orderId": "
|
905
|
-
# "side": "
|
837
|
+
# "symbol": "ETH-30DEC22-1400-C",
|
838
|
+
# "orderId": "5cf98598-39a7-459e-97bf-76ca765ee020",
|
839
|
+
# "side": "Sell",
|
906
840
|
# "orderType": "Market",
|
907
|
-
# "
|
908
|
-
# "price": "
|
909
|
-
# "qty": "
|
910
|
-
# "
|
841
|
+
# "cancelType": "UNKNOWN",
|
842
|
+
# "price": "72.5",
|
843
|
+
# "qty": "1",
|
844
|
+
# "orderIv": "",
|
845
|
+
# "timeInForce": "IOC",
|
911
846
|
# "orderStatus": "Filled",
|
912
|
-
# "
|
913
|
-
# "
|
914
|
-
# "createdTime": "1661338622771",
|
915
|
-
# "updatedTime": "1661338622775",
|
916
|
-
# "takeProfit": "0.00",
|
917
|
-
# "stopLoss": "0.00",
|
918
|
-
# "tpTriggerBy": "UNKNOWN",
|
919
|
-
# "slTriggerBy": "UNKNOWN",
|
920
|
-
# "triggerBy": "UNKNOWN",
|
847
|
+
# "orderLinkId": "",
|
848
|
+
# "lastPriceOnCreated": "",
|
921
849
|
# "reduceOnly": False,
|
922
|
-
# "
|
850
|
+
# "leavesQty": "",
|
851
|
+
# "leavesValue": "",
|
852
|
+
# "cumExecQty": "1",
|
853
|
+
# "cumExecValue": "75",
|
854
|
+
# "avgPrice": "75",
|
855
|
+
# "blockTradeId": "",
|
856
|
+
# "positionIdx": 0,
|
857
|
+
# "cumExecFee": "0.358635",
|
858
|
+
# "createdTime": "1672364262444",
|
859
|
+
# "updatedTime": "1672364262457",
|
860
|
+
# "rejectReason": "EC_NoError",
|
861
|
+
# "stopOrderType": "",
|
862
|
+
# "triggerPrice": "",
|
863
|
+
# "takeProfit": "",
|
864
|
+
# "stopLoss": "",
|
865
|
+
# "tpTriggerBy": "",
|
866
|
+
# "slTriggerBy": "",
|
923
867
|
# "triggerDirection": 0,
|
924
|
-
# "
|
925
|
-
# "
|
926
|
-
# "
|
927
|
-
# "cumExecQty": "200",
|
928
|
-
# "cumExecValue": "0.00939761"
|
868
|
+
# "triggerBy": "",
|
869
|
+
# "closeOnTrigger": False,
|
870
|
+
# "category": "option"
|
929
871
|
# }
|
930
872
|
# ]
|
931
873
|
# }
|
932
|
-
# unified
|
933
|
-
# {
|
934
|
-
# "id": "f91080af-5187-4261-a802-7604419771aa",
|
935
|
-
# "topic": "user.order.unifiedAccount",
|
936
|
-
# "ts": 1661932033707,
|
937
|
-
# "data": {
|
938
|
-
# "result": [
|
939
|
-
# {
|
940
|
-
# "orderId": "415f8961-4073-4d74-bc3e-df2830e52843",
|
941
|
-
# "orderLinkId": "",
|
942
|
-
# "symbol": "BTCUSDT",
|
943
|
-
# "side": "Buy",
|
944
|
-
# "orderType": "Limit",
|
945
|
-
# "price": "17000.00000000",
|
946
|
-
# "qty": "0.0100",
|
947
|
-
# "timeInForce": "GoodTillCancel",
|
948
|
-
# "orderStatus": "New",
|
949
|
-
# "cumExecQty": "0.0000",
|
950
|
-
# "cumExecValue": "0.00000000",
|
951
|
-
# "cumExecFee": "0.00000000",
|
952
|
-
# "stopOrderType": "UNKNOWN",
|
953
|
-
# "triggerBy": "UNKNOWN",
|
954
|
-
# "triggerPrice": "",
|
955
|
-
# "reduceOnly": True,
|
956
|
-
# "closeOnTrigger": True,
|
957
|
-
# "createdTime": 1661932033636,
|
958
|
-
# "updatedTime": 1661932033644,
|
959
|
-
# "iv": "",
|
960
|
-
# "orderIM": "",
|
961
|
-
# "takeProfit": "",
|
962
|
-
# "stopLoss": "",
|
963
|
-
# "tpTriggerBy": "UNKNOWN",
|
964
|
-
# "slTriggerBy": "UNKNOWN",
|
965
|
-
# "basePrice": "",
|
966
|
-
# "blockTradeId": "",
|
967
|
-
# "leavesQty": "0.0100"
|
968
|
-
# }
|
969
|
-
# ],
|
970
|
-
# "version": 284
|
971
|
-
# },
|
972
|
-
# "type": "snapshot"
|
973
|
-
# }
|
974
874
|
#
|
975
|
-
|
875
|
+
type = self.safe_string(message, 'type', '')
|
976
876
|
if self.orders is None:
|
977
877
|
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
978
878
|
self.orders = ArrayCacheBySymbolById(limit)
|
979
879
|
orders = self.orders
|
980
880
|
rawOrders = []
|
981
881
|
parser = None
|
982
|
-
if
|
882
|
+
if type == 'snapshot':
|
983
883
|
rawOrders = self.safe_value(message, 'data', [])
|
984
884
|
parser = 'parseWsSpotOrder'
|
985
885
|
else:
|
@@ -1088,20 +988,47 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
1088
988
|
async def watch_balance(self, params={}):
|
1089
989
|
"""
|
1090
990
|
query for balance and get the amount of funds available for trading or funds locked in orders
|
991
|
+
see https://bybit-exchange.github.io/docs/v5/websocket/private/wallet
|
1091
992
|
:param dict params: extra parameters specific to the bybit api endpoint
|
1092
993
|
:returns dict: a `balance structure <https://docs.ccxt.com/en/latest/manual.html?#balance-structure>`
|
1093
994
|
"""
|
995
|
+
await self.load_markets()
|
1094
996
|
method = 'watchBalance'
|
1095
997
|
messageHash = 'balances'
|
998
|
+
type = None
|
999
|
+
type, params = self.handle_market_type_and_params('watchBalance', None, params)
|
1000
|
+
subType = None
|
1001
|
+
subType, params = self.handle_sub_type_and_params('watchBalance', None, params)
|
1096
1002
|
unified = await self.isUnifiedEnabled()
|
1097
1003
|
isUnifiedMargin = self.safe_value(unified, 0, False)
|
1098
|
-
|
1004
|
+
isUnifiedAccount = self.safe_value(unified, 1, False)
|
1005
|
+
url = self.get_url_by_market_type(None, True, method, params)
|
1099
1006
|
await self.authenticate(url)
|
1100
1007
|
topicByMarket = {
|
1101
1008
|
'spot': 'outboundAccountInfo',
|
1102
|
-
'
|
1103
|
-
'unified': 'user.wallet.unifiedAccount',
|
1009
|
+
'unified': 'wallet',
|
1104
1010
|
}
|
1011
|
+
if isUnifiedAccount:
|
1012
|
+
# unified account
|
1013
|
+
if subType == 'inverse':
|
1014
|
+
messageHash += ':contract'
|
1015
|
+
else:
|
1016
|
+
messageHash += ':unified'
|
1017
|
+
if not isUnifiedMargin and not isUnifiedAccount:
|
1018
|
+
# normal account using v5
|
1019
|
+
if type == 'spot':
|
1020
|
+
messageHash += ':spot'
|
1021
|
+
else:
|
1022
|
+
messageHash += ':contract'
|
1023
|
+
if isUnifiedMargin:
|
1024
|
+
# unified margin account using v5
|
1025
|
+
if type == 'spot':
|
1026
|
+
messageHash += ':spot'
|
1027
|
+
else:
|
1028
|
+
if subType == 'linear':
|
1029
|
+
messageHash += ':unified'
|
1030
|
+
else:
|
1031
|
+
messageHash += ':contract'
|
1105
1032
|
topics = [self.safe_value(topicByMarket, self.get_private_type(url))]
|
1106
1033
|
return await self.watch_topics(url, messageHash, topics, params)
|
1107
1034
|
|
@@ -1129,59 +1056,124 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
1129
1056
|
# }
|
1130
1057
|
# ]
|
1131
1058
|
# }
|
1132
|
-
# contract
|
1133
|
-
# {
|
1134
|
-
# "topic": "user.wallet.contractAccount",
|
1135
|
-
# "data": [
|
1136
|
-
# {
|
1137
|
-
# "coin": "USDT",
|
1138
|
-
# "equity": "610.3984319",
|
1139
|
-
# "walletBalance": "609.7384319",
|
1140
|
-
# "positionMargin": "4.7582882",
|
1141
|
-
# "availableBalance": "604.9801437",
|
1142
|
-
# "orderMargin": "0",
|
1143
|
-
# "unrealisedPnl": "0.66",
|
1144
|
-
# "cumRealisedPnl": "-0.2615681"
|
1145
|
-
# }
|
1146
|
-
# ]
|
1147
|
-
# }
|
1148
1059
|
# unified
|
1149
|
-
#
|
1150
|
-
#
|
1151
|
-
#
|
1152
|
-
#
|
1153
|
-
#
|
1154
|
-
#
|
1155
|
-
#
|
1156
|
-
#
|
1157
|
-
#
|
1158
|
-
#
|
1159
|
-
#
|
1160
|
-
#
|
1161
|
-
#
|
1162
|
-
#
|
1163
|
-
#
|
1164
|
-
#
|
1165
|
-
#
|
1166
|
-
#
|
1167
|
-
#
|
1168
|
-
#
|
1169
|
-
#
|
1170
|
-
#
|
1171
|
-
#
|
1172
|
-
#
|
1173
|
-
#
|
1174
|
-
#
|
1175
|
-
#
|
1176
|
-
#
|
1177
|
-
#
|
1178
|
-
#
|
1179
|
-
#
|
1180
|
-
#
|
1181
|
-
#
|
1182
|
-
#
|
1183
|
-
#
|
1184
|
-
#
|
1060
|
+
# {
|
1061
|
+
# "id": "5923242c464be9-25ca-483d-a743-c60101fc656f",
|
1062
|
+
# "topic": "wallet",
|
1063
|
+
# "creationTime": 1672364262482,
|
1064
|
+
# "data": [
|
1065
|
+
# {
|
1066
|
+
# "accountIMRate": "0.016",
|
1067
|
+
# "accountMMRate": "0.003",
|
1068
|
+
# "totalEquity": "12837.78330098",
|
1069
|
+
# "totalWalletBalance": "12840.4045924",
|
1070
|
+
# "totalMarginBalance": "12837.78330188",
|
1071
|
+
# "totalAvailableBalance": "12632.05767702",
|
1072
|
+
# "totalPerpUPL": "-2.62129051",
|
1073
|
+
# "totalInitialMargin": "205.72562486",
|
1074
|
+
# "totalMaintenanceMargin": "39.42876721",
|
1075
|
+
# "coin": [
|
1076
|
+
# {
|
1077
|
+
# "coin": "USDC",
|
1078
|
+
# "equity": "200.62572554",
|
1079
|
+
# "usdValue": "200.62572554",
|
1080
|
+
# "walletBalance": "201.34882644",
|
1081
|
+
# "availableToWithdraw": "0",
|
1082
|
+
# "availableToBorrow": "1500000",
|
1083
|
+
# "borrowAmount": "0",
|
1084
|
+
# "accruedInterest": "0",
|
1085
|
+
# "totalOrderIM": "0",
|
1086
|
+
# "totalPositionIM": "202.99874213",
|
1087
|
+
# "totalPositionMM": "39.14289747",
|
1088
|
+
# "unrealisedPnl": "74.2768991",
|
1089
|
+
# "cumRealisedPnl": "-209.1544627",
|
1090
|
+
# "bonus": "0"
|
1091
|
+
# },
|
1092
|
+
# {
|
1093
|
+
# "coin": "BTC",
|
1094
|
+
# "equity": "0.06488393",
|
1095
|
+
# "usdValue": "1023.08402268",
|
1096
|
+
# "walletBalance": "0.06488393",
|
1097
|
+
# "availableToWithdraw": "0.06488393",
|
1098
|
+
# "availableToBorrow": "2.5",
|
1099
|
+
# "borrowAmount": "0",
|
1100
|
+
# "accruedInterest": "0",
|
1101
|
+
# "totalOrderIM": "0",
|
1102
|
+
# "totalPositionIM": "0",
|
1103
|
+
# "totalPositionMM": "0",
|
1104
|
+
# "unrealisedPnl": "0",
|
1105
|
+
# "cumRealisedPnl": "0",
|
1106
|
+
# "bonus": "0"
|
1107
|
+
# },
|
1108
|
+
# {
|
1109
|
+
# "coin": "ETH",
|
1110
|
+
# "equity": "0",
|
1111
|
+
# "usdValue": "0",
|
1112
|
+
# "walletBalance": "0",
|
1113
|
+
# "availableToWithdraw": "0",
|
1114
|
+
# "availableToBorrow": "26",
|
1115
|
+
# "borrowAmount": "0",
|
1116
|
+
# "accruedInterest": "0",
|
1117
|
+
# "totalOrderIM": "0",
|
1118
|
+
# "totalPositionIM": "0",
|
1119
|
+
# "totalPositionMM": "0",
|
1120
|
+
# "unrealisedPnl": "0",
|
1121
|
+
# "cumRealisedPnl": "0",
|
1122
|
+
# "bonus": "0"
|
1123
|
+
# },
|
1124
|
+
# {
|
1125
|
+
# "coin": "USDT",
|
1126
|
+
# "equity": "11726.64664904",
|
1127
|
+
# "usdValue": "11613.58597018",
|
1128
|
+
# "walletBalance": "11728.54414904",
|
1129
|
+
# "availableToWithdraw": "11723.92075829",
|
1130
|
+
# "availableToBorrow": "2500000",
|
1131
|
+
# "borrowAmount": "0",
|
1132
|
+
# "accruedInterest": "0",
|
1133
|
+
# "totalOrderIM": "0",
|
1134
|
+
# "totalPositionIM": "2.72589075",
|
1135
|
+
# "totalPositionMM": "0.28576575",
|
1136
|
+
# "unrealisedPnl": "-1.8975",
|
1137
|
+
# "cumRealisedPnl": "0.64782276",
|
1138
|
+
# "bonus": "0"
|
1139
|
+
# },
|
1140
|
+
# {
|
1141
|
+
# "coin": "EOS3L",
|
1142
|
+
# "equity": "215.0570412",
|
1143
|
+
# "usdValue": "0",
|
1144
|
+
# "walletBalance": "215.0570412",
|
1145
|
+
# "availableToWithdraw": "215.0570412",
|
1146
|
+
# "availableToBorrow": "0",
|
1147
|
+
# "borrowAmount": "0",
|
1148
|
+
# "accruedInterest": "",
|
1149
|
+
# "totalOrderIM": "0",
|
1150
|
+
# "totalPositionIM": "0",
|
1151
|
+
# "totalPositionMM": "0",
|
1152
|
+
# "unrealisedPnl": "0",
|
1153
|
+
# "cumRealisedPnl": "0",
|
1154
|
+
# "bonus": "0"
|
1155
|
+
# },
|
1156
|
+
# {
|
1157
|
+
# "coin": "BIT",
|
1158
|
+
# "equity": "1.82",
|
1159
|
+
# "usdValue": "0.48758257",
|
1160
|
+
# "walletBalance": "1.82",
|
1161
|
+
# "availableToWithdraw": "1.82",
|
1162
|
+
# "availableToBorrow": "0",
|
1163
|
+
# "borrowAmount": "0",
|
1164
|
+
# "accruedInterest": "",
|
1165
|
+
# "totalOrderIM": "0",
|
1166
|
+
# "totalPositionIM": "0",
|
1167
|
+
# "totalPositionMM": "0",
|
1168
|
+
# "unrealisedPnl": "0",
|
1169
|
+
# "cumRealisedPnl": "0",
|
1170
|
+
# "bonus": "0"
|
1171
|
+
# }
|
1172
|
+
# ],
|
1173
|
+
# "accountType": "UNIFIED"
|
1174
|
+
# }
|
1175
|
+
# ]
|
1176
|
+
# }
|
1185
1177
|
#
|
1186
1178
|
if self.balance is None:
|
1187
1179
|
self.balance = {}
|
@@ -1189,31 +1181,43 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
1189
1181
|
topic = self.safe_value(message, 'topic')
|
1190
1182
|
info = None
|
1191
1183
|
rawBalances = []
|
1184
|
+
account = None
|
1192
1185
|
if topic == 'outboundAccountInfo':
|
1186
|
+
account = 'spot'
|
1193
1187
|
data = self.safe_value(message, 'data', [])
|
1194
1188
|
for i in range(0, len(data)):
|
1195
1189
|
B = self.safe_value(data[i], 'B', [])
|
1196
1190
|
rawBalances = self.array_concat(rawBalances, B)
|
1197
1191
|
info = rawBalances
|
1198
|
-
if topic == '
|
1199
|
-
rawBalances = self.safe_value(message, 'data', [])
|
1200
|
-
info = rawBalances
|
1201
|
-
if topic == 'user.wallet.unifiedAccount':
|
1192
|
+
if topic == 'wallet':
|
1202
1193
|
data = self.safe_value(message, 'data', {})
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1194
|
+
for i in range(0, len(data)):
|
1195
|
+
result = self.safe_value(data, 0, {})
|
1196
|
+
account = self.safe_string_lower(result, 'accountType')
|
1197
|
+
rawBalances = self.array_concat(rawBalances, self.safe_value(result, 'coin', []))
|
1198
|
+
info = data
|
1206
1199
|
for i in range(0, len(rawBalances)):
|
1207
|
-
self.parse_ws_balance(rawBalances[i])
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1200
|
+
self.parse_ws_balance(rawBalances[i], account)
|
1201
|
+
if account is not None:
|
1202
|
+
if self.safe_value(self.balance, account) is None:
|
1203
|
+
self.balance[account] = {}
|
1204
|
+
self.balance[account]['info'] = info
|
1205
|
+
timestamp = self.safe_integer(message, 'ts')
|
1206
|
+
self.balance[account]['timestamp'] = timestamp
|
1207
|
+
self.balance[account]['datetime'] = self.iso8601(timestamp)
|
1208
|
+
self.balance[account] = self.safe_balance(self.balance[account])
|
1209
|
+
messageHash = 'balances:' + account
|
1210
|
+
client.resolve(self.balance[account], messageHash)
|
1211
|
+
else:
|
1212
|
+
self.balance['info'] = info
|
1213
|
+
timestamp = self.safe_integer(message, 'ts')
|
1214
|
+
self.balance['timestamp'] = timestamp
|
1215
|
+
self.balance['datetime'] = self.iso8601(timestamp)
|
1216
|
+
self.balance = self.safe_balance(self.balance)
|
1217
|
+
messageHash = 'balances'
|
1218
|
+
client.resolve(self.balance, messageHash)
|
1215
1219
|
|
1216
|
-
def parse_ws_balance(self, balance):
|
1220
|
+
def parse_ws_balance(self, balance, accountType=None):
|
1217
1221
|
#
|
1218
1222
|
# spot
|
1219
1223
|
# {
|
@@ -1221,42 +1225,36 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
1221
1225
|
# "f": "176.81254174",
|
1222
1226
|
# "l": "201.575"
|
1223
1227
|
# }
|
1224
|
-
# contract
|
1225
|
-
# {
|
1226
|
-
# "coin": "USDT",
|
1227
|
-
# "equity": "610.3984319",
|
1228
|
-
# "walletBalance": "609.7384319",
|
1229
|
-
# "positionMargin": "4.7582882",
|
1230
|
-
# "availableBalance": "604.9801437",
|
1231
|
-
# "orderMargin": "0",
|
1232
|
-
# "unrealisedPnl": "0.66",
|
1233
|
-
# "cumRealisedPnl": "-0.2615681"
|
1234
|
-
# }
|
1235
1228
|
# unified
|
1236
|
-
#
|
1237
|
-
#
|
1238
|
-
#
|
1239
|
-
#
|
1240
|
-
#
|
1241
|
-
#
|
1242
|
-
#
|
1243
|
-
#
|
1244
|
-
#
|
1245
|
-
#
|
1246
|
-
#
|
1247
|
-
#
|
1248
|
-
#
|
1249
|
-
#
|
1250
|
-
#
|
1251
|
-
#
|
1229
|
+
# {
|
1230
|
+
# "coin": "BTC",
|
1231
|
+
# "equity": "0.06488393",
|
1232
|
+
# "usdValue": "1023.08402268",
|
1233
|
+
# "walletBalance": "0.06488393",
|
1234
|
+
# "availableToWithdraw": "0.06488393",
|
1235
|
+
# "availableToBorrow": "2.5",
|
1236
|
+
# "borrowAmount": "0",
|
1237
|
+
# "accruedInterest": "0",
|
1238
|
+
# "totalOrderIM": "0",
|
1239
|
+
# "totalPositionIM": "0",
|
1240
|
+
# "totalPositionMM": "0",
|
1241
|
+
# "unrealisedPnl": "0",
|
1242
|
+
# "cumRealisedPnl": "0",
|
1243
|
+
# "bonus": "0"
|
1244
|
+
# }
|
1252
1245
|
#
|
1253
1246
|
account = self.account()
|
1254
|
-
currencyId = self.
|
1247
|
+
currencyId = self.safe_string_2(balance, 'a', 'coin')
|
1255
1248
|
code = self.safe_currency_code(currencyId)
|
1256
|
-
account['free'] = self.safe_string_n(balance, ['
|
1257
|
-
account['used'] = self.
|
1249
|
+
account['free'] = self.safe_string_n(balance, ['availableToWithdraw', 'f', 'free', 'availableToWithdraw'])
|
1250
|
+
account['used'] = self.safe_string_2(balance, 'l', 'locked')
|
1258
1251
|
account['total'] = self.safe_string(balance, 'walletBalance')
|
1259
|
-
|
1252
|
+
if accountType is not None:
|
1253
|
+
if self.safe_value(self.balance, accountType) is None:
|
1254
|
+
self.balance[accountType] = {}
|
1255
|
+
self.balance[accountType][code] = account
|
1256
|
+
else:
|
1257
|
+
self.balance[code] = account
|
1260
1258
|
|
1261
1259
|
async def watch_topics(self, url, messageHash, topics=[], params={}):
|
1262
1260
|
request = {
|
@@ -1376,7 +1374,12 @@ class bybit(Exchange, ccxt.async_support.bybit):
|
|
1376
1374
|
'outboundAccountInfo': self.handle_balance,
|
1377
1375
|
'execution': self.handle_my_trades,
|
1378
1376
|
'ticketInfo': self.handle_my_trades,
|
1377
|
+
'user.openapi.perp.trade': self.handle_my_trades,
|
1379
1378
|
}
|
1379
|
+
exacMethod = self.safe_value(methods, topic)
|
1380
|
+
if exacMethod is not None:
|
1381
|
+
exacMethod(client, message)
|
1382
|
+
return
|
1380
1383
|
keys = list(methods.keys())
|
1381
1384
|
for i in range(0, len(keys)):
|
1382
1385
|
key = keys[i]
|