ccxt 4.4.52__py2.py3-none-any.whl → 4.4.57__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.
Files changed (223) hide show
  1. ccxt/__init__.py +1 -3
  2. ccxt/abstract/binance.py +0 -1
  3. ccxt/abstract/binancecoinm.py +0 -1
  4. ccxt/abstract/binanceus.py +0 -1
  5. ccxt/abstract/binanceusdm.py +0 -1
  6. ccxt/ace.py +3 -0
  7. ccxt/alpaca.py +5 -0
  8. ccxt/ascendex.py +2 -1
  9. ccxt/async_support/__init__.py +1 -3
  10. ccxt/async_support/ace.py +3 -0
  11. ccxt/async_support/alpaca.py +5 -0
  12. ccxt/async_support/ascendex.py +2 -1
  13. ccxt/async_support/base/exchange.py +24 -7
  14. ccxt/async_support/bigone.py +5 -0
  15. ccxt/async_support/binance.py +54 -54
  16. ccxt/async_support/bingx.py +25 -29
  17. ccxt/async_support/bit2c.py +3 -0
  18. ccxt/async_support/bitbank.py +3 -0
  19. ccxt/async_support/bitbns.py +3 -0
  20. ccxt/async_support/bitfinex.py +6 -1
  21. ccxt/async_support/bitflyer.py +6 -1
  22. ccxt/async_support/bitget.py +9 -5
  23. ccxt/async_support/bithumb.py +3 -1
  24. ccxt/async_support/bitmart.py +22 -12
  25. ccxt/async_support/bitmex.py +99 -93
  26. ccxt/async_support/bitopro.py +7 -2
  27. ccxt/async_support/bitrue.py +4 -0
  28. ccxt/async_support/bitso.py +5 -2
  29. ccxt/async_support/bitstamp.py +3 -0
  30. ccxt/async_support/bitteam.py +5 -0
  31. ccxt/async_support/bitvavo.py +4 -0
  32. ccxt/async_support/blockchaincom.py +4 -0
  33. ccxt/async_support/blofin.py +3 -0
  34. ccxt/async_support/btcalpha.py +5 -0
  35. ccxt/async_support/btcbox.py +3 -2
  36. ccxt/async_support/btcmarkets.py +5 -0
  37. ccxt/async_support/btcturk.py +3 -0
  38. ccxt/async_support/bybit.py +13 -5
  39. ccxt/async_support/cex.py +2 -0
  40. ccxt/async_support/coinbase.py +20 -13
  41. ccxt/async_support/coinbaseexchange.py +5 -0
  42. ccxt/async_support/coinbaseinternational.py +23 -4
  43. ccxt/async_support/coincatch.py +3 -0
  44. ccxt/async_support/coincheck.py +2 -0
  45. ccxt/async_support/coinex.py +6 -2
  46. ccxt/async_support/coinlist.py +5 -0
  47. ccxt/async_support/coinmate.py +4 -0
  48. ccxt/async_support/coinmetro.py +9 -5
  49. ccxt/async_support/coinone.py +3 -0
  50. ccxt/async_support/coinsph.py +4 -0
  51. ccxt/async_support/coinspot.py +1 -0
  52. ccxt/async_support/cryptocom.py +5 -0
  53. ccxt/async_support/currencycom.py +3 -0
  54. ccxt/async_support/defx.py +5 -0
  55. ccxt/async_support/delta.py +4 -1
  56. ccxt/async_support/deribit.py +15 -28
  57. ccxt/async_support/digifinex.py +10 -5
  58. ccxt/async_support/ellipx.py +9 -5
  59. ccxt/async_support/exmo.py +7 -4
  60. ccxt/async_support/gate.py +5 -1
  61. ccxt/async_support/gemini.py +3 -0
  62. ccxt/async_support/hashkey.py +5 -4
  63. ccxt/async_support/hitbtc.py +6 -2
  64. ccxt/async_support/hollaex.py +7 -2
  65. ccxt/async_support/htx.py +8 -1
  66. ccxt/async_support/huobijp.py +5 -0
  67. ccxt/async_support/hyperliquid.py +9 -4
  68. ccxt/async_support/idex.py +5 -1
  69. ccxt/async_support/independentreserve.py +4 -0
  70. ccxt/async_support/indodax.py +3 -0
  71. ccxt/async_support/kraken.py +7 -5
  72. ccxt/async_support/krakenfutures.py +5 -2
  73. ccxt/async_support/kucoin.py +13 -6
  74. ccxt/async_support/kucoinfutures.py +5 -1
  75. ccxt/async_support/kuna.py +3 -0
  76. ccxt/async_support/latoken.py +4 -0
  77. ccxt/async_support/lbank.py +6 -1
  78. ccxt/async_support/luno.py +6 -1
  79. ccxt/async_support/mercado.py +4 -0
  80. ccxt/async_support/mexc.py +10 -9
  81. ccxt/async_support/ndax.py +6 -1
  82. ccxt/async_support/novadax.py +5 -0
  83. ccxt/async_support/oceanex.py +6 -2
  84. ccxt/async_support/okcoin.py +4 -0
  85. ccxt/async_support/okx.py +17 -5
  86. ccxt/async_support/onetrading.py +4 -0
  87. ccxt/async_support/oxfun.py +3 -0
  88. ccxt/async_support/p2b.py +3 -0
  89. ccxt/async_support/paradex.py +8 -2
  90. ccxt/async_support/phemex.py +10 -4
  91. ccxt/async_support/poloniex.py +6 -3
  92. ccxt/async_support/poloniexfutures.py +5 -1
  93. ccxt/async_support/probit.py +4 -0
  94. ccxt/async_support/timex.py +4 -0
  95. ccxt/async_support/tokocrypto.py +5 -0
  96. ccxt/async_support/tradeogre.py +2 -0
  97. ccxt/async_support/upbit.py +5 -2
  98. ccxt/async_support/vertex.py +6 -2
  99. ccxt/async_support/wavesexchange.py +20 -3
  100. ccxt/async_support/wazirx.py +2 -0
  101. ccxt/async_support/whitebit.py +5 -4
  102. ccxt/async_support/woo.py +15 -5
  103. ccxt/async_support/woofipro.py +23 -9
  104. ccxt/async_support/xt.py +5 -0
  105. ccxt/async_support/yobit.py +5 -2
  106. ccxt/async_support/zaif.py +2 -0
  107. ccxt/async_support/zonda.py +2 -0
  108. ccxt/base/exchange.py +96 -54
  109. ccxt/base/types.py +1 -1
  110. ccxt/bigone.py +5 -0
  111. ccxt/binance.py +54 -54
  112. ccxt/bingx.py +25 -29
  113. ccxt/bit2c.py +3 -0
  114. ccxt/bitbank.py +3 -0
  115. ccxt/bitbns.py +3 -0
  116. ccxt/bitfinex.py +6 -1
  117. ccxt/bitflyer.py +6 -1
  118. ccxt/bitget.py +9 -5
  119. ccxt/bithumb.py +3 -1
  120. ccxt/bitmart.py +22 -12
  121. ccxt/bitmex.py +99 -93
  122. ccxt/bitopro.py +7 -2
  123. ccxt/bitrue.py +4 -0
  124. ccxt/bitso.py +5 -2
  125. ccxt/bitstamp.py +3 -0
  126. ccxt/bitteam.py +5 -0
  127. ccxt/bitvavo.py +4 -0
  128. ccxt/blockchaincom.py +4 -0
  129. ccxt/blofin.py +3 -0
  130. ccxt/btcalpha.py +5 -0
  131. ccxt/btcbox.py +3 -2
  132. ccxt/btcmarkets.py +5 -0
  133. ccxt/btcturk.py +3 -0
  134. ccxt/bybit.py +13 -5
  135. ccxt/cex.py +2 -0
  136. ccxt/coinbase.py +20 -13
  137. ccxt/coinbaseexchange.py +5 -0
  138. ccxt/coinbaseinternational.py +23 -4
  139. ccxt/coincatch.py +3 -0
  140. ccxt/coincheck.py +2 -0
  141. ccxt/coinex.py +6 -2
  142. ccxt/coinlist.py +5 -0
  143. ccxt/coinmate.py +4 -0
  144. ccxt/coinmetro.py +9 -5
  145. ccxt/coinone.py +3 -0
  146. ccxt/coinsph.py +4 -0
  147. ccxt/coinspot.py +1 -0
  148. ccxt/cryptocom.py +5 -0
  149. ccxt/currencycom.py +3 -0
  150. ccxt/defx.py +5 -0
  151. ccxt/delta.py +4 -1
  152. ccxt/deribit.py +15 -28
  153. ccxt/digifinex.py +10 -5
  154. ccxt/ellipx.py +9 -5
  155. ccxt/exmo.py +7 -4
  156. ccxt/gate.py +5 -1
  157. ccxt/gemini.py +3 -0
  158. ccxt/hashkey.py +5 -4
  159. ccxt/hitbtc.py +6 -2
  160. ccxt/hollaex.py +7 -2
  161. ccxt/htx.py +8 -1
  162. ccxt/huobijp.py +5 -0
  163. ccxt/hyperliquid.py +9 -4
  164. ccxt/idex.py +5 -1
  165. ccxt/independentreserve.py +4 -0
  166. ccxt/indodax.py +3 -0
  167. ccxt/kraken.py +7 -5
  168. ccxt/krakenfutures.py +5 -2
  169. ccxt/kucoin.py +13 -6
  170. ccxt/kucoinfutures.py +5 -1
  171. ccxt/kuna.py +3 -0
  172. ccxt/latoken.py +4 -0
  173. ccxt/lbank.py +6 -1
  174. ccxt/luno.py +6 -1
  175. ccxt/mercado.py +4 -0
  176. ccxt/mexc.py +10 -9
  177. ccxt/ndax.py +6 -1
  178. ccxt/novadax.py +5 -0
  179. ccxt/oceanex.py +6 -2
  180. ccxt/okcoin.py +4 -0
  181. ccxt/okx.py +17 -5
  182. ccxt/onetrading.py +4 -0
  183. ccxt/oxfun.py +3 -0
  184. ccxt/p2b.py +3 -0
  185. ccxt/paradex.py +8 -2
  186. ccxt/phemex.py +10 -4
  187. ccxt/poloniex.py +6 -3
  188. ccxt/poloniexfutures.py +5 -1
  189. ccxt/pro/__init__.py +1 -1
  190. ccxt/pro/binance.py +2 -2
  191. ccxt/pro/bitcoincom.py +1 -4
  192. ccxt/pro/bitget.py +3 -3
  193. ccxt/pro/bitopro.py +1 -1
  194. ccxt/pro/bybit.py +7 -2
  195. ccxt/pro/cex.py +1 -1
  196. ccxt/pro/coincatch.py +3 -3
  197. ccxt/pro/mexc.py +3 -3
  198. ccxt/pro/okx.py +1 -1
  199. ccxt/probit.py +4 -0
  200. ccxt/test/tests_async.py +57 -30
  201. ccxt/test/tests_sync.py +57 -30
  202. ccxt/timex.py +4 -0
  203. ccxt/tokocrypto.py +5 -0
  204. ccxt/tradeogre.py +2 -0
  205. ccxt/upbit.py +5 -2
  206. ccxt/vertex.py +6 -2
  207. ccxt/wavesexchange.py +20 -3
  208. ccxt/wazirx.py +2 -0
  209. ccxt/whitebit.py +5 -4
  210. ccxt/woo.py +15 -5
  211. ccxt/woofipro.py +23 -9
  212. ccxt/xt.py +5 -0
  213. ccxt/yobit.py +5 -2
  214. ccxt/zaif.py +2 -0
  215. ccxt/zonda.py +2 -0
  216. {ccxt-4.4.52.dist-info → ccxt-4.4.57.dist-info}/METADATA +225 -143
  217. {ccxt-4.4.52.dist-info → ccxt-4.4.57.dist-info}/RECORD +220 -223
  218. ccxt/abstract/lykke.py +0 -29
  219. ccxt/async_support/lykke.py +0 -1370
  220. ccxt/lykke.py +0 -1370
  221. {ccxt-4.4.52.dist-info → ccxt-4.4.57.dist-info}/LICENSE.txt +0 -0
  222. {ccxt-4.4.52.dist-info → ccxt-4.4.57.dist-info}/WHEEL +0 -0
  223. {ccxt-4.4.52.dist-info → ccxt-4.4.57.dist-info}/top_level.txt +0 -0
@@ -341,17 +341,20 @@ class woofipro(Exchange, ImplicitAPI):
341
341
  'limit': 500,
342
342
  'daysBack': None,
343
343
  'untilDays': 100000,
344
+ 'symbolRequired': False,
344
345
  },
345
346
  'fetchOrder': {
346
347
  'marginMode': False,
347
348
  'trigger': True,
348
349
  'trailing': False,
350
+ 'symbolRequired': False,
349
351
  },
350
352
  'fetchOpenOrders': {
351
353
  'marginMode': False,
352
354
  'limit': 500,
353
355
  'trigger': True,
354
356
  'trailing': False,
357
+ 'symbolRequired': False,
355
358
  },
356
359
  'fetchOrders': None,
357
360
  'fetchClosedOrders': {
@@ -362,6 +365,7 @@ class woofipro(Exchange, ImplicitAPI):
362
365
  'untilDays': 100000,
363
366
  'trigger': True,
364
367
  'trailing': False,
368
+ 'symbolRequired': False,
365
369
  },
366
370
  'fetchOHLCV': {
367
371
  'limit': 1000,
@@ -1384,6 +1388,7 @@ class woofipro(Exchange, ImplicitAPI):
1384
1388
  'algo_type': 'POSITIONAL_TP_SL',
1385
1389
  'child_orders': [],
1386
1390
  }
1391
+ childOrders = outterOrder['child_orders']
1387
1392
  closeSide = 'SELL' if (orderSide == 'BUY') else 'BUY'
1388
1393
  if stopLoss is not None:
1389
1394
  stopLossPrice = self.safe_number_2(stopLoss, 'triggerPrice', 'price', stopLoss)
@@ -1394,7 +1399,7 @@ class woofipro(Exchange, ImplicitAPI):
1394
1399
  'type': 'LIMIT',
1395
1400
  'reduce_only': True,
1396
1401
  }
1397
- outterOrder['child_orders'].append(stopLossOrder)
1402
+ childOrders.append(stopLossOrder)
1398
1403
  if takeProfit is not None:
1399
1404
  takeProfitPrice = self.safe_number_2(takeProfit, 'triggerPrice', 'price', takeProfit)
1400
1405
  takeProfitOrder: dict = {
@@ -1404,7 +1409,7 @@ class woofipro(Exchange, ImplicitAPI):
1404
1409
  'type': 'LIMIT',
1405
1410
  'reduce_only': True,
1406
1411
  }
1407
- outterOrder['child_orders'].append(takeProfitOrder)
1412
+ outterOrder.append(takeProfitOrder)
1408
1413
  request['child_orders'] = [outterOrder]
1409
1414
  params = self.omit(params, ['reduceOnly', 'reduce_only', 'clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLoss', 'takeProfit'])
1410
1415
  return self.extend(request, params)
@@ -1502,7 +1507,7 @@ class woofipro(Exchange, ImplicitAPI):
1502
1507
  takeProfit = self.safe_value(orderParams, 'takeProfit')
1503
1508
  isConditional = triggerPrice is not None or stopLoss is not None or takeProfit is not None or (self.safe_value(orderParams, 'childOrders') is not None)
1504
1509
  if isConditional:
1505
- raise NotSupported(self.id + 'createOrders() only support non-stop order')
1510
+ raise NotSupported(self.id + ' createOrders() only support non-stop order')
1506
1511
  orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
1507
1512
  ordersRequests.append(orderRequest)
1508
1513
  request: dict = {
@@ -1774,7 +1779,9 @@ class woofipro(Exchange, ImplicitAPI):
1774
1779
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1775
1780
  """
1776
1781
  await self.load_markets()
1777
- market = self.market(symbol) if (symbol is not None) else None
1782
+ market = None
1783
+ if symbol is not None:
1784
+ market = self.market(symbol)
1778
1785
  trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
1779
1786
  request: dict = {}
1780
1787
  clientOrderId = self.safe_string_n(params, ['clOrdID', 'clientOrderId', 'client_order_id'])
@@ -2192,7 +2199,9 @@ class woofipro(Exchange, ImplicitAPI):
2192
2199
  :param dict [params]: extra parameters specific to the exchange API endpoint
2193
2200
  :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
2194
2201
  """
2195
- currency, rows = await self.get_asset_history_rows(code, since, limit, params)
2202
+ currencyRows = await self.get_asset_history_rows(code, since, limit, params)
2203
+ currency = self.safe_value(currencyRows, 0)
2204
+ rows = self.safe_list(currencyRows, 1)
2196
2205
  return self.parse_ledger(rows, currency, since, limit, params)
2197
2206
 
2198
2207
  def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
@@ -2285,7 +2294,9 @@ class woofipro(Exchange, ImplicitAPI):
2285
2294
  :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2286
2295
  """
2287
2296
  request: dict = {}
2288
- currency, rows = await self.get_asset_history_rows(code, since, limit, self.extend(request, params))
2297
+ currencyRows = await self.get_asset_history_rows(code, since, limit, self.extend(request, params))
2298
+ currency = self.safe_value(currencyRows, 0)
2299
+ rows = self.safe_list(currencyRows, 1)
2289
2300
  #
2290
2301
  # {
2291
2302
  # "rows":[],
@@ -2344,7 +2355,7 @@ class woofipro(Exchange, ImplicitAPI):
2344
2355
  if code is not None:
2345
2356
  code = code.upper()
2346
2357
  if code != 'USDC':
2347
- raise NotSupported(self.id + 'withdraw() only support USDC')
2358
+ raise NotSupported(self.id + ' withdraw() only support USDC')
2348
2359
  currency = self.currency(code)
2349
2360
  verifyingContractAddress = self.safe_string(self.options, 'verifyingContractAddress')
2350
2361
  chainId = self.safe_string(params, 'chainId')
@@ -2544,7 +2555,7 @@ class woofipro(Exchange, ImplicitAPI):
2544
2555
  'takeProfitPrice': None,
2545
2556
  })
2546
2557
 
2547
- async def fetch_position(self, symbol: Str = None, params={}):
2558
+ async def fetch_position(self, symbol: Str, params={}):
2548
2559
  """
2549
2560
 
2550
2561
  https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-one-position-info
@@ -2674,9 +2685,12 @@ class woofipro(Exchange, ImplicitAPI):
2674
2685
  auth = ''
2675
2686
  ts = str(self.nonce())
2676
2687
  url += pathWithParams
2688
+ apiKey = self.apiKey
2689
+ if apiKey.find('ed25519:') < 0:
2690
+ apiKey = 'ed25519:' + apiKey
2677
2691
  headers = {
2678
2692
  'orderly-account-id': self.accountId,
2679
- 'orderly-key': self.apiKey,
2693
+ 'orderly-key': apiKey,
2680
2694
  'orderly-timestamp': ts,
2681
2695
  }
2682
2696
  auth = ts + method + '/' + version + '/' + pathWithParams
ccxt/async_support/xt.py CHANGED
@@ -721,6 +721,7 @@ class xt(Exchange, ImplicitAPI):
721
721
  'untilDays': 100000, # todo
722
722
  'marketType': True,
723
723
  'subType': True,
724
+ 'symbolRequired': False,
724
725
  },
725
726
  'fetchOrder': {
726
727
  'marginMode': False,
@@ -728,6 +729,7 @@ class xt(Exchange, ImplicitAPI):
728
729
  'trailing': False,
729
730
  'marketType': True,
730
731
  'subType': True,
732
+ 'symbolRequired': False,
731
733
  },
732
734
  'fetchOpenOrders': {
733
735
  'marginMode': True,
@@ -736,6 +738,7 @@ class xt(Exchange, ImplicitAPI):
736
738
  'trailing': False,
737
739
  'marketType': True,
738
740
  'subType': True,
741
+ 'symbolRequired': False,
739
742
  },
740
743
  'fetchOrders': {
741
744
  'marginMode': True,
@@ -746,6 +749,7 @@ class xt(Exchange, ImplicitAPI):
746
749
  'trailing': False,
747
750
  'marketType': True,
748
751
  'subType': True,
752
+ 'symbolRequired': False,
749
753
  },
750
754
  'fetchClosedOrders': {
751
755
  'marginMode': True,
@@ -757,6 +761,7 @@ class xt(Exchange, ImplicitAPI):
757
761
  'trailing': False,
758
762
  'marketType': True,
759
763
  'subType': True,
764
+ 'symbolRequired': False,
760
765
  },
761
766
  'fetchOHLCV': {
762
767
  'limit': 1000, # todo for derivatives
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.yobit import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Balances, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction
10
+ from ccxt.base.types import Balances, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, OrderBooks, Trade, TradingFees, Transaction
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -351,17 +351,20 @@ class yobit(Exchange, ImplicitAPI):
351
351
  'limit': 1000,
352
352
  'daysBack': 100000, # todo
353
353
  'untilDays': 100000, # todo
354
+ 'symbolRequired': True,
354
355
  },
355
356
  'fetchOrder': {
356
357
  'marginMode': False,
357
358
  'trigger': False,
358
359
  'trailing': False,
360
+ 'symbolRequired': False,
359
361
  },
360
362
  'fetchOpenOrders': {
361
363
  'marginMode': False,
362
364
  'limit': None,
363
365
  'trigger': False,
364
366
  'trailing': False,
367
+ 'symbolRequired': True,
365
368
  },
366
369
  'fetchOrders': None,
367
370
  'fetchClosedOrders': None,
@@ -558,7 +561,7 @@ class yobit(Exchange, ImplicitAPI):
558
561
  orderbook = response[market['id']]
559
562
  return self.parse_order_book(orderbook, symbol)
560
563
 
561
- async def fetch_order_books(self, symbols: Strings = None, limit: Int = None, params={}):
564
+ async def fetch_order_books(self, symbols: Strings = None, limit: Int = None, params={}) -> OrderBooks:
562
565
  """
563
566
 
564
567
  https://yobit.net/en/api
@@ -166,6 +166,7 @@ class zaif(Exchange, ImplicitAPI):
166
166
  'limit': None,
167
167
  'trigger': False,
168
168
  'trailing': False,
169
+ 'symbolRequired': False,
169
170
  },
170
171
  'fetchOrders': None, # todo
171
172
  'fetchClosedOrders': {
@@ -176,6 +177,7 @@ class zaif(Exchange, ImplicitAPI):
176
177
  'untilDays': 100000, # todo
177
178
  'trigger': False,
178
179
  'trailing': False,
180
+ 'symbolRequired': False,
179
181
  },
180
182
  'fetchOHLCV': None,
181
183
  },
@@ -334,6 +334,7 @@ class zonda(Exchange, ImplicitAPI):
334
334
  'limit': None,
335
335
  'daysBack': 100000, # todo
336
336
  'untilDays': 100000, # todo
337
+ 'symbolRequired': False,
337
338
  },
338
339
  'fetchOrder': None,
339
340
  'fetchOpenOrders': {
@@ -341,6 +342,7 @@ class zonda(Exchange, ImplicitAPI):
341
342
  'limit': 100,
342
343
  'trigger': False,
343
344
  'trailing': False,
345
+ 'symbolRequired': False,
344
346
  },
345
347
  'fetchOrders': None,
346
348
  'fetchClosedOrders': None, # todo
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.52'
7
+ __version__ = '4.4.57'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2361,9 +2361,17 @@ class Exchange(object):
2361
2361
  if fromStart:
2362
2362
  if limit > arrayLength:
2363
2363
  limit = arrayLength
2364
- array = self.array_slice(array, 0, limit) if ascending else self.array_slice(array, -limit)
2364
+ # array = self.array_slice(array, 0, limit) if ascending else self.array_slice(array, -limit)
2365
+ if ascending:
2366
+ array = self.array_slice(array, 0, limit)
2367
+ else:
2368
+ array = self.array_slice(array, -limit)
2365
2369
  else:
2366
- array = self.array_slice(array, -limit) if ascending else self.array_slice(array, 0, limit)
2370
+ # array = self.array_slice(array, -limit) if ascending else self.array_slice(array, 0, limit)
2371
+ if ascending:
2372
+ array = self.array_slice(array, -limit)
2373
+ else:
2374
+ array = self.array_slice(array, 0, limit)
2367
2375
  return array
2368
2376
 
2369
2377
  def filter_by_since_limit(self, array: List[object], since: Int = None, limit: Int = None, key: IndexType = 'timestamp', tail=False):
@@ -2741,36 +2749,17 @@ class Exchange(object):
2741
2749
 
2742
2750
  def features_generator(self):
2743
2751
  #
2744
- # the exchange-specific features can be something like self, where we support 'string' aliases too:
2752
+ # in the exchange-specific features can be something like self, where we support 'string' aliases too:
2745
2753
  #
2746
2754
  # {
2747
- # 'myItem' : {
2755
+ # 'my' : {
2748
2756
  # 'createOrder' : {...},
2749
- # 'fetchOrders' : {...},
2750
2757
  # },
2751
2758
  # 'swap': {
2752
- # 'linear': 'myItem',
2753
- # 'inverse': 'myItem',
2754
- # },
2755
- # 'future': {
2756
- # 'linear': 'myItem',
2757
- # 'inverse': 'myItem',
2758
- # }
2759
- # }
2760
- #
2761
- #
2762
- #
2763
- # self method would regenerate the blank features tree, eg:
2764
- #
2765
- # {
2766
- # "spot": {
2767
- # "createOrder": None,
2768
- # "fetchBalance": None,
2769
- # ...
2759
+ # 'linear': {
2760
+ # 'extends': my',
2761
+ # },
2770
2762
  # },
2771
- # "swap": {
2772
- # ...
2773
- # }
2774
2763
  # }
2775
2764
  #
2776
2765
  if self.features is None:
@@ -2806,13 +2795,13 @@ class Exchange(object):
2806
2795
  extendObj = self.features_mapper(initialFeatures, extendsStr)
2807
2796
  featuresObj = self.deep_extend(extendObj, featuresObj)
2808
2797
  #
2809
- # corrections
2798
+ # ### corrections ###
2810
2799
  #
2800
+ # createOrder
2811
2801
  if 'createOrder' in featuresObj:
2812
2802
  value = self.safe_dict(featuresObj['createOrder'], 'attachedStopLossTakeProfit')
2813
- if value is not None:
2814
- featuresObj['createOrder']['stopLoss'] = value
2815
- featuresObj['createOrder']['takeProfit'] = value
2803
+ featuresObj['createOrder']['stopLoss'] = value
2804
+ featuresObj['createOrder']['takeProfit'] = value
2816
2805
  if marketType == 'spot':
2817
2806
  # default 'hedged': False
2818
2807
  featuresObj['createOrder']['hedged'] = False
@@ -2822,6 +2811,15 @@ class Exchange(object):
2822
2811
  # default 'GTC' to True
2823
2812
  if self.safe_bool(featuresObj['createOrder']['timeInForce'], 'GTC') is None:
2824
2813
  featuresObj['createOrder']['timeInForce']['GTC'] = True
2814
+ # other methods
2815
+ keys = list(featuresObj.keys())
2816
+ for i in range(0, len(keys)):
2817
+ key = keys[i]
2818
+ featureBlock = featuresObj[key]
2819
+ if not self.in_array(key, ['sandbox']) and featureBlock is not None:
2820
+ # default "symbolRequired" to False to all methods(except `createOrder`)
2821
+ if not ('symbolRequired' in featureBlock):
2822
+ featureBlock['symbolRequired'] = self.in_array(key, ['createOrder', 'createOrders', 'fetchOHLCV'])
2825
2823
  return featuresObj
2826
2824
 
2827
2825
  def orderbook_checksum_message(self, symbol: Str):
@@ -3058,7 +3056,9 @@ class Exchange(object):
3058
3056
  for i in range(0, len(marketValues)):
3059
3057
  value = marketValues[i]
3060
3058
  if value['id'] in self.markets_by_id:
3061
- (self.markets_by_id[value['id']]).append(value)
3059
+ marketsByIdArray = (self.markets_by_id[value['id']])
3060
+ marketsByIdArray.append(value)
3061
+ self.markets_by_id[value['id']] = marketsByIdArray
3062
3062
  else:
3063
3063
  self.markets_by_id[value['id']] = [value]
3064
3064
  market = self.deep_extend(self.safe_market_structure(), {
@@ -3413,13 +3413,16 @@ class Exchange(object):
3413
3413
  results = []
3414
3414
  if isinstance(orders, list):
3415
3415
  for i in range(0, len(orders)):
3416
- order = self.extend(self.parse_order(orders[i], market), params)
3416
+ parsed = self.parse_order(orders[i], market) # don't inline self call
3417
+ order = self.extend(parsed, params)
3417
3418
  results.append(order)
3418
3419
  else:
3419
3420
  ids = list(orders.keys())
3420
3421
  for i in range(0, len(ids)):
3421
3422
  id = ids[i]
3422
- order = self.extend(self.parse_order(self.extend({'id': id}, orders[id]), market), params)
3423
+ idExtended = self.extend({'id': id}, orders[id])
3424
+ parsedOrder = self.parse_order(idExtended, market) # don't inline these calls
3425
+ order = self.extend(parsedOrder, params)
3423
3426
  results.append(order)
3424
3427
  results = self.sort_by(results, 'timestamp')
3425
3428
  symbol = market['symbol'] if (market is not None) else None
@@ -3768,12 +3771,18 @@ class Exchange(object):
3768
3771
  result[volume] = []
3769
3772
  for i in range(0, len(ohlcvs)):
3770
3773
  ts = ohlcvs[i][0] if ms else self.parse_to_int(ohlcvs[i][0] / 1000)
3771
- result[timestamp].append(ts)
3772
- result[open].append(ohlcvs[i][1])
3773
- result[high].append(ohlcvs[i][2])
3774
- result[low].append(ohlcvs[i][3])
3775
- result[close].append(ohlcvs[i][4])
3776
- result[volume].append(ohlcvs[i][5])
3774
+ resultTimestamp = result[timestamp]
3775
+ resultTimestamp.append(ts)
3776
+ resultOpen = result[open]
3777
+ resultOpen.append(ohlcvs[i][1])
3778
+ resultHigh = result[high]
3779
+ resultHigh.append(ohlcvs[i][2])
3780
+ resultLow = result[low]
3781
+ resultLow.append(ohlcvs[i][3])
3782
+ resultClose = result[close]
3783
+ resultClose.append(ohlcvs[i][4])
3784
+ resultVolume = result[volume]
3785
+ resultVolume.append(ohlcvs[i][5])
3777
3786
  return result
3778
3787
 
3779
3788
  def fetch_web_endpoint(self, method, endpointMethod, returnAsJson, startRegex=None, endRegex=None):
@@ -3787,14 +3796,18 @@ class Exchange(object):
3787
3796
  maxRetries = self.safe_value(options, 'webApiRetries', 10)
3788
3797
  response = None
3789
3798
  retry = 0
3799
+ shouldBreak = False
3790
3800
  while(retry < maxRetries):
3791
3801
  try:
3792
3802
  response = getattr(self, endpointMethod)({})
3803
+ shouldBreak = True
3793
3804
  break
3794
3805
  except Exception as e:
3795
3806
  retry = retry + 1
3796
3807
  if retry == maxRetries:
3797
3808
  raise e
3809
+ if shouldBreak:
3810
+ break # self is needed because of GO
3798
3811
  content = response
3799
3812
  if startRegex is not None:
3800
3813
  splitted_by_start = content.split(startRegex)
@@ -4274,12 +4287,19 @@ class Exchange(object):
4274
4287
  objects = self.to_array(objects)
4275
4288
  # return all of them if no values were passed
4276
4289
  if values is None or not values:
4277
- return self.index_by(objects, key) if indexed else objects
4290
+ # return self.index_by(objects, key) if indexed else objects
4291
+ if indexed:
4292
+ return self.index_by(objects, key)
4293
+ else:
4294
+ return objects
4278
4295
  results = []
4279
4296
  for i in range(0, len(objects)):
4280
4297
  if self.in_array(objects[i][key], values):
4281
4298
  results.append(objects[i])
4282
- return self.index_by(results, key) if indexed else results
4299
+ # return self.index_by(results, key) if indexed else results
4300
+ if indexed:
4301
+ return self.index_by(results, key)
4302
+ return results
4283
4303
 
4284
4304
  def fetch2(self, path, api: Any = 'public', method='GET', params={}, headers: Any = None, body: Any = None, config={}):
4285
4305
  if self.enableRateLimit:
@@ -4304,8 +4324,9 @@ class Exchange(object):
4304
4324
  self.log('Request failed with the error: ' + str(e) + ', retrying ' + (i + str(1)) + ' of ' + str(retries) + '...')
4305
4325
  if (retryDelay is not None) and (retryDelay != 0):
4306
4326
  self.sleep(retryDelay)
4307
- continue
4308
- raise e
4327
+ # continue #check self
4328
+ if i >= retries:
4329
+ raise e
4309
4330
  return None # self line is never reached, but exists for c# value return requirement
4310
4331
 
4311
4332
  def request(self, path, api: Any = 'public', method='GET', params={}, headers: Any = None, body: Any = None, config={}):
@@ -4464,7 +4485,7 @@ class Exchange(object):
4464
4485
  'precision': None,
4465
4486
  })
4466
4487
 
4467
- def safe_market(self, marketId: Str, market: Market = None, delimiter: Str = None, marketType: Str = None):
4488
+ def safe_market(self, marketId: Str = None, market: Market = None, delimiter: Str = None, marketType: Str = None):
4468
4489
  result = self.safe_market_structure({
4469
4490
  'symbol': marketId,
4470
4491
  'marketId': marketId,
@@ -4629,9 +4650,8 @@ class Exchange(object):
4629
4650
  return [value2, params]
4630
4651
 
4631
4652
  def handle_option(self, methodName: str, optionName: str, defaultValue=None):
4632
- # eslint-disable-next-line no-unused-vars
4633
- result, empty = self.handle_option_and_params({}, methodName, optionName, defaultValue)
4634
- return result
4653
+ res = self.handle_option_and_params({}, methodName, optionName, defaultValue)
4654
+ return self.safe_value(res, 0)
4635
4655
 
4636
4656
  def handle_market_type_and_params(self, methodName: str, market: Market = None, params={}, defaultValue=None):
4637
4657
  """
@@ -4801,6 +4821,18 @@ class Exchange(object):
4801
4821
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
4802
4822
  raise NotSupported(self.id + ' createOrder() is not supported yet')
4803
4823
 
4824
+ def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}):
4825
+ raise NotSupported(self.id + ' createConvertTrade() is not supported yet')
4826
+
4827
+ def fetch_convert_trade(self, id: str, code: Str = None, params={}):
4828
+ raise NotSupported(self.id + ' fetchConvertTrade() is not supported yet')
4829
+
4830
+ def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
4831
+ raise NotSupported(self.id + ' fetchConvertTradeHistory() is not supported yet')
4832
+
4833
+ def fetch_position_mode(self, symbol: Str = None, params={}):
4834
+ raise NotSupported(self.id + ' fetchPositionMode() is not supported yet')
4835
+
4804
4836
  def create_trailing_amount_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount=None, trailingTriggerPrice=None, params={}):
4805
4837
  """
4806
4838
  create a trailing order by providing the symbol, type, side, amount, price and trailingAmount
@@ -5392,10 +5424,14 @@ class Exchange(object):
5392
5424
  return self.create_order_ws(symbol, 'market', 'sell', amount, None, params)
5393
5425
 
5394
5426
  def cost_to_precision(self, symbol: str, cost):
5427
+ if cost is None:
5428
+ return None
5395
5429
  market = self.market(symbol)
5396
5430
  return self.decimal_to_precision(cost, TRUNCATE, market['precision']['price'], self.precisionMode, self.paddingMode)
5397
5431
 
5398
5432
  def price_to_precision(self, symbol: str, price):
5433
+ if price is None:
5434
+ return None
5399
5435
  market = self.market(symbol)
5400
5436
  result = self.decimal_to_precision(price, ROUND, market['precision']['price'], self.precisionMode, self.paddingMode)
5401
5437
  if result == '0':
@@ -5403,6 +5439,8 @@ class Exchange(object):
5403
5439
  return result
5404
5440
 
5405
5441
  def amount_to_precision(self, symbol: str, amount):
5442
+ if amount is None:
5443
+ return None
5406
5444
  market = self.market(symbol)
5407
5445
  result = self.decimal_to_precision(amount, TRUNCATE, market['precision']['amount'], self.precisionMode, self.paddingMode)
5408
5446
  if result == '0':
@@ -5410,6 +5448,8 @@ class Exchange(object):
5410
5448
  return result
5411
5449
 
5412
5450
  def fee_to_precision(self, symbol: str, fee):
5451
+ if fee is None:
5452
+ return None
5413
5453
  market = self.market(symbol)
5414
5454
  return self.decimal_to_precision(fee, ROUND, market['precision']['price'], self.precisionMode, self.paddingMode)
5415
5455
 
@@ -5504,25 +5544,25 @@ class Exchange(object):
5504
5544
 
5505
5545
  def create_post_only_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
5506
5546
  if not self.has['createPostOnlyOrder']:
5507
- raise NotSupported(self.id + 'createPostOnlyOrder() is not supported yet')
5547
+ raise NotSupported(self.id + ' createPostOnlyOrder() is not supported yet')
5508
5548
  query = self.extend(params, {'postOnly': True})
5509
5549
  return self.create_order(symbol, type, side, amount, price, query)
5510
5550
 
5511
5551
  def create_post_only_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
5512
5552
  if not self.has['createPostOnlyOrderWs']:
5513
- raise NotSupported(self.id + 'createPostOnlyOrderWs() is not supported yet')
5553
+ raise NotSupported(self.id + ' createPostOnlyOrderWs() is not supported yet')
5514
5554
  query = self.extend(params, {'postOnly': True})
5515
5555
  return self.create_order_ws(symbol, type, side, amount, price, query)
5516
5556
 
5517
5557
  def create_reduce_only_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
5518
5558
  if not self.has['createReduceOnlyOrder']:
5519
- raise NotSupported(self.id + 'createReduceOnlyOrder() is not supported yet')
5559
+ raise NotSupported(self.id + ' createReduceOnlyOrder() is not supported yet')
5520
5560
  query = self.extend(params, {'reduceOnly': True})
5521
5561
  return self.create_order(symbol, type, side, amount, price, query)
5522
5562
 
5523
5563
  def create_reduce_only_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
5524
5564
  if not self.has['createReduceOnlyOrderWs']:
5525
- raise NotSupported(self.id + 'createReduceOnlyOrderWs() is not supported yet')
5565
+ raise NotSupported(self.id + ' createReduceOnlyOrderWs() is not supported yet')
5526
5566
  query = self.extend(params, {'reduceOnly': True})
5527
5567
  return self.create_order_ws(symbol, type, side, amount, price, query)
5528
5568
 
@@ -5641,14 +5681,16 @@ class Exchange(object):
5641
5681
  results = []
5642
5682
  if isinstance(tickers, list):
5643
5683
  for i in range(0, len(tickers)):
5644
- ticker = self.extend(self.parse_ticker(tickers[i]), params)
5684
+ parsedTicker = self.parse_ticker(tickers[i])
5685
+ ticker = self.extend(parsedTicker, params)
5645
5686
  results.append(ticker)
5646
5687
  else:
5647
5688
  marketIds = list(tickers.keys())
5648
5689
  for i in range(0, len(marketIds)):
5649
5690
  marketId = marketIds[i]
5650
5691
  market = self.safe_market(marketId)
5651
- ticker = self.extend(self.parse_ticker(tickers[marketId], market), params)
5692
+ parsed = self.parse_ticker(tickers[marketId], market)
5693
+ ticker = self.extend(parsed, params)
5652
5694
  results.append(ticker)
5653
5695
  symbols = self.market_symbols(symbols)
5654
5696
  return self.filter_by_array(results, 'symbol', symbols)
ccxt/base/types.py CHANGED
@@ -278,7 +278,7 @@ class Ticker(TypedDict):
278
278
 
279
279
  Tickers = Dict[str, Ticker]
280
280
 
281
-
281
+ OrderBooks = Dict[str, OrderBook]
282
282
  class MarginMode(TypedDict):
283
283
  info: Dict[str, Any]
284
284
  symbol: Str
ccxt/bigone.py CHANGED
@@ -336,17 +336,20 @@ class bigone(Exchange, ImplicitAPI):
336
336
  'limit': 200,
337
337
  'daysBack': None,
338
338
  'untilDays': None,
339
+ 'symbolRequired': True,
339
340
  },
340
341
  'fetchOrder': {
341
342
  'marginMode': False,
342
343
  'trigger': False,
343
344
  'trailing': False,
345
+ 'symbolRequired': False,
344
346
  },
345
347
  'fetchOpenOrders': {
346
348
  'marginMode': False,
347
349
  'limit': 200,
348
350
  'trigger': False,
349
351
  'trailing': False,
352
+ 'symbolRequired': True,
350
353
  },
351
354
  'fetchOrders': {
352
355
  'marginMode': False,
@@ -355,6 +358,7 @@ class bigone(Exchange, ImplicitAPI):
355
358
  'untilDays': None,
356
359
  'trigger': False,
357
360
  'trailing': False,
361
+ 'symbolRequired': True,
358
362
  },
359
363
  'fetchClosedOrders': {
360
364
  'marginMode': False,
@@ -364,6 +368,7 @@ class bigone(Exchange, ImplicitAPI):
364
368
  'untilDays': None,
365
369
  'trigger': False,
366
370
  'trailing': False,
371
+ 'symbolRequired': True,
367
372
  },
368
373
  'fetchOHLCV': {
369
374
  'limit': 500,