ccxt 4.2.82__py2.py3-none-any.whl → 4.2.84__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.

Files changed (191) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bitstamp.py +1 -1
  3. ccxt/abstract/bybit.py +1 -1
  4. ccxt/ace.py +1 -1
  5. ccxt/alpaca.py +1 -1
  6. ccxt/ascendex.py +1 -1
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/ace.py +1 -1
  9. ccxt/async_support/alpaca.py +1 -1
  10. ccxt/async_support/ascendex.py +1 -1
  11. ccxt/async_support/base/exchange.py +1 -1
  12. ccxt/async_support/bigone.py +1 -1
  13. ccxt/async_support/binance.py +1 -1
  14. ccxt/async_support/bingx.py +1 -1
  15. ccxt/async_support/bitbank.py +1 -1
  16. ccxt/async_support/bitbns.py +1 -1
  17. ccxt/async_support/bitfinex.py +1 -1
  18. ccxt/async_support/bitfinex2.py +1 -1
  19. ccxt/async_support/bitflyer.py +1 -1
  20. ccxt/async_support/bitget.py +12 -5
  21. ccxt/async_support/bithumb.py +2 -1
  22. ccxt/async_support/bitmart.py +1 -1
  23. ccxt/async_support/bitmex.py +1 -1
  24. ccxt/async_support/bitopro.py +1 -1
  25. ccxt/async_support/bitrue.py +1 -1
  26. ccxt/async_support/bitso.py +1 -1
  27. ccxt/async_support/bitstamp.py +43 -16
  28. ccxt/async_support/bitteam.py +1 -1
  29. ccxt/async_support/bitvavo.py +1 -1
  30. ccxt/async_support/blockchaincom.py +1 -1
  31. ccxt/async_support/blofin.py +1 -1
  32. ccxt/async_support/btcalpha.py +1 -1
  33. ccxt/async_support/btcmarkets.py +1 -1
  34. ccxt/async_support/btcturk.py +1 -1
  35. ccxt/async_support/bybit.py +5 -5
  36. ccxt/async_support/cex.py +1 -1
  37. ccxt/async_support/coinbase.py +1 -1
  38. ccxt/async_support/coinbaseinternational.py +1 -1
  39. ccxt/async_support/coinbasepro.py +1 -1
  40. ccxt/async_support/coinex.py +2 -3
  41. ccxt/async_support/coinlist.py +1 -1
  42. ccxt/async_support/coinmate.py +1 -1
  43. ccxt/async_support/coinmetro.py +1 -1
  44. ccxt/async_support/coinone.py +1 -1
  45. ccxt/async_support/coinsph.py +1 -1
  46. ccxt/async_support/cryptocom.py +1 -1
  47. ccxt/async_support/currencycom.py +1 -1
  48. ccxt/async_support/delta.py +1 -1
  49. ccxt/async_support/deribit.py +17 -2
  50. ccxt/async_support/digifinex.py +1 -1
  51. ccxt/async_support/exmo.py +1 -1
  52. ccxt/async_support/gate.py +1 -1
  53. ccxt/async_support/gemini.py +2 -1
  54. ccxt/async_support/hitbtc.py +1 -1
  55. ccxt/async_support/hollaex.py +1 -1
  56. ccxt/async_support/htx.py +6 -28
  57. ccxt/async_support/huobijp.py +1 -1
  58. ccxt/async_support/hyperliquid.py +6 -5
  59. ccxt/async_support/idex.py +1 -1
  60. ccxt/async_support/independentreserve.py +1 -1
  61. ccxt/async_support/indodax.py +1 -1
  62. ccxt/async_support/kraken.py +1 -1
  63. ccxt/async_support/krakenfutures.py +1 -1
  64. ccxt/async_support/kucoin.py +11 -2
  65. ccxt/async_support/kucoinfutures.py +147 -10
  66. ccxt/async_support/kuna.py +1 -1
  67. ccxt/async_support/latoken.py +1 -1
  68. ccxt/async_support/lbank.py +1 -1
  69. ccxt/async_support/luno.py +1 -1
  70. ccxt/async_support/lykke.py +1 -1
  71. ccxt/async_support/mercado.py +1 -1
  72. ccxt/async_support/mexc.py +1 -1
  73. ccxt/async_support/ndax.py +1 -1
  74. ccxt/async_support/novadax.py +1 -1
  75. ccxt/async_support/oceanex.py +1 -1
  76. ccxt/async_support/okcoin.py +1 -1
  77. ccxt/async_support/okx.py +1 -1
  78. ccxt/async_support/onetrading.py +1 -1
  79. ccxt/async_support/p2b.py +1 -1
  80. ccxt/async_support/phemex.py +1 -1
  81. ccxt/async_support/poloniex.py +1 -1
  82. ccxt/async_support/poloniexfutures.py +1 -1
  83. ccxt/async_support/probit.py +1 -1
  84. ccxt/async_support/timex.py +1 -1
  85. ccxt/async_support/tokocrypto.py +1 -1
  86. ccxt/async_support/tradeogre.py +2 -1
  87. ccxt/async_support/upbit.py +1 -1
  88. ccxt/async_support/wavesexchange.py +1 -1
  89. ccxt/async_support/wazirx.py +1 -1
  90. ccxt/async_support/whitebit.py +1 -1
  91. ccxt/async_support/woo.py +1 -1
  92. ccxt/async_support/yobit.py +1 -1
  93. ccxt/async_support/zaif.py +1 -1
  94. ccxt/async_support/zonda.py +1 -1
  95. ccxt/base/exchange.py +1 -1
  96. ccxt/bigone.py +1 -1
  97. ccxt/binance.py +1 -1
  98. ccxt/bingx.py +1 -1
  99. ccxt/bitbank.py +1 -1
  100. ccxt/bitbns.py +1 -1
  101. ccxt/bitfinex.py +1 -1
  102. ccxt/bitfinex2.py +1 -1
  103. ccxt/bitflyer.py +1 -1
  104. ccxt/bitget.py +12 -5
  105. ccxt/bithumb.py +2 -1
  106. ccxt/bitmart.py +1 -1
  107. ccxt/bitmex.py +1 -1
  108. ccxt/bitopro.py +1 -1
  109. ccxt/bitrue.py +1 -1
  110. ccxt/bitso.py +1 -1
  111. ccxt/bitstamp.py +43 -16
  112. ccxt/bitteam.py +1 -1
  113. ccxt/bitvavo.py +1 -1
  114. ccxt/blockchaincom.py +1 -1
  115. ccxt/blofin.py +1 -1
  116. ccxt/btcalpha.py +1 -1
  117. ccxt/btcmarkets.py +1 -1
  118. ccxt/btcturk.py +1 -1
  119. ccxt/bybit.py +5 -5
  120. ccxt/cex.py +1 -1
  121. ccxt/coinbase.py +1 -1
  122. ccxt/coinbaseinternational.py +1 -1
  123. ccxt/coinbasepro.py +1 -1
  124. ccxt/coinex.py +2 -3
  125. ccxt/coinlist.py +1 -1
  126. ccxt/coinmate.py +1 -1
  127. ccxt/coinmetro.py +1 -1
  128. ccxt/coinone.py +1 -1
  129. ccxt/coinsph.py +1 -1
  130. ccxt/cryptocom.py +1 -1
  131. ccxt/currencycom.py +1 -1
  132. ccxt/delta.py +1 -1
  133. ccxt/deribit.py +17 -2
  134. ccxt/digifinex.py +1 -1
  135. ccxt/exmo.py +1 -1
  136. ccxt/gate.py +1 -1
  137. ccxt/gemini.py +2 -1
  138. ccxt/hitbtc.py +1 -1
  139. ccxt/hollaex.py +1 -1
  140. ccxt/htx.py +6 -28
  141. ccxt/huobijp.py +1 -1
  142. ccxt/hyperliquid.py +6 -5
  143. ccxt/idex.py +1 -1
  144. ccxt/independentreserve.py +1 -1
  145. ccxt/indodax.py +1 -1
  146. ccxt/kraken.py +1 -1
  147. ccxt/krakenfutures.py +1 -1
  148. ccxt/kucoin.py +11 -2
  149. ccxt/kucoinfutures.py +147 -10
  150. ccxt/kuna.py +1 -1
  151. ccxt/latoken.py +1 -1
  152. ccxt/lbank.py +1 -1
  153. ccxt/luno.py +1 -1
  154. ccxt/lykke.py +1 -1
  155. ccxt/mercado.py +1 -1
  156. ccxt/mexc.py +1 -1
  157. ccxt/ndax.py +1 -1
  158. ccxt/novadax.py +1 -1
  159. ccxt/oceanex.py +1 -1
  160. ccxt/okcoin.py +1 -1
  161. ccxt/okx.py +1 -1
  162. ccxt/onetrading.py +1 -1
  163. ccxt/p2b.py +1 -1
  164. ccxt/phemex.py +1 -1
  165. ccxt/poloniex.py +1 -1
  166. ccxt/poloniexfutures.py +1 -1
  167. ccxt/pro/__init__.py +3 -1
  168. ccxt/pro/bithumb.py +368 -0
  169. ccxt/pro/bitmart.py +1 -1
  170. ccxt/pro/bybit.py +1 -1
  171. ccxt/pro/cex.py +15 -5
  172. ccxt/pro/okx.py +2 -1
  173. ccxt/pro/p2b.py +14 -4
  174. ccxt/pro/woo.py +1 -1
  175. ccxt/probit.py +1 -1
  176. ccxt/test/base/test_market.py +3 -0
  177. ccxt/timex.py +1 -1
  178. ccxt/tokocrypto.py +1 -1
  179. ccxt/tradeogre.py +2 -1
  180. ccxt/upbit.py +1 -1
  181. ccxt/wavesexchange.py +1 -1
  182. ccxt/wazirx.py +1 -1
  183. ccxt/whitebit.py +1 -1
  184. ccxt/woo.py +1 -1
  185. ccxt/yobit.py +1 -1
  186. ccxt/zaif.py +1 -1
  187. ccxt/zonda.py +1 -1
  188. {ccxt-4.2.82.dist-info → ccxt-4.2.84.dist-info}/METADATA +5 -5
  189. {ccxt-4.2.82.dist-info → ccxt-4.2.84.dist-info}/RECORD +191 -190
  190. {ccxt-4.2.82.dist-info → ccxt-4.2.84.dist-info}/WHEEL +0 -0
  191. {ccxt-4.2.82.dist-info → ccxt-4.2.84.dist-info}/top_level.txt +0 -0
ccxt/pro/bithumb.py ADDED
@@ -0,0 +1,368 @@
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
8
+ from ccxt.base.types import Int, OrderBook, Strings, Ticker, Tickers, Trade
9
+ from ccxt.async_support.base.ws.client import Client
10
+ from typing import List
11
+ from ccxt.base.errors import ExchangeError
12
+
13
+
14
+ class bithumb(ccxt.async_support.bithumb):
15
+
16
+ def describe(self):
17
+ return self.deep_extend(super(bithumb, self).describe(), {
18
+ 'has': {
19
+ 'ws': True,
20
+ 'watchBalance': False,
21
+ 'watchTicker': True,
22
+ 'watchTickers': True,
23
+ 'watchTrades': True,
24
+ 'watchOrderBook': True,
25
+ 'watchOHLCV': False,
26
+ },
27
+ 'urls': {
28
+ 'api': {
29
+ 'ws': 'wss://pubwss.bithumb.com/pub/ws',
30
+ },
31
+ },
32
+ 'options': {},
33
+ 'streaming': {},
34
+ 'exceptions': {},
35
+ })
36
+
37
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
38
+ """
39
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
40
+ :param str symbol: unified symbol of the market to fetch the ticker for
41
+ :param dict [params]: extra parameters specific to the exchange API endpoint
42
+ :param str [params.channel]: the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
43
+ :returns dict: a `ticker structure <https://github.com/ccxt/ccxt/wiki/Manual#ticker-structure>`
44
+ """
45
+ url = self.urls['api']['ws']
46
+ await self.load_markets()
47
+ market = self.market(symbol)
48
+ messageHash = 'ticker:' + market['symbol']
49
+ request = {
50
+ 'type': 'ticker',
51
+ 'symbols': [market['base'] + '_' + market['quote']],
52
+ 'tickTypes': [self.safe_string(params, 'tickTypes', '24H')],
53
+ }
54
+ return await self.watch(url, messageHash, self.extend(request, params), messageHash)
55
+
56
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
57
+ """
58
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
59
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
60
+ :param dict [params]: extra parameters specific to the exchange API endpoint
61
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
62
+ """
63
+ await self.load_markets()
64
+ url = self.urls['api']['ws']
65
+ marketIds = []
66
+ messageHashes = []
67
+ symbols = self.market_symbols(symbols, None, False, True, True)
68
+ for i in range(0, len(symbols)):
69
+ symbol = symbols[i]
70
+ market = self.market(symbol)
71
+ marketIds.append(market['base'] + '_' + market['quote'])
72
+ messageHashes.append('ticker:' + market['symbol'])
73
+ request = {
74
+ 'type': 'ticker',
75
+ 'symbols': marketIds,
76
+ 'tickTypes': [self.safe_string(params, 'tickTypes', '24H')],
77
+ }
78
+ message = self.extend(request, params)
79
+ newTicker = await self.watch_multiple(url, messageHashes, message, messageHashes)
80
+ if self.newUpdates:
81
+ result = {}
82
+ result[newTicker['symbol']] = newTicker
83
+ return result
84
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
85
+
86
+ def handle_ticker(self, client: Client, message):
87
+ #
88
+ # {
89
+ # "type" : "ticker",
90
+ # "content" : {
91
+ # "symbol" : "BTC_KRW", # 통화코드
92
+ # "tickType" : "24H", # 변동 기준시간- 30M, 1H, 12H, 24H, MID
93
+ # "date" : "20200129", # 일자
94
+ # "time" : "121844", # 시간
95
+ # "openPrice" : "2302", # 시가
96
+ # "closePrice" : "2317", # 종가
97
+ # "lowPrice" : "2272", # 저가
98
+ # "highPrice" : "2344", # 고가
99
+ # "value" : "2831915078.07065789", # 누적거래금액
100
+ # "volume" : "1222314.51355788", # 누적거래량
101
+ # "sellVolume" : "760129.34079004", # 매도누적거래량
102
+ # "buyVolume" : "462185.17276784", # 매수누적거래량
103
+ # "prevClosePrice" : "2326", # 전일종가
104
+ # "chgRate" : "0.65", # 변동률
105
+ # "chgAmt" : "15", # 변동금액
106
+ # "volumePower" : "60.80" # 체결강도
107
+ # }
108
+ # }
109
+ #
110
+ content = self.safe_dict(message, 'content', {})
111
+ marketId = self.safe_string(content, 'symbol')
112
+ symbol = self.safe_symbol(marketId, None, '_')
113
+ ticker = self.parse_ws_ticker(content)
114
+ messageHash = 'ticker:' + symbol
115
+ self.tickers[symbol] = ticker
116
+ client.resolve(self.tickers[symbol], messageHash)
117
+
118
+ def parse_ws_ticker(self, ticker, market=None):
119
+ #
120
+ # {
121
+ # "symbol" : "BTC_KRW", # 통화코드
122
+ # "tickType" : "24H", # 변동 기준시간- 30M, 1H, 12H, 24H, MID
123
+ # "date" : "20200129", # 일자
124
+ # "time" : "121844", # 시간
125
+ # "openPrice" : "2302", # 시가
126
+ # "closePrice" : "2317", # 종가
127
+ # "lowPrice" : "2272", # 저가
128
+ # "highPrice" : "2344", # 고가
129
+ # "value" : "2831915078.07065789", # 누적거래금액
130
+ # "volume" : "1222314.51355788", # 누적거래량
131
+ # "sellVolume" : "760129.34079004", # 매도누적거래량
132
+ # "buyVolume" : "462185.17276784", # 매수누적거래량
133
+ # "prevClosePrice" : "2326", # 전일종가
134
+ # "chgRate" : "0.65", # 변동률
135
+ # "chgAmt" : "15", # 변동금액
136
+ # "volumePower" : "60.80" # 체결강도
137
+ # }
138
+ #
139
+ date = self.safe_string(ticker, 'date', '')
140
+ time = self.safe_string(ticker, 'time', '')
141
+ datetime = date[0:4] + '-' + date[4:6] + '-' + date[6:8] + 'T' + time[0:2] + ':' + time[2:4] + ':' + time[4:6]
142
+ marketId = self.safe_string(ticker, 'symbol')
143
+ return self.safe_ticker({
144
+ 'symbol': self.safe_symbol(marketId, market, '_'),
145
+ 'timestamp': self.parse8601(datetime),
146
+ 'datetime': datetime,
147
+ 'high': self.safe_string(ticker, 'highPrice'),
148
+ 'low': self.safe_string(ticker, 'lowPrice'),
149
+ 'bid': None,
150
+ 'bidVolume': self.safe_string(ticker, 'buyVolume'),
151
+ 'ask': None,
152
+ 'askVolume': self.safe_string(ticker, 'sellVolume'),
153
+ 'vwap': None,
154
+ 'open': self.safe_string(ticker, 'openPrice'),
155
+ 'close': self.safe_string(ticker, 'closePrice'),
156
+ 'last': None,
157
+ 'previousClose': self.safe_string(ticker, 'prevClosePrice'),
158
+ 'change': self.safe_string(ticker, 'chgAmt'),
159
+ 'percentage': self.safe_string(ticker, 'chgRate'),
160
+ 'average': None,
161
+ 'baseVolume': self.safe_string(ticker, 'volume'),
162
+ 'quoteVolume': self.safe_string(ticker, 'value'),
163
+ 'info': ticker,
164
+ }, market)
165
+
166
+ async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
167
+ """
168
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
169
+ :param str symbol: unified symbol of the market to fetch the order book for
170
+ :param int [limit]: the maximum amount of order book entries to return
171
+ :param dict [params]: extra parameters specific to the exchange API endpoint
172
+ :returns dict: A dictionary of `order book structures <https://github.com/ccxt/ccxt/wiki/Manual#order-book-structure>` indexed by market symbols
173
+ """
174
+ await self.load_markets()
175
+ url = self.urls['api']['ws']
176
+ market = self.market(symbol)
177
+ symbol = market['symbol']
178
+ messageHash = 'orderbook' + ':' + symbol
179
+ request = {
180
+ 'type': 'orderbookdepth',
181
+ 'symbols': [market['base'] + '_' + market['quote']],
182
+ }
183
+ orderbook = await self.watch(url, messageHash, self.extend(request, params), messageHash)
184
+ return orderbook.limit()
185
+
186
+ def handle_order_book(self, client: Client, message):
187
+ #
188
+ # {
189
+ # "type" : "orderbookdepth",
190
+ # "content" : {
191
+ # "list" : [
192
+ # {
193
+ # "symbol" : "BTC_KRW",
194
+ # "orderType" : "ask", # 주문타입 – bid / ask
195
+ # "price" : "10593000", # 호가
196
+ # "quantity" : "1.11223318", # 잔량
197
+ # "total" : "3" # 건수
198
+ # },
199
+ # {"symbol" : "BTC_KRW", "orderType" : "ask", "price" : "10596000", "quantity" : "0.5495", "total" : "8"},
200
+ # {"symbol" : "BTC_KRW", "orderType" : "ask", "price" : "10598000", "quantity" : "18.2085", "total" : "10"},
201
+ # {"symbol" : "BTC_KRW", "orderType" : "bid", "price" : "10532000", "quantity" : "0", "total" : "0"},
202
+ # {"symbol" : "BTC_KRW", "orderType" : "bid", "price" : "10572000", "quantity" : "2.3324", "total" : "4"},
203
+ # {"symbol" : "BTC_KRW", "orderType" : "bid", "price" : "10571000", "quantity" : "1.469", "total" : "3"},
204
+ # {"symbol" : "BTC_KRW", "orderType" : "bid", "price" : "10569000", "quantity" : "0.5152", "total" : "2"}
205
+ # ],
206
+ # "datetime":1580268255864325 # 일시
207
+ # }
208
+ # }
209
+ #
210
+ content = self.safe_dict(message, 'content', {})
211
+ list = self.safe_list(content, 'list', [])
212
+ first = self.safe_dict(list, 0, {})
213
+ marketId = self.safe_string(first, 'symbol')
214
+ symbol = self.safe_symbol(marketId, None, '_')
215
+ timestampStr = self.safe_string(content, 'datetime')
216
+ timestamp = self.parse_to_int(timestampStr[0:13])
217
+ if not (symbol in self.orderbooks):
218
+ ob = self.order_book()
219
+ ob['symbol'] = symbol
220
+ self.orderbooks[symbol] = ob
221
+ orderbook = self.orderbooks[symbol]
222
+ self.handle_deltas(orderbook, list)
223
+ orderbook['timestamp'] = timestamp
224
+ orderbook['datetime'] = self.iso8601(timestamp)
225
+ messageHash = 'orderbook' + ':' + symbol
226
+ client.resolve(orderbook, messageHash)
227
+
228
+ def handle_delta(self, orderbook, delta):
229
+ #
230
+ # {
231
+ # symbol: "ETH_BTC",
232
+ # orderType: "bid",
233
+ # price: "0.07349517",
234
+ # quantity: "0",
235
+ # total: "0",
236
+ # }
237
+ #
238
+ sideId = self.safe_string(delta, 'orderType')
239
+ side = 'bids' if (sideId == 'bid') else 'asks'
240
+ bidAsk = self.parse_bid_ask(delta, 'price', 'quantity')
241
+ orderbookSide = orderbook[side]
242
+ orderbookSide.storeArray(bidAsk)
243
+
244
+ def handle_deltas(self, orderbook, deltas):
245
+ for i in range(0, len(deltas)):
246
+ self.handle_delta(orderbook, deltas[i])
247
+
248
+ async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
249
+ """
250
+ get the list of most recent trades for a particular symbol
251
+ :param str symbol: unified symbol of the market to fetch trades for
252
+ :param int [since]: timestamp in ms of the earliest trade to fetch
253
+ :param int [limit]: the maximum amount of trades to fetch
254
+ :param dict [params]: extra parameters specific to the exchange API endpoint
255
+ :returns dict[]: a list of `trade structures <https://github.com/ccxt/ccxt/wiki/Manual#public-trades>`
256
+ """
257
+ await self.load_markets()
258
+ url = self.urls['api']['ws']
259
+ market = self.market(symbol)
260
+ symbol = market['symbol']
261
+ messageHash = 'trade:' + symbol
262
+ request = {
263
+ 'type': 'transaction',
264
+ 'symbols': [market['base'] + '_' + market['quote']],
265
+ }
266
+ trades = await self.watch(url, messageHash, self.extend(request, params), messageHash)
267
+ if self.newUpdates:
268
+ limit = trades.getLimit(symbol, limit)
269
+ return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
270
+
271
+ def handle_trades(self, client, message):
272
+ #
273
+ # {
274
+ # "type" : "transaction",
275
+ # "content" : {
276
+ # "list" : [
277
+ # {
278
+ # "symbol" : "BTC_KRW",
279
+ # "buySellGb" : "1",
280
+ # "contPrice" : "10579000",
281
+ # "contQty" : "0.01",
282
+ # "contAmt" : "105790.00",
283
+ # "contDtm" : "2020-01-29 12:24:18.830039",
284
+ # "updn" : "dn"
285
+ # }
286
+ # ]
287
+ # }
288
+ # }
289
+ #
290
+ content = self.safe_dict(message, 'content', {})
291
+ rawTrades = self.safe_list(content, 'list', [])
292
+ for i in range(0, len(rawTrades)):
293
+ rawTrade = rawTrades[i]
294
+ marketId = self.safe_string(rawTrade, 'symbol')
295
+ symbol = self.safe_symbol(marketId, None, '_')
296
+ if not (symbol in self.trades):
297
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
298
+ stored = ArrayCache(limit)
299
+ self.trades[symbol] = stored
300
+ trades = self.trades[symbol]
301
+ parsed = self.parse_ws_trade(rawTrade)
302
+ trades.append(parsed)
303
+ messageHash = 'trade' + ':' + symbol
304
+ client.resolve(trades, messageHash)
305
+
306
+ def parse_ws_trade(self, trade, market=None):
307
+ #
308
+ # {
309
+ # "symbol" : "BTC_KRW",
310
+ # "buySellGb" : "1",
311
+ # "contPrice" : "10579000",
312
+ # "contQty" : "0.01",
313
+ # "contAmt" : "105790.00",
314
+ # "contDtm" : "2020-01-29 12:24:18.830039",
315
+ # "updn" : "dn"
316
+ # }
317
+ #
318
+ marketId = self.safe_string(trade, 'symbol')
319
+ datetime = self.safe_string(trade, 'contDtm')
320
+ sideId = self.safe_string(trade, 'buySellGb')
321
+ return self.safe_trade({
322
+ 'id': None,
323
+ 'info': trade,
324
+ 'timestamp': self.parse8601(datetime),
325
+ 'datetime': datetime,
326
+ 'symbol': self.safe_symbol(marketId, market, '_'),
327
+ 'order': None,
328
+ 'type': None,
329
+ 'side': 'buy' if (sideId == '1') else 'sell',
330
+ 'takerOrMaker': None,
331
+ 'price': self.safe_string(trade, 'contPrice'),
332
+ 'amount': self.safe_string(trade, 'contQty'),
333
+ 'cost': self.safe_string(trade, 'contAmt'),
334
+ 'fee': None,
335
+ }, market)
336
+
337
+ def handle_error_message(self, client: Client, message):
338
+ #
339
+ # {
340
+ # "status" : "5100",
341
+ # "resmsg" : "Invalid Filter Syntax"
342
+ # }
343
+ #
344
+ if not ('status' in message):
345
+ return True
346
+ errorCode = self.safe_string(message, 'status')
347
+ try:
348
+ if errorCode != '0000':
349
+ msg = self.safe_string(message, 'resmsg')
350
+ raise ExchangeError(self.id + ' ' + msg)
351
+ return True
352
+ except Exception as e:
353
+ client.reject(e)
354
+ return True
355
+
356
+ def handle_message(self, client: Client, message):
357
+ if not self.handle_error_message(client, message):
358
+ return
359
+ topic = self.safe_string(message, 'type')
360
+ if topic is not None:
361
+ methods = {
362
+ 'ticker': self.handle_ticker,
363
+ 'orderbookdepth': self.handle_order_book,
364
+ 'transaction': self.handle_trades,
365
+ }
366
+ method = self.safe_value(methods, topic)
367
+ if method is not None:
368
+ method(client, message)
ccxt/pro/bitmart.py CHANGED
@@ -663,9 +663,9 @@ class bitmart(ccxt.async_support.bitmart):
663
663
  # }
664
664
  #
665
665
  data = self.safe_value(message, 'data', [])
666
- cache = self.positions
667
666
  if self.positions is None:
668
667
  self.positions = ArrayCacheBySymbolBySide()
668
+ cache = self.positions
669
669
  newPositions = []
670
670
  for i in range(0, len(data)):
671
671
  rawPosition = data[i]
ccxt/pro/bybit.py CHANGED
@@ -197,7 +197,7 @@ class bybit(ccxt.async_support.bybit):
197
197
 
198
198
  async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
199
199
  """
200
- n watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
200
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
201
201
  :see: https://bybit-exchange.github.io/docs/v5/websocket/public/ticker
202
202
  :see: https://bybit-exchange.github.io/docs/v5/websocket/public/etp-ticker
203
203
  :param str[] symbols: unified symbol of the market to fetch the ticker for
ccxt/pro/cex.py CHANGED
@@ -131,6 +131,7 @@ class cex(ccxt.async_support.cex):
131
131
  url = self.urls['api']['ws']
132
132
  messageHash = 'trades'
133
133
  subscriptionHash = 'old:' + symbol
134
+ self.options['currentWatchTradeSymbol'] = symbol # exchange supports only 1 symbol for self watchTrades channel
134
135
  client = self.safe_value(self.clients, url)
135
136
  if client is not None:
136
137
  subscriptionKeys = list(client.subscriptions.keys())
@@ -167,11 +168,15 @@ class cex(ccxt.async_support.cex):
167
168
  data = self.safe_list(message, 'data', [])
168
169
  limit = self.safe_integer(self.options, 'tradesLimit', 1000)
169
170
  stored = ArrayCache(limit)
171
+ symbol = self.safe_string(self.options, 'currentWatchTradeSymbol')
172
+ if symbol is None:
173
+ return
174
+ market = self.market(symbol)
170
175
  dataLength = len(data)
171
176
  for i in range(0, dataLength):
172
177
  index = dataLength - 1 - i
173
178
  rawTrade = data[index]
174
- parsed = self.parse_ws_old_trade(rawTrade)
179
+ parsed = self.parse_ws_old_trade(rawTrade, market)
175
180
  stored.append(parsed)
176
181
  messageHash = 'trades'
177
182
  self.trades = stored # trades don't have symbol
@@ -196,7 +201,7 @@ class cex(ccxt.async_support.cex):
196
201
  'id': id,
197
202
  'timestamp': timestamp,
198
203
  'datetime': self.iso8601(timestamp),
199
- 'symbol': None,
204
+ 'symbol': self.safe_string(market, 'symbol'),
200
205
  'type': None,
201
206
  'side': side,
202
207
  'order': None,
@@ -218,8 +223,10 @@ class cex(ccxt.async_support.cex):
218
223
  #
219
224
  data = self.safe_value(message, 'data', [])
220
225
  stored = self.trades # to do fix self, self.trades is not meant to be used like self
221
- for i in range(0, len(data)):
222
- rawTrade = data[i]
226
+ dataLength = len(data)
227
+ for i in range(0, dataLength):
228
+ index = dataLength - 1 - i
229
+ rawTrade = data[index]
223
230
  parsed = self.parse_ws_old_trade(rawTrade)
224
231
  stored.append(parsed)
225
232
  messageHash = 'trades'
@@ -325,12 +332,15 @@ class cex(ccxt.async_support.cex):
325
332
  data = self.safe_value(message, 'data', {})
326
333
  ticker = self.parse_ws_ticker(data)
327
334
  symbol = ticker['symbol']
335
+ if symbol is None:
336
+ return
328
337
  self.tickers[symbol] = ticker
329
338
  messageHash = 'ticker:' + symbol
330
339
  client.resolve(ticker, messageHash)
331
340
  client.resolve(ticker, 'tickers')
332
341
  messageHash = self.safe_string(message, 'oid')
333
- client.resolve(ticker, messageHash)
342
+ if messageHash is not None:
343
+ client.resolve(ticker, messageHash)
334
344
 
335
345
  def parse_ws_ticker(self, ticker, market=None):
336
346
  #
ccxt/pro/okx.py CHANGED
@@ -1236,7 +1236,8 @@ class okx(ccxt.async_support.okx):
1236
1236
  stringMsg = self.json(message)
1237
1237
  self.handle_errors(None, None, client.url, method, None, stringMsg, stringMsg, None, None)
1238
1238
  orders = self.parse_orders(args, None, None, None)
1239
- client.resolve(orders, messageHash)
1239
+ first = self.safe_dict(orders, 0, {})
1240
+ client.resolve(first, messageHash)
1240
1241
 
1241
1242
  async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
1242
1243
  """
ccxt/pro/p2b.py CHANGED
@@ -57,6 +57,7 @@ class p2b(ccxt.async_support.p2b):
57
57
  'watchTickers': {
58
58
  'name': 'state', # or 'price'
59
59
  },
60
+ 'tickerSubs': self.create_safe_dictionary(),
60
61
  },
61
62
  'streaming': {
62
63
  'ping': self.ping,
@@ -120,13 +121,14 @@ class p2b(ccxt.async_support.p2b):
120
121
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
121
122
  """
122
123
  await self.load_markets()
123
- watchTickerOptions = self.safe_value(self.options, 'watchTicker')
124
+ watchTickerOptions = self.safe_dict(self.options, 'watchTicker')
124
125
  name = self.safe_string(watchTickerOptions, 'name', 'state') # or price
125
126
  name, params = self.handle_option_and_params(params, 'method', 'name', name)
126
127
  market = self.market(symbol)
127
- request = [
128
- market['id'],
129
- ]
128
+ symbol = market['symbol']
129
+ self.options['tickerSubs'][market['id']] = True # we need to re-subscribe to all tickers upon watching a new ticker
130
+ tickerSubs = self.options['tickerSubs']
131
+ request = list(tickerSubs.keys())
130
132
  messageHash = name + '::' + market['symbol']
131
133
  return await self.subscribe(name + '.subscribe', messageHash, request, params)
132
134
 
@@ -407,3 +409,11 @@ class p2b(ccxt.async_support.p2b):
407
409
  #
408
410
  client.lastPong = self.safe_integer(message, 'id')
409
411
  return message
412
+
413
+ def on_error(self, client: Client, error):
414
+ self.options['tickerSubs'] = self.create_safe_dictionary()
415
+ self.on_error(client, error)
416
+
417
+ def on_close(self, client: Client, error):
418
+ self.options['tickerSubs'] = self.create_safe_dictionary()
419
+ self.on_close(client, error)
ccxt/pro/woo.py CHANGED
@@ -229,7 +229,7 @@ class woo(ccxt.async_support.woo):
229
229
 
230
230
  async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
231
231
  """
232
- n watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
232
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
233
233
  :param str[] symbols: unified symbol of the market to fetch the ticker for
234
234
  :param dict [params]: extra parameters specific to the exchange API endpoint
235
235
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
ccxt/probit.py CHANGED
@@ -256,7 +256,7 @@ class probit(Exchange, ImplicitAPI):
256
256
  },
257
257
  })
258
258
 
259
- def fetch_markets(self, params={}):
259
+ def fetch_markets(self, params={}) -> List[Market]:
260
260
  """
261
261
  :see: https://docs-en.probit.com/reference/market
262
262
  retrieves data on all markets for probit
@@ -91,6 +91,9 @@ def test_market(exchange, skipped_properties, method, market):
91
91
  # otherwise, it must be false or undefined
92
92
  test_shared_methods.assert_in_array(exchange, skipped_properties, method, market, 'margin', [False, None])
93
93
  if not ('contractSize' in skipped_properties):
94
+ if not market['spot']:
95
+ # if not spot, then contractSize should be defined
96
+ assert market['contractSize'] is not None, '\"contractSize\" must be defined when \"spot\" is false' + log_text
94
97
  test_shared_methods.assert_greater(exchange, skipped_properties, method, market, 'contractSize', '0')
95
98
  # typical values
96
99
  test_shared_methods.assert_greater(exchange, skipped_properties, method, market, 'expiry', '0')
ccxt/timex.py CHANGED
@@ -292,7 +292,7 @@ class timex(Exchange, ImplicitAPI):
292
292
  #
293
293
  return self.parse_to_int(response) * 1000
294
294
 
295
- def fetch_markets(self, params={}):
295
+ def fetch_markets(self, params={}) -> List[Market]:
296
296
  """
297
297
  retrieves data on all markets for timex
298
298
  :see: https://plasma-relay-backend.timex.io/swagger-ui/index.html?urls.primaryName=Relay#/Public/listMarkets
ccxt/tokocrypto.py CHANGED
@@ -637,7 +637,7 @@ class tokocrypto(Exchange, ImplicitAPI):
637
637
  #
638
638
  return self.safe_integer(response, 'serverTime')
639
639
 
640
- def fetch_markets(self, params={}):
640
+ def fetch_markets(self, params={}) -> List[Market]:
641
641
  """
642
642
  :see: https://www.tokocrypto.com/apidocs/#get-all-supported-trading-symbol
643
643
  retrieves data on all markets for tokocrypto
ccxt/tradeogre.py CHANGED
@@ -6,6 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.tradeogre import ImplicitAPI
8
8
  from ccxt.base.types import IndexType, Int, Market, Num, Order, OrderSide, OrderType, Str, Ticker
9
+ from typing import List
9
10
  from ccxt.base.errors import ExchangeError
10
11
  from ccxt.base.errors import BadRequest
11
12
  from ccxt.base.errors import InsufficientFunds
@@ -162,7 +163,7 @@ class tradeogre(Exchange, ImplicitAPI):
162
163
  },
163
164
  })
164
165
 
165
- def fetch_markets(self, params={}):
166
+ def fetch_markets(self, params={}) -> List[Market]:
166
167
  """
167
168
  retrieves data on all markets for bigone
168
169
  :see: https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#markets
ccxt/upbit.py CHANGED
@@ -403,7 +403,7 @@ class upbit(Exchange, ImplicitAPI):
403
403
  },
404
404
  })
405
405
 
406
- def fetch_markets(self, params={}):
406
+ def fetch_markets(self, params={}) -> List[Market]:
407
407
  """
408
408
  :see: https://docs.upbit.com/reference/%EB%A7%88%EC%BC%93-%EC%BD%94%EB%93%9C-%EC%A1%B0%ED%9A%8C
409
409
  retrieves data on all markets for upbit
ccxt/wavesexchange.py CHANGED
@@ -494,7 +494,7 @@ class wavesexchange(Exchange, ImplicitAPI):
494
494
  self.options['quotes'] = quotes
495
495
  return quotes
496
496
 
497
- def fetch_markets(self, params={}):
497
+ def fetch_markets(self, params={}) -> List[Market]:
498
498
  """
499
499
  retrieves data on all markets for wavesexchange
500
500
  :param dict [params]: extra parameters specific to the exchange API endpoint
ccxt/wazirx.py CHANGED
@@ -196,7 +196,7 @@ class wazirx(Exchange, ImplicitAPI):
196
196
  },
197
197
  })
198
198
 
199
- def fetch_markets(self, params={}):
199
+ def fetch_markets(self, params={}) -> List[Market]:
200
200
  """
201
201
  :see: https://docs.wazirx.com/#exchange-info
202
202
  retrieves data on all markets for wazirx
ccxt/whitebit.py CHANGED
@@ -281,7 +281,7 @@ class whitebit(Exchange, ImplicitAPI):
281
281
  },
282
282
  })
283
283
 
284
- def fetch_markets(self, params={}):
284
+ def fetch_markets(self, params={}) -> List[Market]:
285
285
  """
286
286
  retrieves data on all markets for whitebit
287
287
  :see: https://docs.whitebit.com/public/http-v4/#market-info
ccxt/woo.py CHANGED
@@ -387,7 +387,7 @@ class woo(Exchange, ImplicitAPI):
387
387
  #
388
388
  return self.safe_integer(response, 'timestamp')
389
389
 
390
- def fetch_markets(self, params={}):
390
+ def fetch_markets(self, params={}) -> List[Market]:
391
391
  """
392
392
  retrieves data on all markets for woo
393
393
  :param dict [params]: extra parameters specific to the exchange API endpoint
ccxt/yobit.py CHANGED
@@ -347,7 +347,7 @@ class yobit(Exchange, ImplicitAPI):
347
347
  #
348
348
  return self.parse_balance(response)
349
349
 
350
- def fetch_markets(self, params={}):
350
+ def fetch_markets(self, params={}) -> List[Market]:
351
351
  """
352
352
  :see: https://yobit.net/en/api
353
353
  retrieves data on all markets for yobit
ccxt/zaif.py CHANGED
@@ -143,7 +143,7 @@ class zaif(Exchange, ImplicitAPI):
143
143
  },
144
144
  })
145
145
 
146
- def fetch_markets(self, params={}):
146
+ def fetch_markets(self, params={}) -> List[Market]:
147
147
  """
148
148
  :see: https://zaif-api-document.readthedocs.io/ja/latest/PublicAPI.html#id12
149
149
  retrieves data on all markets for zaif
ccxt/zonda.py CHANGED
@@ -311,7 +311,7 @@ class zonda(Exchange, ImplicitAPI):
311
311
  },
312
312
  })
313
313
 
314
- def fetch_markets(self, params={}):
314
+ def fetch_markets(self, params={}) -> List[Market]:
315
315
  """
316
316
  :see: https://docs.zondacrypto.exchange/reference/ticker-1
317
317
  retrieves data on all markets for zonda