ccxt 4.4.88__py2.py3-none-any.whl → 4.4.91__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 -3
- ccxt/abstract/bitget.py +58 -0
- ccxt/abstract/bitrue.py +65 -65
- ccxt/abstract/cryptocom.py +2 -0
- ccxt/abstract/luno.py +1 -0
- ccxt/async_support/__init__.py +1 -3
- ccxt/async_support/base/exchange.py +6 -3
- ccxt/async_support/base/ws/client.py +173 -64
- ccxt/async_support/base/ws/future.py +23 -50
- ccxt/async_support/binance.py +2 -2
- ccxt/async_support/bingx.py +55 -29
- ccxt/async_support/bitget.py +469 -147
- ccxt/async_support/bitmex.py +2 -1
- ccxt/async_support/bitrue.py +72 -66
- ccxt/async_support/bitvavo.py +34 -0
- ccxt/async_support/btcalpha.py +35 -0
- ccxt/async_support/btcbox.py +35 -0
- ccxt/async_support/btcmarkets.py +35 -0
- ccxt/async_support/btcturk.py +35 -0
- ccxt/async_support/bybit.py +9 -3
- ccxt/async_support/cex.py +61 -0
- ccxt/async_support/coinbase.py +1 -3
- ccxt/async_support/cryptocom.py +66 -2
- ccxt/async_support/cryptomus.py +1 -1
- ccxt/async_support/delta.py +2 -2
- ccxt/async_support/digifinex.py +39 -99
- ccxt/async_support/exmo.py +14 -7
- ccxt/async_support/gate.py +14 -7
- ccxt/async_support/hashkey.py +15 -28
- ccxt/async_support/hollaex.py +27 -22
- ccxt/async_support/hyperliquid.py +104 -53
- ccxt/async_support/kraken.py +54 -50
- ccxt/async_support/luno.py +87 -1
- ccxt/async_support/mexc.py +1 -0
- ccxt/async_support/modetrade.py +2 -2
- ccxt/async_support/okx.py +2 -1
- ccxt/async_support/paradex.py +1 -1
- ccxt/async_support/phemex.py +16 -8
- ccxt/async_support/tradeogre.py +3 -3
- ccxt/async_support/xt.py +1 -1
- ccxt/base/exchange.py +20 -8
- ccxt/binance.py +2 -2
- ccxt/bingx.py +55 -29
- ccxt/bitget.py +469 -147
- ccxt/bitmex.py +2 -1
- ccxt/bitrue.py +72 -66
- ccxt/bitvavo.py +34 -0
- ccxt/btcalpha.py +35 -0
- ccxt/btcbox.py +35 -0
- ccxt/btcmarkets.py +35 -0
- ccxt/btcturk.py +35 -0
- ccxt/bybit.py +9 -3
- ccxt/cex.py +61 -0
- ccxt/coinbase.py +1 -3
- ccxt/cryptocom.py +66 -2
- ccxt/cryptomus.py +1 -1
- ccxt/delta.py +2 -2
- ccxt/digifinex.py +39 -99
- ccxt/exmo.py +13 -7
- ccxt/gate.py +14 -7
- ccxt/hashkey.py +15 -28
- ccxt/hollaex.py +27 -22
- ccxt/hyperliquid.py +104 -53
- ccxt/kraken.py +53 -50
- ccxt/luno.py +87 -1
- ccxt/mexc.py +1 -0
- ccxt/modetrade.py +2 -2
- ccxt/okx.py +2 -1
- ccxt/paradex.py +1 -1
- ccxt/phemex.py +16 -8
- ccxt/pro/__init__.py +1 -127
- ccxt/pro/bitstamp.py +1 -1
- ccxt/pro/bybit.py +6 -136
- ccxt/pro/coinbase.py +2 -0
- ccxt/pro/cryptocom.py +27 -0
- ccxt/pro/kraken.py +249 -267
- ccxt/pro/mexc.py +0 -1
- ccxt/tradeogre.py +3 -3
- ccxt/xt.py +1 -1
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/METADATA +64 -23
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/RECORD +84 -101
- ccxt/abstract/coinlist.py +0 -57
- ccxt/async_support/base/ws/aiohttp_client.py +0 -147
- ccxt/async_support/bitcoincom.py +0 -18
- ccxt/async_support/bitfinex1.py +0 -1711
- ccxt/async_support/bitpanda.py +0 -17
- ccxt/async_support/coinlist.py +0 -2542
- ccxt/async_support/poloniexfutures.py +0 -1875
- ccxt/bitcoincom.py +0 -18
- ccxt/bitfinex1.py +0 -1710
- ccxt/bitpanda.py +0 -17
- ccxt/coinlist.py +0 -2542
- ccxt/poloniexfutures.py +0 -1875
- ccxt/pro/bitcoincom.py +0 -35
- ccxt/pro/bitfinex1.py +0 -635
- ccxt/pro/bitpanda.py +0 -16
- ccxt/pro/poloniexfutures.py +0 -1004
- ccxt/pro/wazirx.py +0 -766
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/WHEEL +0 -0
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/top_level.txt +0 -0
ccxt/pro/bitcoincom.py
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
|
-
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
4
|
-
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
5
|
-
|
6
|
-
from ccxt.pro.hitbtc import hitbtc
|
7
|
-
from ccxt.base.types import Any
|
8
|
-
|
9
|
-
import ccxt.async_support.hitbtc as hitbtcRest
|
10
|
-
|
11
|
-
import ccxt.async_support.bitcoincom as bitcoincomRest
|
12
|
-
|
13
|
-
|
14
|
-
class bitcoincom(hitbtc):
|
15
|
-
|
16
|
-
def describe(self) -> Any:
|
17
|
-
# eslint-disable-next-line new-cap
|
18
|
-
describeExtended = self.get_describe_for_extended_ws_exchange(bitcoincomRest(), hitbtcRest(), super(bitcoincom, self).describe())
|
19
|
-
return self.deep_extend(describeExtended, {
|
20
|
-
'id': 'bitcoincom',
|
21
|
-
'name': 'bitcoin.com',
|
22
|
-
'countries': ['KN'],
|
23
|
-
'urls': {
|
24
|
-
'logo': 'https://user-images.githubusercontent.com/1294454/97296144-514fa300-1861-11eb-952b-3d55d492200b.jpg',
|
25
|
-
'api': {
|
26
|
-
'ws': 'wss://api.fmfw.io/api/2/ws',
|
27
|
-
},
|
28
|
-
},
|
29
|
-
'fees': {
|
30
|
-
'trading': {
|
31
|
-
'maker': self.parse_number('0.0015'),
|
32
|
-
'taker': self.parse_number('0.002'),
|
33
|
-
},
|
34
|
-
},
|
35
|
-
})
|
ccxt/pro/bitfinex1.py
DELETED
@@ -1,635 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
|
-
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
4
|
-
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
5
|
-
|
6
|
-
import ccxt.async_support
|
7
|
-
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById
|
8
|
-
import hashlib
|
9
|
-
from ccxt.base.types import Any, Int, Order, OrderBook, Str, Ticker, Trade
|
10
|
-
from ccxt.async_support.base.ws.client import Client
|
11
|
-
from typing import List
|
12
|
-
from ccxt.base.errors import ExchangeError
|
13
|
-
from ccxt.base.errors import AuthenticationError
|
14
|
-
from ccxt.base.precise import Precise
|
15
|
-
|
16
|
-
|
17
|
-
class bitfinex1(ccxt.async_support.bitfinex1):
|
18
|
-
|
19
|
-
def describe(self) -> Any:
|
20
|
-
return self.deep_extend(super(bitfinex1, self).describe(), {
|
21
|
-
'has': {
|
22
|
-
'ws': True,
|
23
|
-
'watchTicker': True,
|
24
|
-
'watchTickers': False,
|
25
|
-
'watchOrderBook': True,
|
26
|
-
'watchTrades': True,
|
27
|
-
'watchTradesForSymbols': False,
|
28
|
-
'watchBalance': False, # for now
|
29
|
-
'watchOHLCV': False, # missing on the exchange side in v1
|
30
|
-
},
|
31
|
-
'urls': {
|
32
|
-
'api': {
|
33
|
-
'ws': {
|
34
|
-
'public': 'wss://api-pub.bitfinex.com/ws/1',
|
35
|
-
'private': 'wss://api.bitfinex.com/ws/1',
|
36
|
-
},
|
37
|
-
},
|
38
|
-
},
|
39
|
-
'options': {
|
40
|
-
'watchOrderBook': {
|
41
|
-
'prec': 'P0',
|
42
|
-
'freq': 'F0',
|
43
|
-
},
|
44
|
-
'ordersLimit': 1000,
|
45
|
-
},
|
46
|
-
})
|
47
|
-
|
48
|
-
async def subscribe(self, channel, symbol, params={}):
|
49
|
-
await self.load_markets()
|
50
|
-
market = self.market(symbol)
|
51
|
-
marketId = market['id']
|
52
|
-
url = self.urls['api']['ws']['public']
|
53
|
-
messageHash = channel + ':' + marketId
|
54
|
-
# channel = 'trades'
|
55
|
-
request: dict = {
|
56
|
-
'event': 'subscribe',
|
57
|
-
'channel': channel,
|
58
|
-
'symbol': marketId,
|
59
|
-
'messageHash': messageHash,
|
60
|
-
}
|
61
|
-
return await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
|
62
|
-
|
63
|
-
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
64
|
-
"""
|
65
|
-
get the list of most recent trades for a particular symbol
|
66
|
-
|
67
|
-
https://docs.bitfinex.com/v1/reference/ws-public-trades
|
68
|
-
|
69
|
-
:param str symbol: unified symbol of the market to fetch trades for
|
70
|
-
:param int [since]: timestamp in ms of the earliest trade to fetch
|
71
|
-
:param int [limit]: the maximum amount of trades to fetch
|
72
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
73
|
-
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
74
|
-
"""
|
75
|
-
await self.load_markets()
|
76
|
-
symbol = self.symbol(symbol)
|
77
|
-
trades = await self.subscribe('trades', symbol, params)
|
78
|
-
if self.newUpdates:
|
79
|
-
limit = trades.getLimit(symbol, limit)
|
80
|
-
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
81
|
-
|
82
|
-
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
83
|
-
"""
|
84
|
-
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
85
|
-
|
86
|
-
https://docs.bitfinex.com/v1/reference/ws-public-ticker
|
87
|
-
|
88
|
-
:param str symbol: unified symbol of the market to fetch the ticker for
|
89
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
90
|
-
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
91
|
-
"""
|
92
|
-
return await self.subscribe('ticker', symbol, params)
|
93
|
-
|
94
|
-
def handle_trades(self, client: Client, message, subscription):
|
95
|
-
#
|
96
|
-
# initial snapshot
|
97
|
-
#
|
98
|
-
# [
|
99
|
-
# 2,
|
100
|
-
# [
|
101
|
-
# [null, 1580565020, 9374.9, 0.005],
|
102
|
-
# [null, 1580565004, 9374.9, 0.005],
|
103
|
-
# [null, 1580565003, 9374.9, 0.005],
|
104
|
-
# ]
|
105
|
-
# ]
|
106
|
-
#
|
107
|
-
# when a trade does not have an id yet
|
108
|
-
#
|
109
|
-
# # channel id, update type, seq, time, price, amount
|
110
|
-
# [2, "te", "28462857-BTCUSD", 1580565041, 9374.9, 0.005],
|
111
|
-
#
|
112
|
-
# when a trade already has an id
|
113
|
-
#
|
114
|
-
# # channel id, update type, seq, trade id, time, price, amount
|
115
|
-
# [2, "tu", "28462857-BTCUSD", 413357662, 1580565041, 9374.9, 0.005]
|
116
|
-
#
|
117
|
-
channel = self.safe_value(subscription, 'channel')
|
118
|
-
marketId = self.safe_string(subscription, 'pair')
|
119
|
-
messageHash = channel + ':' + marketId
|
120
|
-
tradesLimit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
121
|
-
market = self.safe_market(marketId)
|
122
|
-
symbol = market['symbol']
|
123
|
-
data = self.safe_value(message, 1)
|
124
|
-
stored = self.safe_value(self.trades, symbol)
|
125
|
-
if stored is None:
|
126
|
-
stored = ArrayCache(tradesLimit)
|
127
|
-
self.trades[symbol] = stored
|
128
|
-
if isinstance(data, list):
|
129
|
-
trades = self.parse_trades(data, market)
|
130
|
-
for i in range(0, len(trades)):
|
131
|
-
stored.append(trades[i])
|
132
|
-
else:
|
133
|
-
second = self.safe_string(message, 1)
|
134
|
-
if second != 'tu':
|
135
|
-
return
|
136
|
-
trade = self.parse_trade(message, market)
|
137
|
-
stored.append(trade)
|
138
|
-
client.resolve(stored, messageHash)
|
139
|
-
|
140
|
-
def parse_trade(self, trade, market=None) -> Trade:
|
141
|
-
#
|
142
|
-
# snapshot trade
|
143
|
-
#
|
144
|
-
# # null, time, price, amount
|
145
|
-
# [null, 1580565020, 9374.9, 0.005],
|
146
|
-
#
|
147
|
-
# when a trade does not have an id yet
|
148
|
-
#
|
149
|
-
# # channel id, update type, seq, time, price, amount
|
150
|
-
# [2, "te", "28462857-BTCUSD", 1580565041, 9374.9, 0.005],
|
151
|
-
#
|
152
|
-
# when a trade already has an id
|
153
|
-
#
|
154
|
-
# # channel id, update type, seq, trade id, time, price, amount
|
155
|
-
# [2, "tu", "28462857-BTCUSD", 413357662, 1580565041, 9374.9, 0.005]
|
156
|
-
#
|
157
|
-
if not isinstance(trade, list):
|
158
|
-
return super(bitfinex1, self).parse_trade(trade, market)
|
159
|
-
tradeLength = len(trade)
|
160
|
-
event = self.safe_string(trade, 1)
|
161
|
-
id = None
|
162
|
-
if event == 'tu':
|
163
|
-
id = self.safe_string(trade, tradeLength - 4)
|
164
|
-
timestamp = self.safe_timestamp(trade, tradeLength - 3)
|
165
|
-
price = self.safe_string(trade, tradeLength - 2)
|
166
|
-
amount = self.safe_string(trade, tradeLength - 1)
|
167
|
-
side = None
|
168
|
-
if amount is not None:
|
169
|
-
side = 'buy' if Precise.string_gt(amount, '0') else 'sell'
|
170
|
-
amount = Precise.string_abs(amount)
|
171
|
-
seq = self.safe_string(trade, 2)
|
172
|
-
parts = seq.split('-')
|
173
|
-
marketId = self.safe_string(parts, 1)
|
174
|
-
if marketId is not None:
|
175
|
-
marketId = marketId.replace('t', '')
|
176
|
-
symbol = self.safe_symbol(marketId, market)
|
177
|
-
takerOrMaker = None
|
178
|
-
orderId = None
|
179
|
-
return self.safe_trade({
|
180
|
-
'info': trade,
|
181
|
-
'timestamp': timestamp,
|
182
|
-
'datetime': self.iso8601(timestamp),
|
183
|
-
'symbol': symbol,
|
184
|
-
'id': id,
|
185
|
-
'order': orderId,
|
186
|
-
'type': None,
|
187
|
-
'takerOrMaker': takerOrMaker,
|
188
|
-
'side': side,
|
189
|
-
'price': price,
|
190
|
-
'amount': amount,
|
191
|
-
'cost': None,
|
192
|
-
'fee': None,
|
193
|
-
})
|
194
|
-
|
195
|
-
def handle_ticker(self, client: Client, message, subscription):
|
196
|
-
#
|
197
|
-
# [
|
198
|
-
# 2, # 0 CHANNEL_ID integer Channel ID
|
199
|
-
# 236.62, # 1 BID float Price of last highest bid
|
200
|
-
# 9.0029, # 2 BID_SIZE float Size of the last highest bid
|
201
|
-
# 236.88, # 3 ASK float Price of last lowest ask
|
202
|
-
# 7.1138, # 4 ASK_SIZE float Size of the last lowest ask
|
203
|
-
# -1.02, # 5 DAILY_CHANGE float Amount that the last price has changed since yesterday
|
204
|
-
# 0, # 6 DAILY_CHANGE_PERC float Amount that the price has changed expressed in percentage terms
|
205
|
-
# 236.52, # 7 LAST_PRICE float Price of the last trade.
|
206
|
-
# 5191.36754297, # 8 VOLUME float Daily volume
|
207
|
-
# 250.01, # 9 HIGH float Daily high
|
208
|
-
# 220.05, # 10 LOW float Daily low
|
209
|
-
# ]
|
210
|
-
#
|
211
|
-
marketId = self.safe_string(subscription, 'pair')
|
212
|
-
symbol = self.safe_symbol(marketId)
|
213
|
-
channel = 'ticker'
|
214
|
-
messageHash = channel + ':' + marketId
|
215
|
-
last = self.safe_string(message, 7)
|
216
|
-
change = self.safe_string(message, 5)
|
217
|
-
open = None
|
218
|
-
if (last is not None) and (change is not None):
|
219
|
-
open = Precise.string_sub(last, change)
|
220
|
-
result = self.safe_ticker({
|
221
|
-
'symbol': symbol,
|
222
|
-
'timestamp': None,
|
223
|
-
'datetime': None,
|
224
|
-
'high': self.safe_string(message, 9),
|
225
|
-
'low': self.safe_string(message, 10),
|
226
|
-
'bid': self.safe_string(message, 1),
|
227
|
-
'bidVolume': None,
|
228
|
-
'ask': self.safe_string(message, 3),
|
229
|
-
'askVolume': None,
|
230
|
-
'vwap': None,
|
231
|
-
'open': self.parse_number(open),
|
232
|
-
'close': self.parse_number(last),
|
233
|
-
'last': self.parse_number(last),
|
234
|
-
'previousClose': None,
|
235
|
-
'change': self.parse_number(change),
|
236
|
-
'percentage': self.safe_string(message, 6),
|
237
|
-
'average': None,
|
238
|
-
'baseVolume': self.safe_string(message, 8),
|
239
|
-
'quoteVolume': None,
|
240
|
-
'info': message,
|
241
|
-
})
|
242
|
-
self.tickers[symbol] = result
|
243
|
-
client.resolve(result, messageHash)
|
244
|
-
|
245
|
-
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
246
|
-
"""
|
247
|
-
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
248
|
-
|
249
|
-
https://docs.bitfinex.com/v1/reference/ws-public-order-books
|
250
|
-
|
251
|
-
:param str symbol: unified symbol of the market to fetch the order book for
|
252
|
-
:param int [limit]: the maximum amount of order book entries to return
|
253
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
254
|
-
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
255
|
-
"""
|
256
|
-
if limit is not None:
|
257
|
-
if (limit != 25) and (limit != 100):
|
258
|
-
raise ExchangeError(self.id + ' watchOrderBook limit argument must be None, 25 or 100')
|
259
|
-
options = self.safe_value(self.options, 'watchOrderBook', {})
|
260
|
-
prec = self.safe_string(options, 'prec', 'P0')
|
261
|
-
freq = self.safe_string(options, 'freq', 'F0')
|
262
|
-
request: dict = {
|
263
|
-
# "event": "subscribe", # added in subscribe()
|
264
|
-
# "channel": channel, # added in subscribe()
|
265
|
-
# "symbol": marketId, # added in subscribe()
|
266
|
-
'prec': prec, # string, level of price aggregation, 'P0', 'P1', 'P2', 'P3', 'P4', default P0
|
267
|
-
'freq': freq, # string, frequency of updates 'F0' = realtime, 'F1' = 2 seconds, default is 'F0'
|
268
|
-
'len': limit, # string, number of price points, '25', '100', default = '25'
|
269
|
-
}
|
270
|
-
orderbook = await self.subscribe('book', symbol, self.deep_extend(request, params))
|
271
|
-
return orderbook.limit()
|
272
|
-
|
273
|
-
def handle_order_book(self, client: Client, message, subscription):
|
274
|
-
#
|
275
|
-
# first message(snapshot)
|
276
|
-
#
|
277
|
-
# [
|
278
|
-
# 18691, # channel id
|
279
|
-
# [
|
280
|
-
# [7364.8, 10, 4.354802], # price, count, size > 0 = bid
|
281
|
-
# [7364.7, 1, 0.00288831],
|
282
|
-
# [7364.3, 12, 0.048],
|
283
|
-
# [7364.9, 3, -0.42028976], # price, count, size < 0 = ask
|
284
|
-
# [7365, 1, -0.25],
|
285
|
-
# [7365.5, 1, -0.00371937],
|
286
|
-
# ]
|
287
|
-
# ]
|
288
|
-
#
|
289
|
-
# subsequent updates
|
290
|
-
#
|
291
|
-
# [
|
292
|
-
# 30, # channel id
|
293
|
-
# 9339.9, # price
|
294
|
-
# 0, # count
|
295
|
-
# -1, # size > 0 = bid, size < 0 = ask
|
296
|
-
# ]
|
297
|
-
#
|
298
|
-
marketId = self.safe_string(subscription, 'pair')
|
299
|
-
symbol = self.safe_symbol(marketId)
|
300
|
-
channel = 'book'
|
301
|
-
messageHash = channel + ':' + marketId
|
302
|
-
prec = self.safe_string(subscription, 'prec', 'P0')
|
303
|
-
isRaw = (prec == 'R0')
|
304
|
-
# if it is an initial snapshot
|
305
|
-
if isinstance(message[1], list):
|
306
|
-
limit = self.safe_integer(subscription, 'len')
|
307
|
-
if isRaw:
|
308
|
-
# raw order books
|
309
|
-
self.orderbooks[symbol] = self.indexed_order_book({}, limit)
|
310
|
-
else:
|
311
|
-
# P0, P1, P2, P3, P4
|
312
|
-
self.orderbooks[symbol] = self.counted_order_book({}, limit)
|
313
|
-
orderbook = self.orderbooks[symbol]
|
314
|
-
if isRaw:
|
315
|
-
deltas = message[1]
|
316
|
-
for i in range(0, len(deltas)):
|
317
|
-
delta = deltas[i]
|
318
|
-
id = self.safe_string(delta, 0)
|
319
|
-
price = self.safe_float(delta, 1)
|
320
|
-
delta2Value = delta[2]
|
321
|
-
size = -delta2Value if (delta2Value < 0) else delta2Value
|
322
|
-
side = 'asks' if (delta2Value < 0) else 'bids'
|
323
|
-
bookside = orderbook[side]
|
324
|
-
bookside.storeArray([price, size, id])
|
325
|
-
else:
|
326
|
-
deltas = message[1]
|
327
|
-
for i in range(0, len(deltas)):
|
328
|
-
delta = deltas[i]
|
329
|
-
delta2 = delta[2]
|
330
|
-
size = -delta2 if (delta2 < 0) else delta2
|
331
|
-
side = 'asks' if (delta2 < 0) else 'bids'
|
332
|
-
countedBookSide = orderbook[side]
|
333
|
-
countedBookSide.storeArray([delta[0], size, delta[1]])
|
334
|
-
client.resolve(orderbook, messageHash)
|
335
|
-
else:
|
336
|
-
orderbook = self.orderbooks[symbol]
|
337
|
-
if isRaw:
|
338
|
-
id = self.safe_string(message, 1)
|
339
|
-
price = self.safe_string(message, 2)
|
340
|
-
message3 = message[3]
|
341
|
-
size = -message3 if (message3 < 0) else message3
|
342
|
-
side = 'asks' if (message3 < 0) else 'bids'
|
343
|
-
bookside = orderbook[side]
|
344
|
-
# price = 0 means that you have to remove the order from your book
|
345
|
-
amount = size if Precise.string_gt(price, '0') else '0'
|
346
|
-
bookside.storeArray([self.parse_number(price), self.parse_number(amount), id])
|
347
|
-
else:
|
348
|
-
message3Value = message[3]
|
349
|
-
size = -message3Value if (message3Value < 0) else message3Value
|
350
|
-
side = 'asks' if (message3Value < 0) else 'bids'
|
351
|
-
countedBookSide = orderbook[side]
|
352
|
-
countedBookSide.storeArray([message[1], size, message[2]])
|
353
|
-
client.resolve(orderbook, messageHash)
|
354
|
-
|
355
|
-
def handle_heartbeat(self, client: Client, message):
|
356
|
-
#
|
357
|
-
# every second(approx) if no other updates are sent
|
358
|
-
#
|
359
|
-
# {"event": "heartbeat"}
|
360
|
-
#
|
361
|
-
event = self.safe_string(message, 'event')
|
362
|
-
client.resolve(message, event)
|
363
|
-
|
364
|
-
def handle_system_status(self, client: Client, message):
|
365
|
-
#
|
366
|
-
# todo: answer the question whether handleSystemStatus should be renamed
|
367
|
-
# and unified for any usage pattern that
|
368
|
-
# involves system status and maintenance updates
|
369
|
-
#
|
370
|
-
# {
|
371
|
-
# "event": "info",
|
372
|
-
# "version": 2,
|
373
|
-
# "serverId": "e293377e-7bb7-427e-b28c-5db045b2c1d1",
|
374
|
-
# "platform": {status: 1}, # 1 for operative, 0 for maintenance
|
375
|
-
# }
|
376
|
-
#
|
377
|
-
return message
|
378
|
-
|
379
|
-
def handle_subscription_status(self, client: Client, message):
|
380
|
-
#
|
381
|
-
# {
|
382
|
-
# "event": "subscribed",
|
383
|
-
# "channel": "book",
|
384
|
-
# "chanId": 67473,
|
385
|
-
# "symbol": "tBTCUSD",
|
386
|
-
# "prec": "P0",
|
387
|
-
# "freq": "F0",
|
388
|
-
# "len": "25",
|
389
|
-
# "pair": "BTCUSD"
|
390
|
-
# }
|
391
|
-
#
|
392
|
-
channelId = self.safe_string(message, 'chanId')
|
393
|
-
client.subscriptions[channelId] = message
|
394
|
-
return message
|
395
|
-
|
396
|
-
async def authenticate(self, params={}):
|
397
|
-
url = self.urls['api']['ws']['private']
|
398
|
-
client = self.client(url)
|
399
|
-
future = client.future('authenticated')
|
400
|
-
method = 'auth'
|
401
|
-
authenticated = self.safe_value(client.subscriptions, method)
|
402
|
-
if authenticated is None:
|
403
|
-
nonce = self.milliseconds()
|
404
|
-
payload = 'AUTH' + str(nonce)
|
405
|
-
signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha384, 'hex')
|
406
|
-
request: dict = {
|
407
|
-
'apiKey': self.apiKey,
|
408
|
-
'authSig': signature,
|
409
|
-
'authNonce': nonce,
|
410
|
-
'authPayload': payload,
|
411
|
-
'event': method,
|
412
|
-
'filter': [
|
413
|
-
'trading',
|
414
|
-
'wallet',
|
415
|
-
],
|
416
|
-
}
|
417
|
-
self.spawn(self.watch, url, method, request, 1)
|
418
|
-
return await future
|
419
|
-
|
420
|
-
def handle_authentication_message(self, client: Client, message):
|
421
|
-
status = self.safe_string(message, 'status')
|
422
|
-
if status == 'OK':
|
423
|
-
# we resolve the future here permanently so authentication only happens once
|
424
|
-
future = self.safe_value(client.futures, 'authenticated')
|
425
|
-
future.resolve(True)
|
426
|
-
else:
|
427
|
-
error = AuthenticationError(self.json(message))
|
428
|
-
client.reject(error, 'authenticated')
|
429
|
-
# allows further authentication attempts
|
430
|
-
method = self.safe_string(message, 'event')
|
431
|
-
if method in client.subscriptions:
|
432
|
-
del client.subscriptions[method]
|
433
|
-
|
434
|
-
async def watch_order(self, id, symbol: Str = None, params={}):
|
435
|
-
await self.load_markets()
|
436
|
-
url = self.urls['api']['ws']['private']
|
437
|
-
await self.authenticate()
|
438
|
-
return await self.watch(url, id, None, 1)
|
439
|
-
|
440
|
-
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
441
|
-
"""
|
442
|
-
watches information on multiple orders made by the user
|
443
|
-
|
444
|
-
https://docs.bitfinex.com/v1/reference/ws-auth-order-updates
|
445
|
-
https://docs.bitfinex.com/v1/reference/ws-auth-order-snapshots
|
446
|
-
|
447
|
-
:param str symbol: unified market symbol of the market orders were made in
|
448
|
-
:param int [since]: the earliest time in ms to fetch orders for
|
449
|
-
:param int [limit]: the maximum number of order structures to retrieve
|
450
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
451
|
-
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
452
|
-
"""
|
453
|
-
await self.load_markets()
|
454
|
-
await self.authenticate()
|
455
|
-
if symbol is not None:
|
456
|
-
symbol = self.symbol(symbol)
|
457
|
-
url = self.urls['api']['ws']['private']
|
458
|
-
orders = await self.watch(url, 'os', None, 1)
|
459
|
-
if self.newUpdates:
|
460
|
-
limit = orders.getLimit(symbol, limit)
|
461
|
-
return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
|
462
|
-
|
463
|
-
def handle_orders(self, client: Client, message, subscription):
|
464
|
-
#
|
465
|
-
# order snapshot
|
466
|
-
#
|
467
|
-
# [
|
468
|
-
# 0,
|
469
|
-
# "os",
|
470
|
-
# [
|
471
|
-
# [
|
472
|
-
# 45287766631,
|
473
|
-
# "ETHUST",
|
474
|
-
# -0.07,
|
475
|
-
# -0.07,
|
476
|
-
# "EXCHANGE LIMIT",
|
477
|
-
# "ACTIVE",
|
478
|
-
# 210,
|
479
|
-
# 0,
|
480
|
-
# "2020-05-16T13:17:46Z",
|
481
|
-
# 0,
|
482
|
-
# 0,
|
483
|
-
# 0
|
484
|
-
# ]
|
485
|
-
# ]
|
486
|
-
# ]
|
487
|
-
#
|
488
|
-
# order cancel
|
489
|
-
#
|
490
|
-
# [
|
491
|
-
# 0,
|
492
|
-
# "oc",
|
493
|
-
# [
|
494
|
-
# 45287766631,
|
495
|
-
# "ETHUST",
|
496
|
-
# -0.07,
|
497
|
-
# -0.07,
|
498
|
-
# "EXCHANGE LIMIT",
|
499
|
-
# "CANCELED",
|
500
|
-
# 210,
|
501
|
-
# 0,
|
502
|
-
# "2020-05-16T13:17:46Z",
|
503
|
-
# 0,
|
504
|
-
# 0,
|
505
|
-
# 0,
|
506
|
-
# ]
|
507
|
-
# ]
|
508
|
-
#
|
509
|
-
data = self.safe_value(message, 2, [])
|
510
|
-
messageType = self.safe_string(message, 1)
|
511
|
-
if messageType == 'os':
|
512
|
-
for i in range(0, len(data)):
|
513
|
-
value = data[i]
|
514
|
-
self.handle_order(client, value)
|
515
|
-
else:
|
516
|
-
self.handle_order(client, data)
|
517
|
-
if self.orders is not None:
|
518
|
-
client.resolve(self.orders, 'os')
|
519
|
-
|
520
|
-
def parse_ws_order_status(self, status):
|
521
|
-
statuses: dict = {
|
522
|
-
'ACTIVE': 'open',
|
523
|
-
'CANCELED': 'canceled',
|
524
|
-
}
|
525
|
-
return self.safe_string(statuses, status, status)
|
526
|
-
|
527
|
-
def handle_order(self, client: Client, order):
|
528
|
-
# [45287766631,
|
529
|
-
# "ETHUST",
|
530
|
-
# -0.07,
|
531
|
-
# -0.07,
|
532
|
-
# "EXCHANGE LIMIT",
|
533
|
-
# "CANCELED",
|
534
|
-
# 210,
|
535
|
-
# 0,
|
536
|
-
# "2020-05-16T13:17:46Z",
|
537
|
-
# 0,
|
538
|
-
# 0,
|
539
|
-
# 0]
|
540
|
-
id = self.safe_string(order, 0)
|
541
|
-
marketId = self.safe_string(order, 1)
|
542
|
-
symbol = self.safe_symbol(marketId)
|
543
|
-
amount = self.safe_string(order, 2)
|
544
|
-
remaining = self.safe_string(order, 3)
|
545
|
-
side = 'buy'
|
546
|
-
if Precise.string_lt(amount, '0'):
|
547
|
-
amount = Precise.string_abs(amount)
|
548
|
-
remaining = Precise.string_abs(remaining)
|
549
|
-
side = 'sell'
|
550
|
-
type = self.safe_string(order, 4)
|
551
|
-
if type.find('LIMIT') > -1:
|
552
|
-
type = 'limit'
|
553
|
-
elif type.find('MARKET') > -1:
|
554
|
-
type = 'market'
|
555
|
-
status = self.parse_ws_order_status(self.safe_string(order, 5))
|
556
|
-
price = self.safe_string(order, 6)
|
557
|
-
rawDatetime = self.safe_string(order, 8)
|
558
|
-
timestamp = self.parse8601(rawDatetime)
|
559
|
-
parsed = self.safe_order({
|
560
|
-
'info': order,
|
561
|
-
'id': id,
|
562
|
-
'clientOrderId': None,
|
563
|
-
'timestamp': timestamp,
|
564
|
-
'datetime': self.iso8601(timestamp),
|
565
|
-
'lastTradeTimestamp': None,
|
566
|
-
'symbol': symbol,
|
567
|
-
'type': type,
|
568
|
-
'side': side,
|
569
|
-
'price': price,
|
570
|
-
'stopPrice': None,
|
571
|
-
'triggerPrice': None,
|
572
|
-
'average': None,
|
573
|
-
'amount': amount,
|
574
|
-
'remaining': remaining,
|
575
|
-
'filled': None,
|
576
|
-
'status': status,
|
577
|
-
'fee': None,
|
578
|
-
'cost': None,
|
579
|
-
'trades': None,
|
580
|
-
})
|
581
|
-
if self.orders is None:
|
582
|
-
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
583
|
-
self.orders = ArrayCacheBySymbolById(limit)
|
584
|
-
orders = self.orders
|
585
|
-
orders.append(parsed)
|
586
|
-
client.resolve(parsed, id)
|
587
|
-
return parsed
|
588
|
-
|
589
|
-
def handle_message(self, client: Client, message):
|
590
|
-
if isinstance(message, list):
|
591
|
-
channelId = self.safe_string(message, 0)
|
592
|
-
#
|
593
|
-
# [
|
594
|
-
# 1231,
|
595
|
-
# "hb",
|
596
|
-
# ]
|
597
|
-
#
|
598
|
-
if message[1] == 'hb':
|
599
|
-
return # skip heartbeats within subscription channels for now
|
600
|
-
subscription = self.safe_value(client.subscriptions, channelId, {})
|
601
|
-
channel = self.safe_string(subscription, 'channel')
|
602
|
-
name = self.safe_string(message, 1)
|
603
|
-
methods: dict = {
|
604
|
-
'book': self.handle_order_book,
|
605
|
-
# 'ohlc': self.handleOHLCV,
|
606
|
-
'ticker': self.handle_ticker,
|
607
|
-
'trades': self.handle_trades,
|
608
|
-
'os': self.handle_orders,
|
609
|
-
'on': self.handle_orders,
|
610
|
-
'oc': self.handle_orders,
|
611
|
-
}
|
612
|
-
method = self.safe_value_2(methods, channel, name)
|
613
|
-
if method is not None:
|
614
|
-
method(client, message, subscription)
|
615
|
-
else:
|
616
|
-
# todo add bitfinex handleErrorMessage
|
617
|
-
#
|
618
|
-
# {
|
619
|
-
# "event": "info",
|
620
|
-
# "version": 2,
|
621
|
-
# "serverId": "e293377e-7bb7-427e-b28c-5db045b2c1d1",
|
622
|
-
# "platform": {status: 1}, # 1 for operative, 0 for maintenance
|
623
|
-
# }
|
624
|
-
#
|
625
|
-
event = self.safe_string(message, 'event')
|
626
|
-
if event is not None:
|
627
|
-
methods: dict = {
|
628
|
-
'info': self.handle_system_status,
|
629
|
-
# 'book': 'handleOrderBook',
|
630
|
-
'subscribed': self.handle_subscription_status,
|
631
|
-
'auth': self.handle_authentication_message,
|
632
|
-
}
|
633
|
-
method = self.safe_value(methods, event)
|
634
|
-
if method is not None:
|
635
|
-
method(client, message)
|
ccxt/pro/bitpanda.py
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
|
-
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
4
|
-
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
5
|
-
|
6
|
-
from ccxt.pro.onetrading import onetrading
|
7
|
-
from ccxt.base.types import Any
|
8
|
-
|
9
|
-
|
10
|
-
class bitpanda(onetrading):
|
11
|
-
|
12
|
-
def describe(self) -> Any:
|
13
|
-
return self.deep_extend(super(bitpanda, self).describe(), {
|
14
|
-
'alias': True,
|
15
|
-
'id': 'bitpanda',
|
16
|
-
})
|