ccxt 4.3.53__py2.py3-none-any.whl → 4.3.55__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 (254) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/kucoin.py +3 -0
  3. ccxt/abstract/kucoinfutures.py +3 -0
  4. ccxt/ace.py +1 -1
  5. ccxt/alpaca.py +1 -1
  6. ccxt/ascendex.py +6 -4
  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 +6 -4
  11. ccxt/async_support/base/exchange.py +1 -1
  12. ccxt/async_support/bigone.py +1 -1
  13. ccxt/async_support/binance.py +6 -6
  14. ccxt/async_support/bingx.py +4 -4
  15. ccxt/async_support/bit2c.py +1 -1
  16. ccxt/async_support/bitbank.py +1 -1
  17. ccxt/async_support/bitbns.py +1 -1
  18. ccxt/async_support/bitfinex.py +1 -1
  19. ccxt/async_support/bitfinex2.py +1 -1
  20. ccxt/async_support/bitflyer.py +1 -1
  21. ccxt/async_support/bitget.py +2 -2
  22. ccxt/async_support/bithumb.py +1 -1
  23. ccxt/async_support/bitmart.py +3 -3
  24. ccxt/async_support/bitmex.py +1 -1
  25. ccxt/async_support/bitopro.py +1 -1
  26. ccxt/async_support/bitrue.py +1 -1
  27. ccxt/async_support/bitso.py +1 -1
  28. ccxt/async_support/bitstamp.py +1 -1
  29. ccxt/async_support/bitteam.py +1 -1
  30. ccxt/async_support/bitvavo.py +2 -2
  31. ccxt/async_support/bl3p.py +1 -1
  32. ccxt/async_support/blockchaincom.py +28 -28
  33. ccxt/async_support/blofin.py +1 -1
  34. ccxt/async_support/btcalpha.py +4 -11
  35. ccxt/async_support/btcbox.py +1 -1
  36. ccxt/async_support/btcmarkets.py +1 -1
  37. ccxt/async_support/btcturk.py +1 -1
  38. ccxt/async_support/bybit.py +2 -2
  39. ccxt/async_support/cex.py +2 -2
  40. ccxt/async_support/coinbase.py +33 -33
  41. ccxt/async_support/coinbaseexchange.py +1 -1
  42. ccxt/async_support/coinbaseinternational.py +1 -1
  43. ccxt/async_support/coincheck.py +1 -1
  44. ccxt/async_support/coinex.py +2 -2
  45. ccxt/async_support/coinlist.py +2 -2
  46. ccxt/async_support/coinmate.py +1 -1
  47. ccxt/async_support/coinmetro.py +1 -1
  48. ccxt/async_support/coinone.py +1 -1
  49. ccxt/async_support/coinsph.py +1 -1
  50. ccxt/async_support/coinspot.py +1 -1
  51. ccxt/async_support/cryptocom.py +1 -1
  52. ccxt/async_support/currencycom.py +1 -1
  53. ccxt/async_support/delta.py +2 -2
  54. ccxt/async_support/deribit.py +4 -4
  55. ccxt/async_support/digifinex.py +2 -2
  56. ccxt/async_support/exmo.py +2 -2
  57. ccxt/async_support/gate.py +2 -2
  58. ccxt/async_support/gemini.py +1 -1
  59. ccxt/async_support/hitbtc.py +1 -1
  60. ccxt/async_support/hollaex.py +1 -1
  61. ccxt/async_support/htx.py +3 -3
  62. ccxt/async_support/huobijp.py +1 -1
  63. ccxt/async_support/hyperliquid.py +2 -2
  64. ccxt/async_support/idex.py +1 -1
  65. ccxt/async_support/independentreserve.py +1 -1
  66. ccxt/async_support/indodax.py +1 -1
  67. ccxt/async_support/kraken.py +2 -2
  68. ccxt/async_support/kucoin.py +127 -46
  69. ccxt/async_support/kucoinfutures.py +1 -1
  70. ccxt/async_support/kuna.py +1 -1
  71. ccxt/async_support/latoken.py +1 -1
  72. ccxt/async_support/lbank.py +1 -1
  73. ccxt/async_support/luno.py +1 -1
  74. ccxt/async_support/lykke.py +1 -1
  75. ccxt/async_support/mercado.py +1 -1
  76. ccxt/async_support/mexc.py +1 -1
  77. ccxt/async_support/ndax.py +1 -1
  78. ccxt/async_support/novadax.py +1 -1
  79. ccxt/async_support/oceanex.py +1 -1
  80. ccxt/async_support/okcoin.py +1 -1
  81. ccxt/async_support/okx.py +3 -3
  82. ccxt/async_support/onetrading.py +1 -1
  83. ccxt/async_support/oxfun.py +2 -2
  84. ccxt/async_support/p2b.py +1 -1
  85. ccxt/async_support/paymium.py +1 -1
  86. ccxt/async_support/phemex.py +30 -3
  87. ccxt/async_support/poloniex.py +6 -4
  88. ccxt/async_support/poloniexfutures.py +1 -1
  89. ccxt/async_support/probit.py +1 -1
  90. ccxt/async_support/timex.py +1 -1
  91. ccxt/async_support/tokocrypto.py +1 -1
  92. ccxt/async_support/tradeogre.py +1 -1
  93. ccxt/async_support/upbit.py +1 -1
  94. ccxt/async_support/vertex.py +2 -2
  95. ccxt/async_support/wavesexchange.py +1 -1
  96. ccxt/async_support/wazirx.py +1 -1
  97. ccxt/async_support/whitebit.py +2 -2
  98. ccxt/async_support/woo.py +31 -23
  99. ccxt/async_support/woofipro.py +3 -3
  100. ccxt/async_support/yobit.py +1 -1
  101. ccxt/async_support/zaif.py +1 -1
  102. ccxt/async_support/zonda.py +1 -1
  103. ccxt/base/exchange.py +1 -1
  104. ccxt/base/types.py +4 -1
  105. ccxt/bigone.py +1 -1
  106. ccxt/binance.py +6 -6
  107. ccxt/bingx.py +4 -4
  108. ccxt/bit2c.py +1 -1
  109. ccxt/bitbank.py +1 -1
  110. ccxt/bitbns.py +1 -1
  111. ccxt/bitfinex.py +1 -1
  112. ccxt/bitfinex2.py +1 -1
  113. ccxt/bitflyer.py +1 -1
  114. ccxt/bitget.py +2 -2
  115. ccxt/bithumb.py +1 -1
  116. ccxt/bitmart.py +3 -3
  117. ccxt/bitmex.py +1 -1
  118. ccxt/bitopro.py +1 -1
  119. ccxt/bitrue.py +1 -1
  120. ccxt/bitso.py +1 -1
  121. ccxt/bitstamp.py +1 -1
  122. ccxt/bitteam.py +1 -1
  123. ccxt/bitvavo.py +2 -2
  124. ccxt/bl3p.py +1 -1
  125. ccxt/blockchaincom.py +28 -28
  126. ccxt/blofin.py +1 -1
  127. ccxt/btcalpha.py +4 -11
  128. ccxt/btcbox.py +1 -1
  129. ccxt/btcmarkets.py +1 -1
  130. ccxt/btcturk.py +1 -1
  131. ccxt/bybit.py +2 -2
  132. ccxt/cex.py +2 -2
  133. ccxt/coinbase.py +33 -33
  134. ccxt/coinbaseexchange.py +1 -1
  135. ccxt/coinbaseinternational.py +1 -1
  136. ccxt/coincheck.py +1 -1
  137. ccxt/coinex.py +2 -2
  138. ccxt/coinlist.py +2 -2
  139. ccxt/coinmate.py +1 -1
  140. ccxt/coinmetro.py +1 -1
  141. ccxt/coinone.py +1 -1
  142. ccxt/coinsph.py +1 -1
  143. ccxt/coinspot.py +1 -1
  144. ccxt/cryptocom.py +1 -1
  145. ccxt/currencycom.py +1 -1
  146. ccxt/delta.py +2 -2
  147. ccxt/deribit.py +4 -4
  148. ccxt/digifinex.py +2 -2
  149. ccxt/exmo.py +2 -2
  150. ccxt/gate.py +2 -2
  151. ccxt/gemini.py +1 -1
  152. ccxt/hitbtc.py +1 -1
  153. ccxt/hollaex.py +1 -1
  154. ccxt/htx.py +3 -3
  155. ccxt/huobijp.py +1 -1
  156. ccxt/hyperliquid.py +2 -2
  157. ccxt/idex.py +1 -1
  158. ccxt/independentreserve.py +1 -1
  159. ccxt/indodax.py +1 -1
  160. ccxt/kraken.py +2 -2
  161. ccxt/kucoin.py +127 -46
  162. ccxt/kucoinfutures.py +1 -1
  163. ccxt/kuna.py +1 -1
  164. ccxt/latoken.py +1 -1
  165. ccxt/lbank.py +1 -1
  166. ccxt/luno.py +1 -1
  167. ccxt/lykke.py +1 -1
  168. ccxt/mercado.py +1 -1
  169. ccxt/mexc.py +1 -1
  170. ccxt/ndax.py +1 -1
  171. ccxt/novadax.py +1 -1
  172. ccxt/oceanex.py +1 -1
  173. ccxt/okcoin.py +1 -1
  174. ccxt/okx.py +3 -3
  175. ccxt/onetrading.py +1 -1
  176. ccxt/oxfun.py +2 -2
  177. ccxt/p2b.py +1 -1
  178. ccxt/paymium.py +1 -1
  179. ccxt/phemex.py +30 -3
  180. ccxt/poloniex.py +6 -4
  181. ccxt/poloniexfutures.py +1 -1
  182. ccxt/pro/__init__.py +1 -1
  183. ccxt/pro/binance.py +3 -3
  184. ccxt/pro/bitvavo.py +2 -2
  185. ccxt/pro/bybit.py +20 -14
  186. ccxt/pro/cex.py +3 -3
  187. ccxt/pro/coinbase.py +22 -1
  188. ccxt/pro/cryptocom.py +1 -1
  189. ccxt/pro/gate.py +2 -2
  190. ccxt/pro/hitbtc.py +1 -1
  191. ccxt/pro/kraken.py +2 -2
  192. ccxt/pro/kucoin.py +65 -28
  193. ccxt/pro/okx.py +2 -2
  194. ccxt/pro/oxfun.py +2 -2
  195. ccxt/pro/poloniex.py +1 -1
  196. ccxt/pro/vertex.py +2 -2
  197. ccxt/probit.py +1 -1
  198. ccxt/test/{test_async.py → tests_async.py} +27 -280
  199. ccxt/test/tests_helpers.py +284 -0
  200. ccxt/test/tests_init.py +35 -0
  201. ccxt/test/{test_sync.py → tests_sync.py} +27 -282
  202. ccxt/timex.py +1 -1
  203. ccxt/tokocrypto.py +1 -1
  204. ccxt/tradeogre.py +1 -1
  205. ccxt/upbit.py +1 -1
  206. ccxt/vertex.py +2 -2
  207. ccxt/wavesexchange.py +1 -1
  208. ccxt/wazirx.py +1 -1
  209. ccxt/whitebit.py +2 -2
  210. ccxt/woo.py +31 -23
  211. ccxt/woofipro.py +3 -3
  212. ccxt/yobit.py +1 -1
  213. ccxt/zaif.py +1 -1
  214. ccxt/zonda.py +1 -1
  215. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/METADATA +5 -5
  216. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/RECORD +219 -252
  217. ccxt/test/base/__init__.py +0 -29
  218. ccxt/test/base/test_account.py +0 -26
  219. ccxt/test/base/test_balance.py +0 -56
  220. ccxt/test/base/test_borrow_interest.py +0 -35
  221. ccxt/test/base/test_borrow_rate.py +0 -32
  222. ccxt/test/base/test_calculate_fee.py +0 -51
  223. ccxt/test/base/test_crypto.py +0 -127
  224. ccxt/test/base/test_currency.py +0 -76
  225. ccxt/test/base/test_datetime.py +0 -109
  226. ccxt/test/base/test_decimal_to_precision.py +0 -392
  227. ccxt/test/base/test_deep_extend.py +0 -68
  228. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  229. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  230. ccxt/test/base/test_funding_rate_history.py +0 -29
  231. ccxt/test/base/test_last_price.py +0 -31
  232. ccxt/test/base/test_ledger_entry.py +0 -45
  233. ccxt/test/base/test_ledger_item.py +0 -48
  234. ccxt/test/base/test_leverage_tier.py +0 -33
  235. ccxt/test/base/test_liquidation.py +0 -50
  236. ccxt/test/base/test_margin_mode.py +0 -24
  237. ccxt/test/base/test_margin_modification.py +0 -35
  238. ccxt/test/base/test_market.py +0 -193
  239. ccxt/test/base/test_number.py +0 -411
  240. ccxt/test/base/test_ohlcv.py +0 -33
  241. ccxt/test/base/test_open_interest.py +0 -32
  242. ccxt/test/base/test_order.py +0 -64
  243. ccxt/test/base/test_order_book.py +0 -69
  244. ccxt/test/base/test_position.py +0 -60
  245. ccxt/test/base/test_shared_methods.py +0 -353
  246. ccxt/test/base/test_status.py +0 -24
  247. ccxt/test/base/test_throttle.py +0 -126
  248. ccxt/test/base/test_ticker.py +0 -92
  249. ccxt/test/base/test_trade.py +0 -47
  250. ccxt/test/base/test_trading_fee.py +0 -26
  251. ccxt/test/base/test_transaction.py +0 -39
  252. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/LICENSE.txt +0 -0
  253. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/WHEEL +0 -0
  254. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/top_level.txt +0 -0
@@ -1,60 +0,0 @@
1
- import os
2
- import sys
3
-
4
- root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
5
- sys.path.append(root)
6
-
7
- # ----------------------------------------------------------------------------
8
-
9
- # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
10
- # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
11
-
12
- # ----------------------------------------------------------------------------
13
- # -*- coding: utf-8 -*-
14
-
15
- from ccxt.test.base import test_shared_methods # noqa E402
16
-
17
- def test_position(exchange, skipped_properties, method, entry, symbol, now):
18
- format = {
19
- 'info': {},
20
- 'symbol': 'XYZ/USDT',
21
- 'timestamp': 1504224000000,
22
- 'datetime': '2017-09-01T00:00:00',
23
- 'initialMargin': exchange.parse_number('1.234'),
24
- 'initialMarginPercentage': exchange.parse_number('0.123'),
25
- 'maintenanceMargin': exchange.parse_number('1.234'),
26
- 'maintenanceMarginPercentage': exchange.parse_number('0.123'),
27
- 'entryPrice': exchange.parse_number('1.234'),
28
- 'notional': exchange.parse_number('1.234'),
29
- 'leverage': exchange.parse_number('1.234'),
30
- 'unrealizedPnl': exchange.parse_number('1.234'),
31
- 'contracts': exchange.parse_number('1'),
32
- 'contractSize': exchange.parse_number('1.234'),
33
- 'marginRatio': exchange.parse_number('1.234'),
34
- 'liquidationPrice': exchange.parse_number('1.234'),
35
- 'markPrice': exchange.parse_number('1.234'),
36
- 'collateral': exchange.parse_number('1.234'),
37
- 'marginMode': 'cross',
38
- 'side': 'long',
39
- 'percentage': exchange.parse_number('1.234'),
40
- }
41
- emptyot_allowed_for = ['liquidationPrice', 'initialMargin', 'initialMarginPercentage', 'maintenanceMargin', 'maintenanceMarginPercentage', 'marginRatio']
42
- test_shared_methods.assert_structure(exchange, skipped_properties, method, entry, format, emptyot_allowed_for)
43
- test_shared_methods.assert_timestamp_and_datetime(exchange, skipped_properties, method, entry, now)
44
- test_shared_methods.assert_symbol(exchange, skipped_properties, method, entry, 'symbol', symbol)
45
- test_shared_methods.assert_in_array(exchange, skipped_properties, method, entry, 'side', ['long', 'short'])
46
- test_shared_methods.assert_in_array(exchange, skipped_properties, method, entry, 'marginMode', ['cross', 'isolated'])
47
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'leverage', '0')
48
- test_shared_methods.assert_less_or_equal(exchange, skipped_properties, method, entry, 'leverage', '200')
49
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'initialMargin', '0')
50
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'initialMarginPercentage', '0')
51
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'maintenanceMargin', '0')
52
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'maintenanceMarginPercentage', '0')
53
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'entryPrice', '0')
54
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'notional', '0')
55
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'contracts', '0')
56
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'contractSize', '0')
57
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'marginRatio', '0')
58
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'liquidationPrice', '0')
59
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'markPrice', '0')
60
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'collateral', '0')
@@ -1,353 +0,0 @@
1
- import os
2
- import sys
3
-
4
- root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
5
- sys.path.append(root)
6
-
7
- # ----------------------------------------------------------------------------
8
-
9
- # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
10
- # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
11
-
12
- # ----------------------------------------------------------------------------
13
- # -*- coding: utf-8 -*-
14
-
15
- from ccxt.base.decimal_to_precision import TICK_SIZE # noqa E402
16
- import numbers # noqa E402
17
- from ccxt.base.precise import Precise # noqa E402
18
- from ccxt.base.errors import OnMaintenance # noqa E402
19
- from ccxt.base.errors import OperationFailed # noqa E402
20
-
21
- def log_template(exchange, method, entry):
22
- return ' <<< ' + exchange.id + ' ' + method + ' ::: ' + exchange.json(entry) + ' >>> '
23
-
24
-
25
- def is_temporary_failure(e):
26
- return (isinstance(e, OperationFailed)) and (not (isinstance(e, OnMaintenance)))
27
-
28
-
29
- def string_value(value):
30
- string_val = None
31
- if isinstance(value, str):
32
- string_val = value
33
- elif value is None:
34
- string_val = 'undefined'
35
- else:
36
- string_val = str(value)
37
- return string_val
38
-
39
-
40
- def assert_type(exchange, skipped_properties, entry, key, format):
41
- if key in skipped_properties:
42
- return None
43
- # because "typeof" string is not transpilable without === 'name', we list them manually at this moment
44
- entry_key_val = exchange.safe_value(entry, key)
45
- format_key_val = exchange.safe_value(format, key)
46
- same_string = (isinstance(entry_key_val, str)) and (isinstance(format_key_val, str))
47
- same_numeric = (isinstance(entry_key_val, numbers.Real)) and (isinstance(format_key_val, numbers.Real))
48
- same_boolean = ((entry_key_val) or (entry_key_val is False)) and ((format_key_val) or (format_key_val is False))
49
- same_array = isinstance(entry_key_val, list) and isinstance(format_key_val, list)
50
- same_object = (isinstance(entry_key_val, dict)) and (isinstance(format_key_val, dict))
51
- result = (entry_key_val is None) or same_string or same_numeric or same_boolean or same_array or same_object
52
- return result
53
-
54
-
55
- def assert_structure(exchange, skipped_properties, method, entry, format, empty_allowed_for=[]):
56
- log_text = log_template(exchange, method, entry)
57
- assert entry, 'item is null/undefined' + log_text
58
- # get all expected & predefined keys for this specific item and ensure thos ekeys exist in parsed structure
59
- if isinstance(format, list):
60
- assert isinstance(entry, list), 'entry is not an array' + log_text
61
- real_length = len(entry)
62
- expected_length = len(format)
63
- assert real_length == expected_length, 'entry length is not equal to expected length of ' + str(expected_length) + log_text
64
- for i in range(0, len(format)):
65
- empty_allowed_for_this_key = exchange.in_array(i, empty_allowed_for)
66
- value = entry[i]
67
- if i in skipped_properties:
68
- continue
69
- # check when:
70
- # - it's not inside "allowe empty values" list
71
- # - it's not undefined
72
- if empty_allowed_for_this_key and (value is None):
73
- continue
74
- assert value is not None, str(i) + ' index is expected to have a value' + log_text
75
- # because of other langs, this is needed for arrays
76
- type_assertion = assert_type(exchange, skipped_properties, entry, i, format)
77
- assert type_assertion, str(i) + ' index does not have an expected type ' + log_text
78
- else:
79
- assert isinstance(entry, dict), 'entry is not an object' + log_text
80
- keys = list(format.keys())
81
- for i in range(0, len(keys)):
82
- key = keys[i]
83
- if key in skipped_properties:
84
- continue
85
- assert key in entry, '\"' + string_value(key) + '\" key is missing from structure' + log_text
86
- if key in skipped_properties:
87
- continue
88
- empty_allowed_for_this_key = exchange.in_array(key, empty_allowed_for)
89
- value = entry[key]
90
- # check when:
91
- # - it's not inside "allowe empty values" list
92
- # - it's not undefined
93
- if empty_allowed_for_this_key and (value is None):
94
- continue
95
- # if it was in needed keys, then it should have value.
96
- assert value is not None, '\"' + string_value(key) + '\" key is expected to have a value' + log_text
97
- # add exclusion for info key, as it can be any type
98
- if key != 'info':
99
- type_assertion = assert_type(exchange, skipped_properties, entry, key, format)
100
- assert type_assertion, '\"' + string_value(key) + '\" key is neither undefined, neither of expected type' + log_text
101
-
102
-
103
- def assert_timestamp(exchange, skipped_properties, method, entry, now_to_check=None, key_name_or_index='timestamp'):
104
- log_text = log_template(exchange, method, entry)
105
- skip_value = exchange.safe_value(skipped_properties, key_name_or_index)
106
- if skip_value is not None:
107
- return # skipped
108
- is_date_time_object = isinstance(key_name_or_index, str)
109
- if is_date_time_object:
110
- assert (key_name_or_index in entry), 'timestamp key \"' + key_name_or_index + '\" is missing from structure' + log_text
111
- else:
112
- # if index was provided (mostly from fetchOHLCV) then we check if it exists, as mandatory
113
- assert not (entry[key_name_or_index] is None), 'timestamp index ' + string_value(key_name_or_index) + ' is undefined' + log_text
114
- ts = entry[key_name_or_index]
115
- if ts is not None:
116
- assert isinstance(ts, numbers.Real), 'timestamp is not numeric' + log_text
117
- assert isinstance(ts, int), 'timestamp should be an integer' + log_text
118
- min_ts = 1230940800000 # 03 Jan 2009 - first block
119
- max_ts = 2147483648000 # 19 Jan 2038 - max int
120
- assert ts > min_ts, 'timestamp is impossible to be before ' + str(min_ts) + ' (03.01.2009)' + log_text # 03 Jan 2009 - first block
121
- assert ts < max_ts, 'timestamp more than ' + str(max_ts) + ' (19.01.2038)' + log_text # 19 Jan 2038 - int32 overflows # 7258118400000 -> Jan 1 2200
122
- if now_to_check is not None:
123
- max_ms_offset = 60000 # 1 min
124
- assert ts < now_to_check + max_ms_offset, 'returned item timestamp (' + exchange.iso8601(ts) + ') is ahead of the current time (' + exchange.iso8601(now_to_check) + ')' + log_text
125
-
126
-
127
- def assert_timestamp_and_datetime(exchange, skipped_properties, method, entry, now_to_check=None, key_name_or_index='timestamp'):
128
- log_text = log_template(exchange, method, entry)
129
- skip_value = exchange.safe_value(skipped_properties, key_name_or_index)
130
- if skip_value is not None:
131
- return
132
- assert_timestamp(exchange, skipped_properties, method, entry, now_to_check, key_name_or_index)
133
- is_date_time_object = isinstance(key_name_or_index, str)
134
- # only in case if the entry is a dictionary, thus it must have 'timestamp' & 'datetime' string keys
135
- if is_date_time_object:
136
- # we also test 'datetime' here because it's certain sibling of 'timestamp'
137
- assert ('datetime' in entry), '\"datetime\" key is missing from structure' + log_text
138
- dt = entry['datetime']
139
- if dt is not None:
140
- assert isinstance(dt, str), '\"datetime\" key does not have a string value' + log_text
141
- # there are exceptional cases, like getting microsecond-targeted string '2022-08-08T22:03:19.014680Z', so parsed unified timestamp, which carries only 13 digits (millisecond precision) can not be stringified back to microsecond accuracy, causing the bellow assertion to fail
142
- # assert (dt === exchange.iso8601 (entry['timestamp']))
143
- # so, we have to compare with millisecond accururacy
144
- dt_parsed = exchange.parse8601(dt)
145
- assert exchange.iso8601(dt_parsed) == exchange.iso8601(entry['timestamp']), 'datetime is not iso8601 of timestamp' + log_text
146
-
147
-
148
- def assert_currency_code(exchange, skipped_properties, method, entry, actual_code, expected_code=None):
149
- if ('currency' in skipped_properties) or ('currencyIdAndCode' in skipped_properties):
150
- return
151
- log_text = log_template(exchange, method, entry)
152
- if actual_code is not None:
153
- assert isinstance(actual_code, str), 'currency code should be either undefined or a string' + log_text
154
- assert (actual_code in exchange.currencies), 'currency code (\"' + actual_code + '\") should be present in exchange.currencies' + log_text
155
- if expected_code is not None:
156
- assert actual_code == expected_code, 'currency code in response (\"' + string_value(actual_code) + '\") should be equal to expected code (\"' + string_value(expected_code) + '\")' + log_text
157
-
158
-
159
- def assert_valid_currency_id_and_code(exchange, skipped_properties, method, entry, currency_id, currency_code):
160
- # this is exclusive exceptional key name to be used in `skip-tests.json`, to skip check for currency id and code
161
- if ('currency' in skipped_properties) or ('currencyIdAndCode' in skipped_properties):
162
- return
163
- log_text = log_template(exchange, method, entry)
164
- undefined_values = currency_id is None and currency_code is None
165
- defined_values = currency_id is not None and currency_code is not None
166
- assert undefined_values or defined_values, 'currencyId and currencyCode should be either both defined or both undefined' + log_text
167
- if defined_values:
168
- # check by code
169
- currency_by_code = exchange.currency(currency_code)
170
- assert currency_by_code['id'] == currency_id, 'currencyId \"' + string_value(currency_id) + '\" does not match currency of code: \"' + string_value(currency_code) + '\"' + log_text
171
- # check by id
172
- currency_by_id = exchange.safe_currency(currency_id)
173
- assert currency_by_id['code'] == currency_code, 'currencyCode ' + string_value(currency_code) + ' does not match currency of id: ' + string_value(currency_id) + log_text
174
-
175
-
176
- def assert_symbol(exchange, skipped_properties, method, entry, key, expected_symbol=None):
177
- if key in skipped_properties:
178
- return
179
- log_text = log_template(exchange, method, entry)
180
- actual_symbol = exchange.safe_string(entry, key)
181
- if actual_symbol is not None:
182
- assert isinstance(actual_symbol, str), 'symbol should be either undefined or a string' + log_text
183
- if expected_symbol is not None:
184
- assert actual_symbol == expected_symbol, 'symbol in response (\"' + string_value(actual_symbol) + '\") should be equal to expected symbol (\"' + string_value(expected_symbol) + '\")' + log_text
185
-
186
-
187
- def assert_symbol_in_markets(exchange, skipped_properties, method, symbol):
188
- log_text = log_template(exchange, method, {})
189
- assert (symbol in exchange.markets), 'symbol should be present in exchange.symbols' + log_text
190
-
191
-
192
- def assert_greater(exchange, skipped_properties, method, entry, key, compare_to):
193
- if key in skipped_properties:
194
- return
195
- log_text = log_template(exchange, method, entry)
196
- value = exchange.safe_string(entry, key)
197
- if value is not None:
198
- assert Precise.string_gt(value, compare_to), string_value(key) + ' key (with a value of ' + string_value(value) + ') was expected to be > ' + string_value(compare_to) + log_text
199
-
200
-
201
- def assert_greater_or_equal(exchange, skipped_properties, method, entry, key, compare_to):
202
- if key in skipped_properties:
203
- return
204
- log_text = log_template(exchange, method, entry)
205
- value = exchange.safe_string(entry, key)
206
- if value is not None and compare_to is not None:
207
- assert Precise.string_ge(value, compare_to), string_value(key) + ' key (with a value of ' + string_value(value) + ') was expected to be >= ' + string_value(compare_to) + log_text
208
-
209
-
210
- def assert_less(exchange, skipped_properties, method, entry, key, compare_to):
211
- if key in skipped_properties:
212
- return
213
- log_text = log_template(exchange, method, entry)
214
- value = exchange.safe_string(entry, key)
215
- if value is not None and compare_to is not None:
216
- assert Precise.string_lt(value, compare_to), string_value(key) + ' key (with a value of ' + string_value(value) + ') was expected to be < ' + string_value(compare_to) + log_text
217
-
218
-
219
- def assert_less_or_equal(exchange, skipped_properties, method, entry, key, compare_to):
220
- if key in skipped_properties:
221
- return
222
- log_text = log_template(exchange, method, entry)
223
- value = exchange.safe_string(entry, key)
224
- if value is not None and compare_to is not None:
225
- assert Precise.string_le(value, compare_to), string_value(key) + ' key (with a value of ' + string_value(value) + ') was expected to be <= ' + string_value(compare_to) + log_text
226
-
227
-
228
- def assert_equal(exchange, skipped_properties, method, entry, key, compare_to):
229
- if key in skipped_properties:
230
- return
231
- log_text = log_template(exchange, method, entry)
232
- value = exchange.safe_string(entry, key)
233
- if value is not None and compare_to is not None:
234
- assert Precise.string_eq(value, compare_to), string_value(key) + ' key (with a value of ' + string_value(value) + ') was expected to be equal to ' + string_value(compare_to) + log_text
235
-
236
-
237
- def assert_non_equal(exchange, skipped_properties, method, entry, key, compare_to):
238
- if key in skipped_properties:
239
- return
240
- log_text = log_template(exchange, method, entry)
241
- value = exchange.safe_string(entry, key)
242
- if value is not None:
243
- assert not Precise.string_eq(value, compare_to), string_value(key) + ' key (with a value of ' + string_value(value) + ') was expected not to be equal to ' + string_value(compare_to) + log_text
244
-
245
-
246
- def assert_in_array(exchange, skipped_properties, method, entry, key, expected_array):
247
- if key in skipped_properties:
248
- return
249
- log_text = log_template(exchange, method, entry)
250
- value = exchange.safe_value(entry, key)
251
- # todo: remove undefined check
252
- if value is not None:
253
- stingified_array_value = exchange.json(expected_array) # don't use expectedArray.join (','), as it bugs in other languages, if values are bool, undefined or etc..
254
- assert exchange.in_array(value, expected_array), '\"' + string_value(key) + '\" key (value \"' + string_value(value) + '\") is not from the expected list : [' + stingified_array_value + ']' + log_text
255
-
256
-
257
- def assert_fee_structure(exchange, skipped_properties, method, entry, key):
258
- log_text = log_template(exchange, method, entry)
259
- key_string = string_value(key)
260
- if isinstance(key, int):
261
- key = key
262
- assert isinstance(entry, list), 'fee container is expected to be an array' + log_text
263
- assert key < len(entry), 'fee key ' + key_string + ' was expected to be present in entry' + log_text
264
- else:
265
- assert isinstance(entry, dict), 'fee container is expected to be an object' + log_text
266
- assert key in entry, 'fee key \"' + key + '\" was expected to be present in entry' + log_text
267
- fee_object = exchange.safe_value(entry, key)
268
- # todo: remove undefined check to make stricter
269
- if fee_object is not None:
270
- assert 'cost' in fee_object, key_string + ' fee object should contain \"cost\" key' + log_text
271
- # assertGreaterOrEqual (exchange, skippedProperties, method, feeObject, 'cost', '0'); # fee might be negative in the case of a rebate or reward
272
- assert 'currency' in fee_object, '\"' + key_string + '\" fee object should contain \"currency\" key' + log_text
273
- assert_currency_code(exchange, skipped_properties, method, entry, fee_object['currency'])
274
-
275
-
276
- def assert_timestamp_order(exchange, method, code_or_symbol, items, ascending=True):
277
- for i in range(0, len(items)):
278
- if i > 0:
279
- current_ts = items[i - 1]['timestamp']
280
- next_ts = items[i]['timestamp']
281
- if current_ts is not None and next_ts is not None:
282
- ascending_or_descending = 'ascending' if ascending else 'descending'
283
- comparison = (current_ts <= next_ts) if ascending else (current_ts >= next_ts)
284
- assert comparison, exchange.id + ' ' + method + ' ' + string_value(code_or_symbol) + ' must return a ' + ascending_or_descending + ' sorted array of items by timestamp, but ' + str(current_ts) + ' is opposite with its next ' + str(next_ts) + ' ' + exchange.json(items)
285
-
286
-
287
- def assert_integer(exchange, skipped_properties, method, entry, key):
288
- if key in skipped_properties:
289
- return
290
- log_text = log_template(exchange, method, entry)
291
- if entry is not None:
292
- value = exchange.safe_value(entry, key)
293
- if value is not None:
294
- is_integer = isinstance(value, int)
295
- assert is_integer, '\"' + string_value(key) + '\" key (value \"' + string_value(value) + '\") is not an integer' + log_text
296
-
297
-
298
- def check_precision_accuracy(exchange, skipped_properties, method, entry, key):
299
- if key in skipped_properties:
300
- return
301
- if exchange.is_tick_precision():
302
- # TICK_SIZE should be above zero
303
- assert_greater(exchange, skipped_properties, method, entry, key, '0')
304
- # the below array of integers are inexistent tick-sizes (theoretically technically possible, but not in real-world cases), so their existence in our case indicates to incorrectly implemented tick-sizes, which might mistakenly be implemented with DECIMAL_PLACES, so we throw error
305
- decimal_numbers = ['2', '3', '4', '6', '7', '8', '9', '11', '12', '13', '14', '15', '16']
306
- for i in range(0, len(decimal_numbers)):
307
- num = decimal_numbers[i]
308
- num_str = num
309
- assert_non_equal(exchange, skipped_properties, method, entry, key, num_str)
310
- else:
311
- assert_integer(exchange, skipped_properties, method, entry, key) # should be integer
312
- assert_less_or_equal(exchange, skipped_properties, method, entry, key, '18') # should be under 18 decimals
313
- assert_greater_or_equal(exchange, skipped_properties, method, entry, key, '-8') # in real-world cases, there would not be less than that
314
-
315
-
316
- def remove_proxy_options(exchange, skipped_properties):
317
- proxy_url = exchange.check_proxy_url_settings()
318
- [http_proxy, https_proxy, socks_proxy] = exchange.check_proxy_settings()
319
- # because of bug in transpiled, about `.proxyUrl` being transpiled into `.proxy_url`, we have to use this workaround
320
- exchange.set_property(exchange, 'proxyUrl', None)
321
- exchange.set_property(exchange, 'proxy_url', None)
322
- exchange.set_property(exchange, 'httpProxy', None)
323
- exchange.set_property(exchange, 'http_proxy', None)
324
- exchange.set_property(exchange, 'httpsProxy', None)
325
- exchange.set_property(exchange, 'https_proxy', None)
326
- exchange.set_property(exchange, 'socksProxy', None)
327
- exchange.set_property(exchange, 'socks_proxy', None)
328
- return [proxy_url, http_proxy, https_proxy, socks_proxy]
329
-
330
-
331
- def set_proxy_options(exchange, skipped_properties, proxy_url, http_proxy, https_proxy, socks_proxy):
332
- exchange.proxy_url = proxy_url
333
- exchange.http_proxy = http_proxy
334
- exchange.https_proxy = https_proxy
335
- exchange.socks_proxy = socks_proxy
336
-
337
-
338
- def assert_non_emtpy_array(exchange, skipped_properties, method, entry, hint=None):
339
- log_text = log_template(exchange, method, entry)
340
- if hint is not None:
341
- log_text = log_text + ' ' + hint
342
- assert isinstance(entry, list), 'response is expected to be an array' + log_text
343
- if not ('emptyResponse' in skipped_properties):
344
- return
345
- assert len(entry) > 0, 'response is expected to be a non-empty array' + log_text + ' (add \"emptyResponse\" in skip-tests.json to skip this check)'
346
-
347
-
348
- def assert_round_minute_timestamp(exchange, skipped_properties, method, entry, key):
349
- if key in skipped_properties:
350
- return
351
- log_text = log_template(exchange, method, entry)
352
- ts = exchange.safe_string(entry, key)
353
- assert Precise.string_mod(ts, '60000') == '0', 'timestamp should be a multiple of 60 seconds (1 minute)' + log_text
@@ -1,24 +0,0 @@
1
- import os
2
- import sys
3
-
4
- root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
5
- sys.path.append(root)
6
-
7
- # ----------------------------------------------------------------------------
8
-
9
- # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
10
- # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
11
-
12
- # ----------------------------------------------------------------------------
13
- # -*- coding: utf-8 -*-
14
-
15
-
16
-
17
- def test_status(exchange, skipped_properties, method, entry, now):
18
- format = {
19
- 'info': {},
20
- 'status': 'ok',
21
- 'updated': 1650000000000,
22
- 'eta': 1660000000000,
23
- 'url': 'https://example.com',
24
- }
@@ -1,126 +0,0 @@
1
- import os
2
- import sys
3
-
4
- root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
5
- sys.path.append(root)
6
-
7
- # ----------------------------------------------------------------------------
8
-
9
- import asyncio # noqa: E402
10
- import time # noqa: E402
11
- from ccxt.async_support.base.throttler import Throttler as Throttle # noqa: E402
12
- # from ccxt.async_support.base.throttle import throttle as Throttle
13
-
14
-
15
- delta = 10
16
-
17
- test_cases = [
18
- {
19
- 'tokens': 0,
20
- 'refillRate': 1 / 50,
21
- 'cost': 1,
22
- 'runs': 100,
23
- },
24
- {
25
- 'tokens': 20,
26
- 'refillRate': 1 / 50,
27
- 'cost': 1,
28
- 'runs': 100,
29
- },
30
- {
31
- 'tokens': 40,
32
- 'refillRate': 1 / 50,
33
- 'cost': 1,
34
- 'runs': 100,
35
- },
36
- {
37
- 'tokens': 0,
38
- 'refillRate': 1 / 20,
39
- 'cost': 1,
40
- 'runs': 100,
41
- },
42
- {
43
- 'tokens': 100,
44
- 'refillRate': 1 / 20,
45
- 'cost': 5,
46
- 'runs': 50,
47
- },
48
- {
49
- 'tokens': 0,
50
- 'refillRate': 1 / 40,
51
- 'cost': 2,
52
- 'runs': 50,
53
- },
54
- {
55
- 'tokens': 1,
56
- 'refillRate': 1 / 100,
57
- 'cost': 1,
58
- 'runs': 10,
59
- },
60
- {
61
- 'tokens': 5,
62
- 'refillRate': 1 / 100,
63
- 'cost': 1,
64
- 'runs': 10,
65
- },
66
- {
67
- 'tokens': 0,
68
- 'refillRate': 1 / 500,
69
- 'cost': 1,
70
- 'runs': 10,
71
- },
72
- {
73
- 'tokens': 0,
74
- 'refillRate': 1 / 10,
75
- 'cost': 1,
76
- 'runs': 500,
77
- },
78
- ]
79
-
80
- # add any more tests you want above
81
-
82
-
83
- for i, case in enumerate(test_cases, 1):
84
- case['number'] = i
85
- # while the tokenBucket has tokens the throttler should return instantly
86
- # so the first tokens / cost runs are deducted
87
- instantly_complete = case['tokens'] / case['cost']
88
- # after that each run will take cost and the total time will be runs * cost / refillRate
89
- remaining = case['runs'] - instantly_complete - 1
90
- case['expected'] = remaining * case['cost'] / case['refillRate']
91
-
92
-
93
- async def schedule(case):
94
- throttle = Throttle({
95
- 'tokens': case['tokens'],
96
- 'refillRate': case['refillRate'],
97
- })
98
- start = time.perf_counter_ns()
99
- for i in range(case['runs']):
100
- await throttle(case['cost'])
101
- end = time.perf_counter_ns()
102
- elapsed_ms = (end - start) / 1000000
103
- result = abs(case['expected'] - elapsed_ms) < delta
104
- print(f'case {case["number"]} {"succeeded" if result else "failed"} in {elapsed_ms}ms expected {case["expected"]}ms')
105
- assert result
106
-
107
-
108
- async def main():
109
- await asyncio.wait([schedule(case) for case in test_cases], return_when=asyncio.ALL_COMPLETED)
110
-
111
-
112
- asyncio.run(main())
113
-
114
- # output
115
-
116
- '''
117
- case 8 succeeded in 501.224333ms expected 500.0ms
118
- case 7 succeeded in 900.647542ms expected 900.0ms
119
- case 4 succeeded in 2000.706958ms expected 2000.0ms
120
- case 5 succeeded in 3001.669125ms expected 3000.0ms
121
- case 3 succeeded in 3001.736666ms expected 3000.0ms
122
- case 6 succeeded in 4001.392584ms expected 4000.0ms
123
- case 2 succeeded in 4001.503833ms expected 4000.0ms
124
- case 9 succeeded in 5001.487ms expected 5000.0ms
125
- case 1 succeeded in 5001.635042ms expected 5000.0ms
126
- '''
@@ -1,92 +0,0 @@
1
- import os
2
- import sys
3
-
4
- root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
5
- sys.path.append(root)
6
-
7
- # ----------------------------------------------------------------------------
8
-
9
- # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
10
- # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
11
-
12
- # ----------------------------------------------------------------------------
13
- # -*- coding: utf-8 -*-
14
-
15
- from ccxt.base.precise import Precise # noqa E402
16
- from ccxt.test.base import test_shared_methods # noqa E402
17
-
18
- def test_ticker(exchange, skipped_properties, method, entry, symbol):
19
- format = {
20
- 'info': {},
21
- 'symbol': 'ETH/BTC',
22
- 'timestamp': 1502962946216,
23
- 'datetime': '2017-09-01T00:00:00',
24
- 'high': exchange.parse_number('1.234'),
25
- 'low': exchange.parse_number('1.234'),
26
- 'bid': exchange.parse_number('1.234'),
27
- 'bidVolume': exchange.parse_number('1.234'),
28
- 'ask': exchange.parse_number('1.234'),
29
- 'askVolume': exchange.parse_number('1.234'),
30
- 'vwap': exchange.parse_number('1.234'),
31
- 'open': exchange.parse_number('1.234'),
32
- 'close': exchange.parse_number('1.234'),
33
- 'last': exchange.parse_number('1.234'),
34
- 'previousClose': exchange.parse_number('1.234'),
35
- 'change': exchange.parse_number('1.234'),
36
- 'percentage': exchange.parse_number('1.234'),
37
- 'average': exchange.parse_number('1.234'),
38
- 'baseVolume': exchange.parse_number('1.234'),
39
- 'quoteVolume': exchange.parse_number('1.234'),
40
- }
41
- # todo: atm, many exchanges fail, so temporarily decrease stict mode
42
- empty_allowed_for = ['timestamp', 'datetime', 'open', 'high', 'low', 'close', 'last', 'baseVolume', 'quoteVolume', 'previousClose', 'vwap', 'change', 'percentage', 'average']
43
- # trick csharp-transpiler for string
44
- if not 'BidsAsks' in str(method):
45
- empty_allowed_for.append('bid')
46
- empty_allowed_for.append('ask')
47
- empty_allowed_for.append('bidVolume')
48
- empty_allowed_for.append('askVolume')
49
- test_shared_methods.assert_structure(exchange, skipped_properties, method, entry, format, empty_allowed_for)
50
- test_shared_methods.assert_timestamp_and_datetime(exchange, skipped_properties, method, entry)
51
- log_text = test_shared_methods.log_template(exchange, method, entry)
52
- #
53
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'open', '0')
54
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'high', '0')
55
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'low', '0')
56
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'close', '0')
57
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'ask', '0')
58
- test_shared_methods.assert_greater_or_equal(exchange, skipped_properties, method, entry, 'askVolume', '0')
59
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'bid', '0')
60
- test_shared_methods.assert_greater_or_equal(exchange, skipped_properties, method, entry, 'bidVolume', '0')
61
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'vwap', '0')
62
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'average', '0')
63
- test_shared_methods.assert_greater_or_equal(exchange, skipped_properties, method, entry, 'baseVolume', '0')
64
- test_shared_methods.assert_greater_or_equal(exchange, skipped_properties, method, entry, 'quoteVolume', '0')
65
- last_string = exchange.safe_string(entry, 'last')
66
- close_string = exchange.safe_string(entry, 'close')
67
- assert ((close_string is None) and (last_string is None)) or Precise.string_eq(last_string, close_string), '`last` != `close`' + log_text
68
- base_volume = exchange.safe_string(entry, 'baseVolume')
69
- quote_volume = exchange.safe_string(entry, 'quoteVolume')
70
- high = exchange.safe_string(entry, 'high')
71
- low = exchange.safe_string(entry, 'low')
72
- if not ('quoteVolume' in skipped_properties) and not ('baseVolume' in skipped_properties):
73
- if (base_volume is not None) and (quote_volume is not None) and (high is not None) and (low is not None):
74
- assert Precise.string_ge(quote_volume, Precise.string_mul(base_volume, low)), 'quoteVolume >= baseVolume * low' + log_text
75
- assert Precise.string_le(quote_volume, Precise.string_mul(base_volume, high)), 'quoteVolume <= baseVolume * high' + log_text
76
- vwap = exchange.safe_string(entry, 'vwap')
77
- if vwap is not None:
78
- # todo
79
- # assert (high !== undefined, 'vwap is defined, but high is not' + logText);
80
- # assert (low !== undefined, 'vwap is defined, but low is not' + logText);
81
- # assert (vwap >= low && vwap <= high)
82
- assert Precise.string_ge(vwap, '0'), 'vwap is not greater than zero' + log_text
83
- if base_volume is not None:
84
- assert quote_volume is not None, 'baseVolume & vwap is defined, but quoteVolume is not' + log_text
85
- if quote_volume is not None:
86
- assert base_volume is not None, 'quoteVolume & vwap is defined, but baseVolume is not' + log_text
87
- if not ('spread' in skipped_properties) and not ('ask' in skipped_properties) and not ('bid' in skipped_properties):
88
- ask_string = exchange.safe_string(entry, 'ask')
89
- bid_string = exchange.safe_string(entry, 'bid')
90
- if (ask_string is not None) and (bid_string is not None):
91
- test_shared_methods.assert_greater(exchange, skipped_properties, method, entry, 'ask', exchange.safe_string(entry, 'bid'))
92
- test_shared_methods.assert_symbol(exchange, skipped_properties, method, entry, 'symbol', symbol)